Overview
The AI agent is an event-driven ReAct loop implemented in TypeScript using the Vercel AI SDK. It connects to the sidecar via Server-Sent Events and fires a decision cycle on three trigger conditions:tx_enqueued
A new user transaction arrived in the queue.
bundle_settled(failed)
A bundle terminated with a failure class that requires a retry decision.
30s watchdog
Safety net for SSE reconnect gaps — agent checks for any missed work.
The decision cycle
Data gathering is parallelized out of the LLM hot path. Before the model is invoked, the outer loop fetchesgetState, getTip, getLifecycle, and
getPendingTxs in a single Promise.all and injects the results directly
into the cycle prompt. The agent reads pre-loaded context and goes straight
to the decision — typically two tool calls total.
Tip selection
The agent selects from five percentiles on the live Jito tip oracle:p25, p50, p75, p95, p99.
The escalation policy embedded in the system prompt:
Consecutive fee_too_low failures | Percentile selected |
|---|---|
| 0 | p50 (baseline) |
| 1 | p75 |
| 2 | p95 |
| ≥ 3 | p99 |
“fee_too_low at p75=5000. Pattern: 2 consecutive fee_too_low. Oracle p99=1,000,000. Tx age=34/50 slots near TTL. Escalating to p95=100,000. If this fails: p99.”
The clean boundary
The architectural invariant that makes the system independently upgradeable:Rust never calls an LLM
All execution — signing, serialization, Jito submission — happens in the
Rust sidecar. The agent is an external observer that issues commands.
Agent never touches a keypair
The agent calls
POST /internal/submit with a tip amount and list of
tx_ids. The sidecar does the rest.Configuring the model
The agent model is configured via environment variables in the agent process:Retry race condition
A non-obvious concurrency hazard: thebundle_settled(failed) SSE event fires while the original submit cycle is still executing. The agent handles this with a pendingRetry field:
finally block with zero additional delay.