One operator sees a dropped connection and cancels every open order. Another leaves orders live and rebuilds state from the broker after reconnecting. Both calls can be wrong. The first may turn a safe resting limit into avoidable market exposure; the second may leave stale orders working after its strategy has changed. The difference is not cleverness in the agent. It is whether the broker API exposes enough reliable state to make the decision.
A human can notice a confusing screen, pause and call support. An unattended process cannot. Its broker interface has to make uncertainty visible, give the agent safe recovery options and define what an accepted order means after a timeout.
Order submission is not the contract
Most broker APIs make the happy path look simple: send a symbol, side, quantity and order type, then parse a response. That response might mean the request passed validation, reached an order gateway or was accepted by an exchange. Those are different events. An agent needs an explicit acknowledgement with a broker order ID, acceptance time, status and any venue or route information the broker makes available.
Rejects need equally specific fields. A generic error string forces software to guess whether to correct a tick size, refresh buying power or stop sending orders. Prefer machine-readable codes, the rejected field, retryability and a reason that distinguishes a session restriction from an insufficient-margin check. Preserve the raw response alongside your parsed event. Broker schemas change, and a parser should not erase the evidence needed to diagnose a new reject.
Client order IDs help correlate submissions with later updates, but they are not automatically idempotency keys. Confirm whether the broker guarantees uniqueness, how long it retains IDs and what happens if the same ID arrives with changed parameters. If those semantics are undocumented, treat a timed-out submission as unknown, not failed.
State has to survive a broken stream
A websocket is useful for fast updates, not as the only source of truth. Connections drop, messages arrive late and consumers restart.
The API should let an agent query open orders, executions, positions and balances, and ideally request updates from a cursor or sequence number. If there is no sequence or replay mechanism, the agent needs a documented snapshot-and-reconcile path.
The figures below are typical market ranges for planning, not service guarantees. Actual latency and quotas vary by broker, account, route and market conditions. Design for stalls and bursts rather than treating a typical response time as a deadline.
| Measure | Typical market range | Design implication |
|---|---|---|
| Order acknowledgement on a healthy route | 50-500 ms | A timeout can still follow a successful submission. Reconcile before retrying. |
| Quote stream update delay for liquid instruments | 10-500 ms | Track event timestamps and mark stale data unusable. |
| Account or order polling interval | 1-5 seconds | Use streaming for updates and polling for recovery, within quota. |
| Common per-endpoint request limits | 1-20 requests per second | Read limit headers and budget calls across workers. |
| Reconnect and backfill window | 1-30 seconds | Request a snapshot or replay before resuming new risk. |
Reconciliation should compare broker state with the agent's durable intent, not just its in-memory order map. Store each intended action before sending it.
After a restart, query the broker and match by client ID, broker ID and executions. If the API cannot establish whether an order exists, hold new exposure in the affected instrument until the ambiguity is resolved.
Retries and order changes need explicit rules
A network timeout does not prove that an order was rejected. The broker may have accepted it and lost the response. Blindly repeating a POST can create a duplicate position. Use an idempotency key where the broker supports one. Otherwise, submit a stable client ID, query for it after an uncertain result, and only resend when the API contract makes that safe.
A practical recovery sequence should be deterministic:
- Persist intent. Record the strategy decision, client ID, instrument, side, quantity and risk checks before transmission.
- Submit once. Save the request and response, including transport errors and timestamps.
- Resolve uncertainty. On timeout or server error, query by client ID or list recent orders. Do not infer rejection from a missing response.
- Reconcile fills. Apply executions using unique execution IDs, so replayed events do not double-count quantity.
- Resume within limits. Continue only when positions, working orders and the agent's recorded intent agree.
Cancel and replace operations need the same care. Some APIs implement replace as an atomic amendment; others cancel the old order and submit a new one. The latter creates a window with no working order, and the replacement can fail after the original is cancelled. Expose that transition to the strategy. Treat partial fills as position changes, not as an incidental order status.
An acknowledgement is not a fill, and a timeout is not a rejection.
Risk controls must work outside the strategy
A strategy can calculate its own limits and still fail through a bug, duplicate worker or stale position. Broker-side controls add a separate boundary. Useful controls include maximum order quantity, notional caps, allowed instruments, order-type restrictions and a kill switch that blocks new orders while allowing cancellations. Ask whether limits apply before routing and whether they cover all sessions and order entry methods.
Protective orders also have semantics that matter. A bracket or OCO request may be atomic, or the API may create related orders one at a time. Confirm how the broker handles partial fills, rejected legs, cancel races and overnight transitions. Do not assume that a stop trigger guarantees a fill at the stop price. A stop-market order prioritises execution; a stop-limit order can remain unfilled in a fast market.
Set independent agent-side checks as well. For example, refuse new orders when market data is stale, when position reconciliation is incomplete or when the account's buying power differs from the expected range. Keep a per-instrument exposure ceiling and a global loss or notional boundary. These checks should fail closed for new risk, while leaving a controlled path to cancel orders and alert an operator.
- Record the timestamp and source of each quote used to price an order.
- Make a kill switch available to operations, not only to the strategy process.
- Separate credentials for read access and order entry where the broker permits it.
Test the failure paths before unattended trading
Paper trading is useful for checking request formats and state transitions, but it does not prove live routing behaviour. Simulated fills can be optimistic, and market impact, queue position and some reject conditions may not be represented. Test the same recovery logic against delayed updates, duplicate events, process restarts, rate-limit responses and expired credentials. Keep a replayable event log so a failure can be reproduced without sending live orders.
Track operational measures that expose unsafe behaviour: order acknowledgement latency, reject rate by code, time spent with unknown order state, reconciliation mismatches and the number of duplicate submissions prevented. Alert on a mismatch or stale stream, not only on a process crash. A running agent can be more dangerous than a stopped one if it is acting on outdated positions.
A hosted agentic paper-trading environment can help exercise order workflows without committing live capital. Plans start at $9.99 per month. Treat its results as a test of integration and controls, then validate broker-specific behaviour separately.
Stop doing these things:
- Retrying an order submission just because the client timed out.
- Treating a websocket connection as a durable order ledger.
- Mapping every reject to one generic retry rule.
- Resuming new risk before positions and working orders reconcile.
Frequently Asked Questions
What should a broker API return after an order is submitted?
It should return a broker order ID, an explicit status, an acceptance timestamp and structured reject details when the request fails. The response should distinguish acceptance from execution, because an accepted order may still be pending or partially filled.
How should a trading agent handle an order submission timeout?
Treat the result as unknown, because the broker may have accepted the order without returning a response. Query by a stable client order ID or reconcile recent orders before retrying. Resend only when the broker's idempotency rules make it safe.
Can a websocket alone keep an agent's order state accurate?
No. Streams can disconnect, events can be delayed and an agent can restart between updates. Use the stream for timely events, then reconcile against broker snapshots or replay data after a gap.