ctx.prev. Approval gates suspend the workflow until a human approves.
Defining workflows
Use the builder pattern:workflow() returns a builder, chain .step() calls, then .build() to finalize.
ctx.prev is strongly typed based on preceding steps’ output schemas. No casts needed.
Step options
Input callbacks
Theinput callback receives a StepContext with access to the workflow input and all previous step outputs:
{ message: string }:
input callback is provided, the agent receives a default message: "Execute step \"step-name\"".
Workflow options
Validation rules
- Workflow names must match
/^[a-z][a-z0-9-]*$/ - Step names must match the same pattern
- At least one step is required
- Duplicate step names within a workflow throw an error
- Both workflow and step definitions are deeply frozen after creation
Running workflows
UserunWorkflow() to execute a workflow. It runs each step sequentially, passing outputs forward via ctx.prev.
Result shape
How output accumulation works
Each step’s output is stored inctx.prev keyed by step name. If a step has an output schema, the agent’s response is parsed as JSON and validated against it. Validated data is stored in prev. Steps without an output schema store { response: string }.
If output validation fails (invalid JSON or schema mismatch), the workflow returns an error — it does not silently fall back.
ctx.prev is strongly typed — each step sees the output types of all preceding steps based on their output schemas. No casts needed.
Approval gates
An approval gate suspends the workflow until a human approves. WhenrunWorkflow() hits an approval step, it returns immediately with status: 'pending'.
Approval config
Resuming after approval
When the workflow returnspending, store the step results. After the human approves, call runWorkflow() again with resumeAfter pointing to the approval step:
Building the approval UX
The approval primitive is transport-agnostic —runWorkflow() doesn’t dictate how approvals are delivered or collected. Common patterns:
- HTTP endpoint — Store pending state in a database, expose
POST /workflows/:id/approve, render an approval button in a dashboard - Webhook — Send the approval message to Slack/Discord, listen for a reaction or command
- Durable Object — On Cloudflare, hold workflow state in a Durable Object that wakes when an approval event arrives
- CLI prompt — For dev tooling, prompt in the terminal and resume immediately
Agent-to-agent invocation
Tools can invoke other agents usingctx.agents.invoke(). This enables delegation patterns where a coordinator agent dispatches work to specialized agents.
Invoke options
The invoked agent runs a full ReAct loop with the same LLM adapter as the calling agent. It returns
{ response: string }.
Session persistence
Agents support persistent sessions via anAgentStore. Pass a store to run() to enable conversation history across multiple calls.
Available stores
Session options
LLM adapters
Agents communicate with LLMs through adapters. UsecreateAdapter() to create one:
Available providers
Custom adapters
You can provide a customLLMAdapter directly — any object with a chat() method: