How the runner works
The one-screen mental map of the runtime, before you write decide().
Before you write a line of decide(), hold one picture in your head: the runtime runs everything, you write one function.
Core principle: your plugin returns declarative intent; the engine executes it. The plugin never builds a tx, never touches a key, never calls RPC.
Engine vs plugins
Two halves, one boundary.
- The engine is the trusted runtime: the scheduler that fires triggers, the executor that materializes your intent into a transaction, the signer, logging, metrics, and failure isolation. It ships with the runner. You never edit it.
- Your plugins are the half you own. Each is a
StrategyPlugin: aname, avaultId, a list oftriggers, and adecide()function. That function is your whole strategy.
The engine wires the two together. A crashing plugin gets caught, logged, and marked unhealthy; the runtime carries on with the others.
The pipeline
One plugin tick walks a fixed path:
Each tick starts from a fresh Vault.fetch — your decide() never sees a stale snapshot. You return an Action[]. The executor turns that array into a single transaction (multiple actions become sequential moveCalls in the same tx), signs it with the operator key, and submits. An empty list or a single noop means "decided not to act" and the tick ends cleanly.
That's the entire surface you touch: read ctx, return Action[]. Everything below the arrow is the engine's job.
Why declarative intent
You describe *what* should happen, not *how*. That buys three things:
- Testable.
decide()is a pure-ish function ofctx— no mocks, no chain. - Contained. A buggy plugin can only return a bad
Action[], and the vault's risk caps reject it on-chain. It can't escape the vault. - Safe to delegate. The same boundary that protects you is what lets the runtime sandbox third-party strategies later.
This is the plug-and-socket split: your strategy is the plug, the vault is the socket, and the engine is the cable between them.
From strategy to plugin
A strategy is a concept — a rule for when to mint, size, and redeem. A plugin is that concept written as code the runtime can run. The bridge is decide(): every "if the price crosses X, take a position" becomes a branch that returns an Action[] (or a noop with a reason).
Next: the full layer-by-layer breakdown lives in Runner architecture. From there, the Build ladder walks you through writing real plugins.