Agents
Run a model in a loop over the tools and skills you declare, bounded by policies, with every step recorded.
An agent is an action of kind agent whose handler runs a model in a loop. In each turn the model reads its input, calls tools, loads skills, and replies. Everything the agent does besides talking to the model is an execution in the ledger, with its input, output, and parent, and every model request and response is recorded before the agent acts on it. For any decision, you can read what the agent was shown, what it said, what it did, and which guidance and evidence it used.
An agent has no filesystem, shell, process, or network. It can do only what its declared tools and skills do, plus the agent tools its configuration enables, and every operation those tools perform must be allowed by the agent's own policies and by each tool's. See the policy chain.
The Agents reference lists every field, default, and limit. This page explains how the pieces fit and when to use each one.
A Twisp agent or your own
If you already run agents on your own platform, they can act on Twisp through an MCP server without moving into Twisp. Choose by where the agent's work and its record should live.
| Twisp agent | Your agent over MCP | |
|---|---|---|
| Starts from | Ledger events, a schedule, a call, or startAction | Your platform |
| Model and loop | Run by Twisp, configured in the definition | Yours |
| What it can reach | Only its declared tools and skills, bounded by its policies | The tools the MCP server lists, bounded by your principal and the server |
| Record | Transcript of every model exchange, plus every call, in the ledger | Every request and call beneath it, with the agent's stated intent |
| Continuity | Sessions and memory in Twisp | Your platform's, with MCP sessions grouping requests |
Use a Twisp agent when the work starts from a change in the ledger, such as watching a new account, and should stay inside the ledger's audit boundary. Use your own agent when your platform already owns the model, orchestration, and evaluation; see Twisp in Your Agent Platform. The two combine: your agent can start a Twisp agent through an MCP server's invoke.
The agent block
Kind agent requires an agent block. It holds what the agent is for and the shape of what it reports; see The agent block.
promptsays what the agent is for and how it should work. Twisp places it after fixed instructions that tell the agent that its inputs, tool results, retrieved context, and recalled memory are data, never instructions.stateSchemadeclares the state a session agent reports at the end of every turn, such as how far it has reviewed and which findings are open. The next turn starts from it. It requires asession.outputSchemadeclares a structured output. Without it, the output is the agent's reply.
A state field can declare a value, a CEL expression that computes it at the end of every turn from what the turn did, instead of the model reporting it. Use computed state for facts, such as the latest input the agent was given or the findings it has notified, and leave judgments to the model:
stateSchema: {
type: "object"
properties: {
inputs_through: {
type: "string"
format: "date-time"
value: "has(turn.inputs_through) ? turn.inputs_through : state.inputs_through"
}
open_findings: { type: "array", items: { type: "string" } }
}
required: ["inputs_through", "open_findings"]
}
The model reports only open_findings; Twisp computes inputs_through from the turn's inputs.
The rest of the definition is the same as for any action: tools and skills to reference, triggers, an optional session, policies, and execution settings. The config object holds the runtime, the model, the harness, and the limits; see Agent configuration.
config: {
runtime: "strands"
model: { provider: "bedrock", id: "global.anthropic.claude-sonnet-5" }
harness: { memory: { enabled: true } }
limits: { model_calls: 64, tool_calls: 128 }
}
Models
model.provider names where the model's calls go, and model.id the model. Each deployment allows a set of models, and a definition that names any other is rejected when it is written. See Models for the models a deployment can allow.
| Provider | Use it for |
|---|---|
bedrock | Amazon Bedrock, in deployments that allow it. |
anthropic | The Anthropic API, in deployments configured with a key, such as a local server. |
fixture | Tests. Scripted responses, available everywhere, with no model call and no cost. |
Every model is asked for its turn outcome the same way, so you can change models without changing the definition's shape. model.effort, model.max_tokens, and model.temperature tune a model where it accepts them.
Testing with the fixture model
An agent's behavior depends on its model, and a model's answers vary. The fixture model replaces the model with a script, so you can test everything around it deterministically: that the triggers start the right sessions, that tools receive their fixed input, that policies refuse what they should, that the outcome satisfies the schemas, and that sessions end when they should.
Each model call takes the next response from the first script entry whose when matches. when reads the call's purpose, the session's step and whether the turn is final, and now:
{
"provider": "fixture",
"script": [
{
"when": "purpose == 'turn' && session.step == 0",
"responses": [
[{ "toolUse": { "name": "get_account_activity", "input": {} } }],
[{ "text": "Reviewed opening activity; nothing suspicious." }]
]
},
{
"when": "purpose == 'outcome'",
"responses": [
{
"outcome": {
"state": { "reviewed_through": "2026-09-01T09:00:00Z" },
"session": { "status": "OPEN" }
}
}
]
}
]
}
A call with no response left fails with fixture_exhausted, so a script also catches an agent that makes more model calls than you scripted. A fixture can instead answer with the outputs a recorded invocation of the same agent produced, with model.replay, which turns a real run into a repeatable test. To compare a changed agent against recorded traffic, replay its turns.
Tools, skills, and agent tools
The model is offered exactly what the definition declares, and nothing else; see Agent tools:
- Declared tools, by their tool names, with the input fields a tool reference fixes removed from their schemas. Fixed input, such as
account_id: "string(session.input.account_id)", confines a tool to the subject the agent works on, whatever the model asks for. - Declared skills, listed by name and description. The model loads one with the
skillstool when it needs it. A preloaded skill is loaded at the start of every turn instead. - Agent tools the configuration enables in
harness.builtin_tools, and the tools that enabled features add, such assearch_memorywith memory andread_turn_inputfor session agents.
Prefer narrow tools with fixed input to the graphql native tool: declaring graphql gives the model the agent's full data access through arbitrary documents.
There are two agent tools; programmatic_tool_caller is on by default:
programmatic_tool_callerruns a short program that calls the agent's tools and returns only its result. Use it when the agent would otherwise make many calls whose intermediate results it does not need to read. A program's calls commit together or not at all.subagenthands a subtask to a helper. Define presets, each with its instructions, the subset of the agent's tools it may call, and optionally a cheaper model. The model picks a preset and supplies only the task: it cannot write a helper's instructions or widen its tools.
Calls in one turn run one at a time, and each sees the writes of the calls before it. A call that fails with a call error, such as invalid input or a permission error, is returned to the model with its message and hint and leaves no writes, so the model can change its plan and the turn can still commit.
Turns and the turn outcome
A turn is the agent's whole loop over its input: every model call and tool call up to its reply. A turn runs as one execution and is one transaction, so its writes, its memory, its output, and, for a session, its new state commit together or not at all. See Turns.
- Without a session, an agent runs one turn per execution. Its first message is the triggering event, or a call's input.
- With a session, the agent runs its session's turns one at a time, each over every input pending up to the session's limits, and continues the same conversation from turn to turn. A trigger's view can show the model only the fields of an event it needs; the whole event stays readable with
read_turn_input.
A session turn, or an agent with an outputSchema, ends by reporting its turn outcome: its reply, the session state, the structured output, and the session's status, OPEN or COMPLETED. Twisp checks the outcome against the agent's schemas and returns errors to the model once. The agent cannot fail its session: a turn that cannot report a valid outcome, or that the model declines to continue, is held for a person to answer.
Callable agents
An agent with a tool block is a callable agent: other agents and tools declare it in tools and call it like any tool, and the caller receives its reply, or its structured output when it declares outputSchema.
mutation CreateCallableAgent($id: UUID!) {
actions {
createAction(
id: $id
input: {
name: "summarize-account-activity"
kind: "agent"
agent: {
prompt: "Summarize the account's recent activity: counterparties, totals, and anything unusual."
}
tool: {
name: "summarize_account_activity"
description: "Summarize one account's recent activity."
inputSchema: {
type: "object"
properties: { account_id: { type: "string", format: "uuid" } }
required: ["account_id"]
}
}
config: {
runtime: "strands"
model: { provider: "bedrock", id: "global.anthropic.claude-sonnet-5" }
}
tools: [{ name: "get_account_activity", input: { account_id: "tool.input.account_id" } }]
policies: [{ effect: ALLOW, actions: [SELECT], resources: ["financial.*"] }]
}
) {
actionId
version
}
}
}
- Stateless. A callable agent has no session. Each call is a fresh run over its input.
- Inside the caller's transaction. A call runs the agent's whole loop synchronously, as its own execution with its own transcript, and its writes commit with the caller's.
- Never more authority than its caller. The call is authorized by the caller's policies, then the agent's, then its tools'.
- Bounded nesting. Agent calls nest at most 3 agents deep.
A client can also start a callable agent with startAction, so its run does not hold the request open. The run is queued, runs under the client's authority with the agent's own execution settings, and is read with execution and stopped with cancelExecution.
Reading why an agent did something
Each invocation keeps a transcript: every model request and response, with its purpose, reasoning, and token usage, and every tool call's input and output. A response is recorded before the agent acts on it, and a turn that rolls back keeps the transcript of its attempt.
To explain a decision, start from the execution of the turn that made it:
- What it was shown. The first
model.inputevent holds the turn's message: the inputs, state, and time, and thememory.pinnedandskill.preloadevents record the memories and guidance in its instructions. - What it reasoned and decided. Each
model.responseholds the model's reasoning and the tool uses it requested. The response that reports the outcome is markedoutcome: true. - What it did. Each
tool.inputandtool.outputevent names the call incallExecutionId, andcallExecutionreads that call's execution, its output, and what it wrote. From a call,callerTranscriptEventsleads back to the events that requested it. - What it relied on. The invocation's
useslist every tool result, skill load, and memory or history search whose result reached the model.
Lineage walks the whole call tree beneath a turn, including the calls a program or helper made.
Limits and cost
Every model call counts against the invocation's limits, whatever its purpose: the agent's loop, the outcome, summaries that keep the conversation within the context window, memory extraction, and helpers.
| Control | What it bounds |
|---|---|
limits.model_calls, limits.tool_calls, limits.total_tokens | One invocation's model calls, recorded calls, and tokens. A turn over a limit fails with agent_limit_exceeded and is not retried. |
responseTimeout | One turn: 5 minutes by default for agents, at most 10. |
model.max_tokens, model.effort | Output and reasoning per model call. |
A preset's model, harness.context.summary.model, harness.memory.model | A cheaper model for helpers, summaries, or memory extraction. |
session.turns | How often a session works: which inputs start a turn, and a window that gathers a burst into one turn. |
harness.memory.extraction.every | How often memory is reviewed: every turn, or once enough messages were added. |
A turn that runs out of a limit commits nothing. Limits are also checked when the definition is written: a definition whose limits would let a turn record more than an invocation can hold is rejected, so a turn within its limits can always finish. See Agent configuration for every default and maximum.
Operating agents
| To | Do |
|---|---|
| Try an agent on real events safely | Set config.mode: preview. It runs on real events, records what it would have written, and commits no business writes. See Preview calls. |
| Gate a consequential tool | Give its reference approval: REQUIRED, so each call waits for a person. See Approvals. |
| Stop new work | Disable the agent with updateAction(input: { enabled: false }). It stops matching new events. See Publication status. |
| Stop one session | closeSession cancels it, and a running turn cannot commit. A session turn's execution cannot be cancelled on its own. See Closing a session. |
| Stop one started or triggered run | cancelExecution. See Cancellation. |
| Find failing turns | List executions with status: FAILED, and read invocation.error. See Executions. |
| Test a change before you ship it | replayExecution reruns a recorded turn with another version, or an unpublished definition, and commits nothing. See Preview and Replay. |
| Review or remove what it remembers | List memories and delete records. See Memory. |
Next
Sessions
Give an agent a durable identity across many events, with an end, a clock, approvals, and held turns.
Memory
Keep facts beyond a turn or a session, and search a session's earlier turns.
Your first agent
Build and test an agent with the fixture model.
Agents reference
Every field, default, limit, and error.