kind
(tool_call, llm_call, or local). Recording an llm_call takes an
interceptor, since the request is made inside a provider SDK. See
LLM calls.
An effect becomes a step
When the agent is about to perform an effect it submits a step (POST /v0/executions/{id}/steps) with the kind, the target (the tool name or
model id), and the arguments. The kernel:
- Computes the step’s deterministic ID.
- Looks it up in the
stepsprojection. If it already succeeded or failed, the kernel returnsreplaywith the recorded outcome. - Otherwise evaluates policy and records the decision, returning
proceed,denied,rate_limited, orblocked.
proceed the agent runs the effect and reports the result
(.../complete) or error (.../fail). See the HTTP API for
the shapes.
Step identity
A step’s ID is derived from the effect’s content:targetis the tool name or model id.args_hashis a stable hash of the canonicalized arguments, meaning canonical JSON for tools and the canonical request body for LLM calls.occurrenceis the count of prior identical calls in this run of the agent, so the same call with the same arguments twice yields two distinct steps. It restarts at zero on every dispatch, which is what lets a re-run reproduce the same IDs.
{kind, target, args} and its dispatch_id. Because IDs are content-derived,
parallel effects and reordering across replays are safe. The same set of calls
always produces the same set of IDs. See
Step identity.
Idempotency modes
If an agent crashes after a step started but before its result was recorded, the step is orphaned, and the kernel cannot tell whether the side effect happened. Each effect declares how to recover:Local steps
Alocal step records a value the agent produced itself, such as the current
time, a random choice, or a fresh id. Record it when the value decides which
effects run next, so a resumed run replays the same value. Both SDKs expose it as
step(name, fn).
An unmatched
local step is allowed whatever default_action says, so a
deny-by-default bundle will not block one. See Evaluation.