FIX Gateway as AI: Connecting Your OMS to Claude-Backed Quant Analysis
How BondFoundry's FIX 4.4 gateway sits in front of an AI agent — with HITL approval envelopes, ExecutionReport flowback, and a HITL queue that doesn't trust the model.
Most “AI for trading” pitches stop at the prompt. The interesting part starts when the agent talks to an OMS in production protocol — and the chain of custody between the agent’s intent and the FIX wire has to be auditable.
This post walks through how BondFoundry’s FIX 4.4 gateway accepts a trade proposal from the agent, verifies an HMAC-signed approval envelope, and submits NewOrderSingle — with ExecutionReport flowback into the same audit chain.
The shape of the chain
The agent never speaks FIX directly. The chain is:
- Agent proposes
create_tradevia MCP - Policy gate routes to T2 (single-HITL above materiality) or T3 (dual-HITL irreversible)
- Agent requests an HMAC-signed approval envelope; server generates it
- Trader approves via Slack, Teams, or operator workspace
- Envelope arrives at the FIX gateway
- Gateway verifies HMAC + scope_hash + SoD + expiry
- Gateway constructs
NewOrderSingle(35=D), sends to the venue ExecutionReport(35=8) flows back, gateway updates the trade record- Three audit rows in the chain: gate decision, envelope creation, FIX dispatch + ExecReport
Each step is a separate audit row carrying its own framework_ref. The chain proves there was no skip — you cannot have a FIX send without the envelope verification row immediately before it.
Why the gateway is its own service
The FIX gateway runs as a peer service. The agent does not import it; it talks to it over an internal API. Three reasons:
- Failure isolation. A FIX session disconnect should not take down the agent loop. The gateway crashes; the agent gracefully degrades to “I cannot dispatch right now.”
- Authentication boundary. The gateway holds the venue credentials. The agent has no access to them. A compromised agent cannot exfiltrate FIX session secrets.
- Audit boundary. The gateway writes its own audit rows for
NewOrderSinglesend andExecutionReportreceipt, independent of the agent’s audit rows. The chain join is the envelope_id.
The envelope verification on the gateway side
The HMAC envelope is the gateway’s only trust signal for executing a trade. Even if the agent and the gateway are co-deployed, the gateway re-verifies:
def accept_for_execution(env: ApprovalEnvelope, action: Action) -> Verdict:
if not hmac_verify(env.hmac, env.canonical_payload(), server_secret):
return Verdict.reject("envelope HMAC invalid")
if env.scope_hash != sha256_scope(action):
return Verdict.reject("envelope scope_hash does not match action")
if env.approver_id == action.caller_id:
return Verdict.reject("SoD: approver == caller")
if datetime.utcnow() > env.expires_at:
return Verdict.reject("envelope expired")
return Verdict.accept()
A rejected verdict writes an audit row with the rejection reason and a framework_ref pointing to the relevant AIGF mitigation (most often AIR-SEC-24 for HMAC issues, AIR-OP-18 for SoD).
NewOrderSingle and the audit row
When the gateway accepts, it constructs a FIX 4.4 NewOrderSingle:
8=FIX.4.4 | 9=156 | 35=D | 49=BONDFOUNDRY | 56=VENUE
11=ord_abc123 | 55=US...0X9 | 54=2 | 38=5000000 | 40=2
44=99.87 | 60=2026-06-01T14:23:11.000-05:00 | 10=...
Tag 11 (ClOrdID) is generated server-side and recorded on the audit row alongside the envelope_id. The audit row carries:
tool: "fix_send"envelope_id,scope_hashtier: "T2"(or T3)framework_ref: ["AIR-OP-6", "AIR-SEC-24", "AIR-OP-18"]- the redacted FIX payload (no venue credentials)
- the next-row chain hash
ExecutionReport flowback
The ExecutionReport (35=8) comes back. The gateway parses it, updates the trade record, and writes a third audit row in the chain:
tool: "fix_exec_report"ord_status(35=8 / 39=2 for filled)exec_id,last_qty,last_pxframework_ref: ["AIR-DET-21"](detection / monitoring control)
The chain now contains: gate decision → envelope → fix_send → exec_report. The auditor pulls any one of those rows and can walk back and forward through the chain to reconstruct the entire decision.
The HITL queue
The operator workspace shows a HITL queue scoped to the operator’s portfolio entitlements. Each pending approval shows:
- the action (tool, ISIN, notional, side)
- the rule that routed it (verbatim text, not paraphrase)
- the proposing agent (model + caller_id)
- the time-to-expiry on the envelope (9 of 90 seconds remaining)
- approve / reject buttons that submit through the API endpoint (not the UI button)
The buttons are convenience. The endpoint is the control. SoD is enforced on the endpoint: an approver can only approve actions where they are not the caller.
What this looks like end to end
A PM asks the agent for an IG-book rebalance. The agent runs analytics (T0, no HITL), proposes a $5M sell (T2). The gate routes to HITL. The trader sees the approval in Slack with the rule text. The trader hits approve. The envelope flows to the gateway. The gateway verifies and sends NewOrderSingle. The ExecutionReport comes back filled. Three audit rows, chained, every framework_ref present, every envelope verified.
The PM did not write a FIX message. The trader did not have to remember which fields to fill in. The auditor has a complete chain from intent to fill, citable by framework_ref.
Where this isn’t yet
The roadmap is honest about scaffolding vs production:
- FIX 4.4 acceptor: in flight, vanilla
NewOrderSingle/ExecutionReportcycle working - FIX 4.4 initiator (we dial out): scaffolded
- ICE Bonds, MarketAxess, Tradeweb venue-specific connectivity: bring your own session config; we have CSV venue ladder samples in the repo
- Multi-leg / structured products via FIX: not in scope
If your desk runs proprietary OMS connectivity (REST, internal RPC, etc.), the same chain shape applies — only the dispatcher changes. The envelope, the gate, and the audit chain are unchanged.
Where to start
- Stand up the policy gate and the HMAC envelope first. The FIX gateway adopts both, not the other way around.
- Run the gateway as a peer service. Don’t co-locate it with the agent process.
- Make the gateway re-verify the envelope on every accept. Belt and braces.
- Wire the audit row schema so
envelope_idis the join key. Future-you will thank present-you. - Run the eval
policybattery against the gateway with adversarial prompts. The agent should never be able to talk the gateway into accepting an unsigned action.
BondFoundry’s FIX gateway source is on GitHub. For the envelope mechanics, see HITL envelopes.