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 agentYour agent over MCP
Starts fromLedger events, a schedule, a call, or startActionYour platform
Model and loopRun by Twisp, configured in the definitionYours
What it can reachOnly its declared tools and skills, bounded by its policiesThe tools the MCP server lists, bounded by your principal and the server
RecordTranscript of every model exchange, plus every call, in the ledgerEvery request and call beneath it, with the agent's stated intent
ContinuitySessions and memory in TwispYour 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.

  • prompt says 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.
  • stateSchema declares 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 a session.
  • outputSchema declares 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.

ProviderUse it for
bedrockAmazon Bedrock, in deployments that allow it.
anthropicThe Anthropic API, in deployments configured with a key, such as a local server.
fixtureTests. 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 skills tool 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 as search_memory with memory and read_turn_input for 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_caller runs 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.
  • subagent hands 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:

  1. What it was shown. The first model.input event holds the turn's message: the inputs, state, and time, and the memory.pinned and skill.preload events record the memories and guidance in its instructions.
  2. What it reasoned and decided. Each model.response holds the model's reasoning and the tool uses it requested. The response that reports the outcome is marked outcome: true.
  3. What it did. Each tool.input and tool.output event names the call in callExecutionId, and callExecution reads that call's execution, its output, and what it wrote. From a call, callerTranscriptEvents leads back to the events that requested it.
  4. What it relied on. The invocation's uses list 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.

ControlWhat it bounds
limits.model_calls, limits.tool_calls, limits.total_tokensOne invocation's model calls, recorded calls, and tokens. A turn over a limit fails with agent_limit_exceeded and is not retried.
responseTimeoutOne turn: 5 minutes by default for agents, at most 10.
model.max_tokens, model.effortOutput and reasoning per model call.
A preset's model, harness.context.summary.model, harness.memory.modelA cheaper model for helpers, summaries, or memory extraction.
session.turnsHow often a session works: which inputs start a turn, and a window that gathers a burst into one turn.
harness.memory.extraction.everyHow 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

ToDo
Try an agent on real events safelySet 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 toolGive its reference approval: REQUIRED, so each call waits for a person. See Approvals.
Stop new workDisable the agent with updateAction(input: { enabled: false }). It stops matching new events. See Publication status.
Stop one sessioncloseSession 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 runcancelExecution. See Cancellation.
Find failing turnsList executions with status: FAILED, and read invocation.error. See Executions.
Test a change before you ship itreplayExecution reruns a recorded turn with another version, or an unpublished definition, and commits nothing. See Preview and Replay.
Review or remove what it remembersList 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.

Previous
Models