Agent runtime
The agent.Runtime is the engine that turns a Strategy into a real, capital-deploying process.
Lifecycle
- Build.
agent.BuildDeps(a, …)constructs venues, signers, the swap router, the risk engine, the strategy, and resolves the inference provider for one agent (parsingagent.Inference = "provider:model"against the configured registry). Same code path is used by both the foregroundagent runCLI and the background supervisor insideserve, so behaviour stays identical. - Warmup.
Runtime.Warmup(ctx)invokesStrategy.Warmupexactly once per Runtime, guarded bysync.Once. BothStartandtickOncecall it; whichever runs first wins, the other no-ops with the cached error. The strategy receivesWarmupInputcarrying the agent's universe, config, and the frameworkServices(logger, inference, inference model id, asset registry). Warmup failures abortStart(or every tick) so the operator notices immediately. - Tick loop. A
time.Tickerfires everyagent.tick_secs. Each tick assemblesDecisionInput, callsStrategy.Decide, executes the returnedDecision(swaps before orders), runs reconciliation, and persists everything. - Stop.
Runtime.Stopgraceful-cancels the loop. The persisted agent status is unchanged; to permanently halt, set status tohaltedvia the CLI.
Per-tick execution order
For a Decision{Swaps: [s], Orders: [o], Cancels: [c]}:
- Cancels are sent to the perp venue first.
- Swaps execute and are awaited until confirmation. If a swap fails, the matching
Order(sameBasisKey) is dropped -- no half-filled basis. - Orders are sent only after every swap with a matching
BasisKeyconfirms. - The decision (with its prompt + LLM response if any) is persisted along with resulting tx hashes / venue order IDs.
- Reconciliation reads venue + on-chain state and updates
BasisPositionrows. - PnL is recomputed.
This order is the spot-first invariant that makes delta-neutral strategies safe. Strategies do not have to enforce it themselves -- the runtime guarantees it.
Concurrency
One supervisor goroutine per running agent. Strategy Decide calls within an agent are strictly sequential -- each tick waits for the previous to complete (or hit the tick deadline). Across agents, ticks happen in parallel; the runtime is goroutine-safe.
Where it lives
internal/agent/runtime.go-- theRuntimeitself.internal/agent/builder.go--BuildDeps,BuildStrategy,BuildHyperliquidVenue.internal/agent/supervisor.go-- keeps aRuntimeper running agent on daemon boot.internal/agent/killswitch.go-- the global stop everything switch.