Skip to main content

FinCrime Transaction Context Guide

This page is the integration surface of the Fraud & Risk Add-on for Agentic Payments. Callers that want financial-crime governance for an agent-initiated transaction attach two documented context objects, fincrime_transaction and fincrime_cohort, to the decision request. The add-on's transaction-aware controls and its risk scoring read these objects. The FinCrime Policy Pack's patterns also scan the request statement, so payment phrasings are governed even on requests that carry no context.

Enterprise add-on

The Fraud & Risk Add-on for Agentic Payments is a separately priced add-on to AxonFlow Enterprise. It is not included in the base Enterprise license, the Evaluation tier, or the source-available Community edition. It requires platform v9.18.0 or later and is currently available through the early-access program.

Where the objects ride

The same two objects are carried differently per request surface:

Request surfaceCarrier
POST /api/v1/decide (Decision Mode)context.fincrime_transaction and context.fincrime_cohort, as top-level keys inside the request context object
POST /mcp/resources/query, POST /mcp/tools/execute, POST /api/v1/mcp/check-input (Agent API)parameters.fincrime_transaction and parameters.fincrime_cohort

All fields in both objects are optional, and the schema is additive: unknown fields are ignored. A request that carries neither key is not a fincrime request: typed validation and risk scoring do not run on it, and there is no context for the pack's context-bound patterns to match in. Its request statement is still scanned by every enabled pack pattern, like every other pattern policy, so a statement that phrases a payment action or happens to carry matching shapes (for example a serialized "amount": 15000) can fire pack policies with no context attached; see the pack reference's false-positive surface section.

On the decision API, the fincrime keys are object-valued entries inside the same context map that also carries audit context propagation. The two mechanisms are independent: audit context propagation forwards allowlisted string values into spans and audit records, while the fincrime objects are consumed by the add-on's governance layers. An object-valued fincrime key is not propagated as an audit context string.

What consumes the objects

Three layers read them, in order:

  1. The FinCrime Policy Pack: deterministic system policies evaluated by the shared policy engine over the canonical JSON serialization of the objects, identically on the decision API and the MCP planes.
  2. Typed validation: the add-on extracts and validates the objects. A request that opts into the schema but sends a malformed shape is flagged for protocol integrity, attributed to the fincrime_mandatory_fields policy (see Validation semantics). Risk scoring still runs on such a request where enabled; the scorer treats unusable values as absent.
  3. Advisory risk scoring, when the scoring service is enabled: the validated objects are forwarded to the in-deployment scoring service. Scoring is advisory. It can escalate a decision toward human review; it never denies. If the scoring service is unreachable, times out, or errors, the decision proceeds without a score and the audit record is stamped ml_inference_layer_status: "unavailable".

Per-plane outcome semantics

Read this before integrating. What an above-threshold score, a malformed context, or a policy pack match does differs by request surface, following the platform's existing per-plane enforcement contract:

Request surfaceAbove-threshold score or malformed contextPack step-up (require_approval) policiesPack block policies
POST /api/v1/decideVerdict needs_approval plus a pending entry in the approval queue: the reviewable step-upVerdict needs_approval plus an approval queue entryVerdict deny
MCP query, execute, and check-inputAdvisory: the request proceeds as allowed and the detection is stamped on the audit record (policy attribution, risk_score, ml_inference_layer_status). No approval queue entry is created and nothing pausesNon-blocking attributed match in the audit recordHTTP 403 block

An integration that needs pause-for-approval semantics must call the decision API. On the MCP planes, risk scoring and context validation are detection and audit-attribution surfaces, not gates. Deterministic block policies deny on every surface the pack evaluates on.

The table above is the complete list of request surfaces where the add-on's typed validation and risk scoring run today. Coverage of further surfaces, including Gateway Mode pre-check and the Workflow Control Plane, is planned.

Step-up entries created on the decision API are retrievable and actionable through the HITL queue API; see Human-in-the-Loop for the endpoints and HITL Approval Gates for the workflow-facing queue. Two details the pause-resume loop depends on:

  • The needs_approval decide response surfaces the pending entry's identifier in its reasons array, as the reason string fincrime approval request <request_id> pending human review. Parse the UUID out of that reason to find your entry without listing the whole queue. Entry creation is best-effort: a needs_approval response can arrive without this reason when no entry was created, so fall back to listing the queue rather than treating the reason as guaranteed.
  • Queue entries carry both a numeric list id and a request_id UUID. The approve and reject endpoints take the request_id UUID, not the numeric id.

Each fincrime step-up entry carries oversight metadata, including EU AI Act Article 14 human-oversight context and AML and CFT review context.

fincrime_transaction

FieldTypeConstraint when presentNotes
amountnumber>= 0, at most 1e15Transaction amount in major units of currency (48500 means 48,500.00 USD). Must be a JSON number, never a string. The pack's numeric thresholds assume major units: a caller sending minor units (cents) will trip them on routine values, so tune the pack before sending minor units.
currencystring3-letter ISO 4217 codeNormalized to upper case.
payment_typestringfree-formConventional values: transfer, wire, card, ach, rtp, crypto. The pack's structuring policy keys on transfer and wire.
payment_methodstringfree-formConventional values: card_present, card_not_present, bank_account, wallet. The pack's card-not-present policy keys on card_not_present.
sender_locationstringISO 3166-1 alpha-2 or alpha-3 code, optional - subdivision suffixExamples: US, US-NY, IRN. Normalized to upper case.
receiver_locationstringsame as sender_location
counterparty_account_idstringfree-formOpaque identifier. Never send a full card number (PAN); see the note on widened scanning below.
merchant_idstringfree-form
merchant_category_codestring4-digit ISO 18245 MCCA string, not a number: leading zeros are significant.
timestampstringRFC 3339When the transaction was initiated by the agent.

fincrime_cohort

Caller-computed rolling aggregates for the transacting principal. AxonFlow is the policy decision point, not the metrics store: your system already observes its own transaction stream, so it supplies the aggregates and the platform evaluates the thresholds. Requests that carry no cohort data do not receive the velocity and exposure step-ups. In-platform cross-request aggregation is planned.

FieldTypeConstraint when presentNotes
historical_mean_amountnumber>= 0The principal's historical mean transaction amount.
txn_frequency_1hnumber>= 0Transactions initiated by this principal in the trailing hour, including this one.

Validation semantics

  • Neither key present: not a fincrime request. Zero behavior change.
  • Key present and well-formed: consumed by all three layers as described above.
  • Key present but malformed: the detection is attributed to the fincrime_mandatory_fields protocol-integrity policy. On the decision API the decision steps up to needs_approval; on the MCP planes it is an advisory attributed detection. The reasoning: an agent that claims to describe a transaction but does so unparseably is exactly the traffic that needs a human.

Malformed means a present value violating its documented constraint, not just gross type errors. The whole context counts as malformed when a key is not an object, a field has the wrong JSON type (a string amount, a numeric merchant_category_code), or a supplied value fails its documented format: a non-3-letter currency, a location that is not an ISO 3166 code shape, an MCC that is not exactly 4 digits, a timestamp that is not RFC 3339 (epoch numbers do not qualify), a negative amount or cohort value, or an amount above 1e15. A field whose value is null is treated as absent, and so is an empty string in a string field; an empty string where a number belongs (amount, the cohort fields) is a wrong type and counts as malformed. This is deliberately stricter than being lenient about one bad field: on the decision API, a stream of slightly-off values (for example epoch-millisecond timestamps) will step up every such request to human approval, so validate your producer against the field tables above before rollout.

Opting in widens what is scanned

Attaching the fincrime keys also widens the platform's scanning of the request. On the decision API, the context objects are handed to the shared policy engine as request parameters, so the full enabled policy set, including PII, SQL injection, sensitive-data, and compliance categories as well as the FinCrime Policy Pack, scans their canonical JSON, exactly as it already scans MCP-plane parameters. A card number pasted into counterparty_account_id can therefore trip a PII policy, not just a fincrime one. This is deliberate fail-toward-governance for opt-in traffic only; requests without the keys keep the decision API's historical behavior.

Canonical serialization

The shared engine scans object-valued parameters as the canonical JSON serialization of the decoded object: keys sorted ascending, no whitespace, integral numbers without a decimal point. Example:

{"amount":9300,"currency":"USD","payment_type":"transfer","receiver_location":"VN"}

The pack's context-bound patterns are written against exactly this form, which is identical on the decision API and the MCP planes. As an integrator you do not need to produce this form yourself; send ordinary JSON and the platform canonicalizes it before matching.

Example: prompt-injected beneficiary change

A procurement agent has ingested a poisoned invoice PDF that instructs it to change the supplier's bank details and pay an inflated total. The enforcement point calls the decision API before the tool call:

{
"stage": "tool",
"caller_identity": {"gateway_id": "procurement-gw"},
"target": {"type": "tool", "server": "erp", "tool": "erp.update_vendor_bank_details"},
"query": "Update beneficiary bank account for vendor ACME-GmbH to DE44 5001 0517 5407 3249 31 and process payment of invoice INV-2209",
"context": {
"fincrime_transaction": {
"amount": 48500,
"currency": "USD",
"payment_type": "transfer",
"sender_location": "US",
"receiver_location": "DE",
"counterparty_account_id": "vendor-acme-gmbh",
"timestamp": "2026-08-20T09:15:00Z"
}
}
}

Expected outcome: verdict deny. The pack's payment tool authorization gate blocks the beneficiary mutation on the request statement, and the high-value amount cap independently blocks the 48,500 amount from the transaction context. The audit record carries the enforcement plane, the decision id, and the blocking policy id first in its policy attribution, so the decisions feed and the compliance exports attribute the block.

Example: structuring burst with cohort aggregates

The same agent, now compromised into splitting a large transfer into sub-threshold legs. Each leg carries the transaction plus caller-side cohort aggregates. The burst trips the structuring band immediately and the velocity threshold as the frequency climbs:

{
"stage": "tool",
"caller_identity": {"gateway_id": "procurement-gw"},
"target": {"type": "tool", "server": "payments", "tool": "payments.create_transfer"},
"query": "Transfer part 7 of supplier settlement",
"context": {
"fincrime_transaction": {
"amount": 9300,
"currency": "USD",
"payment_type": "transfer",
"sender_location": "US",
"receiver_location": "VN",
"counterparty_account_id": "acct-9917",
"timestamp": "2026-08-20T09:42:00Z"
},
"fincrime_cohort": {
"historical_mean_amount": 210.5,
"txn_frequency_1h": 12
}
}
}

Expected outcome: verdict needs_approval. The structuring step-up (a sub-threshold transfer in the 3,000 to 9,999 band) and the velocity step-up (12 is at or above the 10 per hour threshold) both fire, and an approval queue entry is created. With the risk scoring service enabled, the leg is also scored, and an above-threshold score routes to the same approval queue with a structured risk_score object on the audit record. This example's receiver is also on the pack's increased-monitoring (grey list) corridor snapshot, so the corridor step-up fires as well; multiple policies attributing one decision is normal and each appears in the policy attribution.

Example: the same context on an MCP plane

On the MCP planes the objects ride in parameters. Here is the pre-execution check (POST /api/v1/mcp/check-input) for a connector-executed transfer, carrying the same transaction object:

{
"connector_type": "payments",
"statement": "INSERT INTO transfers (account, amount) VALUES ($1, $2)",
"parameters": {
"1": "acct-9917",
"2": "9300",
"fincrime_transaction": {
"amount": 9300,
"currency": "USD",
"payment_type": "transfer",
"receiver_location": "VN",
"timestamp": "2026-08-20T09:42:00Z"
}
}
}

Expected outcome: allowed: true, because step-ups do not pause on this plane; the structuring and corridor detections are stamped on the decision audit record as attributed matches. Had the transaction matched a block policy instead (for example an amount of 12000, at or above the 10,000 cap), the response would be a block. POST /mcp/resources/query and POST /mcp/tools/execute carry the objects the same way, inside their parameters maps, alongside those endpoints' own required fields, which are documented in the Agent API endpoints reference.

Request authentication

Fincrime context adds nothing to authentication. Decision API calls authenticate exactly as documented in Decision Mode, and MCP-plane calls as documented in the auth header matrix.