# Native Tools

The tools every Twisp tenant has without creating them: what each does, who can use it, when to reach for it, and how its calls are recorded.

Every tenant has a set of **native tools** without creating them. They are [tools](https://www.twisp.com/docs/actions/tools.md) like your own: each is an action with a well-known `actionId`, a name, schemas, and policies, and every call of one is an [execution](https://www.twisp.com/docs/actions/triggers-and-executions.md#executions-as-records) with its input and output. What differs is who can use each one and how it is made available.

| Tool                                                                     | For         | What it does                                                             | How it is offered                                          |
| ------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------ | ---------------------------------------------------------- |
| [`graphql`](https://www.twisp.com/docs/actions/native-tools.md#graphql)                                                    | Everyone    | Runs a GraphQL query or mutation.                                        | Tool programs: always. Agents and MCP servers: in `tools`. |
| [`cel`](https://www.twisp.com/docs/actions/native-tools.md#cel)                                                            | Everyone    | Evaluates a CEL expression.                                              | Tool programs: always. Agents and MCP servers: in `tools`. |
| [Models](https://www.twisp.com/docs/actions/native-tools.md#models), such as `typesafe_jev`                                | Everyone    | Asks a provider's model typed questions.                                 | In `tools`, for tools, agents, and MCP servers.            |
| [`program`](https://www.twisp.com/docs/actions/native-tools.md#program)                                                    | MCP servers | Runs a Starlark program over the server's tools, atomically.             | Listed in the server's `tools`.                            |
| [`invoke`](https://www.twisp.com/docs/actions/native-tools.md#invoke)                                                      | MCP servers | Previews or runs one of your tools or agents.                            | Listed in the server's `tools`.                            |
| [`get_task`, `cancel_task`](https://www.twisp.com/docs/actions/native-tools.md#get-task-and-cancel-task)                   | MCP servers | Reads or cancels an agent's task, for hosts without the Tasks extension. | Listed in the server's `tools`.                            |
| [`read_turn_input`](https://www.twisp.com/docs/actions/native-tools.md#read-turn-input)                                    | Agents      | Reads one input of the turn whole.                                       | Automatically, when the turn needs it.                     |
| [`todo_write`](https://www.twisp.com/docs/actions/native-tools.md#todo-write)                                              | Agents      | Keeps a checklist across the turn and the session.                       | `harness.builtin_plugins: ["todos"]`.                      |
| [`search_memory`](https://www.twisp.com/docs/actions/native-tools.md#memory-tools)                                         | Agents      | Searches or lists the agent's memory.                                    | `harness.memory.enabled`.                                  |
| [`add_memory`, `read_memory`, `delete_memory`](https://www.twisp.com/docs/actions/native-tools.md#memory-tools)            | Agents      | Saves, reads, and deletes memory records.                                | `harness.memory.tools`.                                    |
| [`search_history`](https://www.twisp.com/docs/actions/native-tools.md#search-history)                                      | Agents      | Searches the session's earlier turns.                                    | `harness.history.index` other than `none`.                 |
| [`programmatic_tool_caller`](https://www.twisp.com/docs/actions/native-tools.md#programmatic-tool-caller)                  | Agents      | Runs a short program that calls the agent's tools.                       | `harness.builtin_tools`; on by default.                    |
| [`subagent`](https://www.twisp.com/docs/actions/native-tools.md#subagent)                                                  | Agents      | Hands a subtask to a helper.                                             | `harness.builtin_tools`.                                   |
| [`retrieve_offloaded_content`](https://www.twisp.com/docs/actions/native-tools.md#retrieve-offloaded-content)              | Agents      | Reads a large tool result that was set aside.                            | Automatically, with context management.                    |
| [`retrieve_context`](https://www.twisp.com/docs/actions/native-tools.md#retrieve-context)                                  | Agents      | Reads content the context manager set aside.                             | Automatically, with context management.                    |
| [`summarize_context`, `truncate_context`, `pin_context`](https://www.twisp.com/docs/actions/native-tools.md#context-tools) | Agents      | Summarize or drop older messages, or pin messages to keep.               | `harness.context.manager: agentic`.                        |

The local environment's `default` MCP server also offers [`audit`](https://www.twisp.com/docs/actions/native-tools.md#audit), which is not a native tool but an ordinary tool the environment installs.

## How native tools behave

- **Listed like any action.** `actions(where: { native: true })` lists every native tool, and `action(id:)` reads one by its `actionId`. Their definitions are fixed at version 1, except a model's, which gains a version with each release, and their names are reserved: no tool or skill of yours can use them. See [Native tools](https://www.twisp.com/docs/reference/actions/tools.md#native-tools).
- **Policies are a layer.** Each native tool carries its own policies, a layer of the [policy chain](https://www.twisp.com/docs/reference/actions/actions.md#policy-chain) like any tool's. `graphql` allows everything, so a `graphql` call can do exactly what the layers above it allow, no more. `cel` allows nothing, since it performs no operation.
- **Some act for their caller.** `graphql` and `cel` act for no caller: you can call one with `invokeAction` or start one with `startAction`, given `INVOKE` on it. The others act for their caller: `program`, `invoke`, `get_task`, and `cancel_task` for an MCP server's request, and `read_turn_input` and the agent tools for an agent's turn. They run only as a call their caller makes. `invokeAction` on one fails with `action_not_callable`, and `startAction` with `start_not_supported`, and nothing is recorded. See [Limits and errors](https://www.twisp.com/docs/reference/actions/limits-and-errors.md).
- **Every call is recorded.** A native tool call is a child execution of whatever made it: a tool, an agent's turn, an MCP request, or a program. Its input is what the caller sent, its output is what the caller was shown, and the calls it makes in turn, such as those of a `program`, are its own children.

## Tools for everyone

### `graphql`

`graphql` runs one GraphQL query or mutation against the ledger with the caller's access, narrowed by every policy layer above it. Later calls in the same execution read earlier writes.

- **When to use it.** In a tool program, for every read and write. For an MCP server whose external agent should have the whole API, such as one an engineer builds with. Give it to an agent only when the agent truly needs arbitrary documents: declaring `graphql` gives the model the agent's full data access, so narrow tools with fixed input are usually the better choice.
- **How it is offered.** A tool program calls it as `graphql(query, variables)` without declaring it. An agent or an MCP server offers it only when its `tools` list it.
- **Input and output.** `query`, at most 64 KiB, with optional `variables` and `operation_name`. The output is `data`, the response's data as JSON. A response with errors fails the call with `action_graphql_error`, or `action_access_denied` for a permission error.
- **Recorded.** Each call is an execution of the native `graphql` tool, with the document and variables as its input and the data as its output. See [Native tools](https://www.twisp.com/docs/reference/actions/tools.md#native-tools).

### `cel`

`cel` evaluates a [CEL](https://www.twisp.com/docs/reference/cel.md) expression over optional bindings and returns its value. Money, decimals, and other domain values keep their types, so `money("10.50", "USD") + money("2.25", "USD")` returns `12.75 USD`.

- **When to use it.** To try an expression before it goes into a tran code, a trigger, or a fixed input, or for an agent that must compute exactly with money and decimals. A tool program rarely needs it: every CEL function is already a Starlark builtin there, and runs without a call. The ones that read the clock or randomness, such as `uuid.New()`, are `cel` calls.
- **How it is offered.** As for `graphql`: a tool program calls `cel(expression, bindings)` without declaring it, and an agent or an MCP server offers it only when listed.
- **Input and output.** `expression`, at most 16 KiB, and optional `bindings`. The output is `value`. A compile or evaluation error fails the call with `action_cel_error`.
- **Recorded.** Each call is an execution of the native `cel` tool. `cel` is always read-only, and an MCP server [annotates](https://www.twisp.com/docs/reference/actions/mcp.md#annotations) it so. See [Native tools](https://www.twisp.com/docs/reference/actions/tools.md#native-tools).

### Narrowing `graphql` and `cel`

To give an agent or an MCP server GraphQL access narrower than its own policies, create your own action of kind `graphql` with your own name, tool name, description, and policies. It takes the native tool's schemas, and its policies narrow what the native tool's allow. A `query` tool that may only read:

```graphql
mutation CreateQueryTool {
  actions {
    createAction(
      id: "5b0e3c7a-41d2-4f8e-9a6b-2c1d8e7f4a90"
      input: {
        name: "ledger-query"
        description: "Read-only GraphQL for agents."
        kind: "graphql"
        config: { version: 1 }
        tool: { name: "query", description: "Run a read-only GraphQL query against the ledger." }
        policies: [{ effect: ALLOW, actions: [SELECT], resources: ["financial.*"] }]
      }
    ) {
      actionId
      version
    }
  }
}
```

List it as `{ name: "ledger-query" }`, and the model sees a tool named `query`. A mutation through it fails with `action_access_denied`, and its hint names the layer that refused: `graphql "ledger-query" must allow db:Insert on ...`. An MCP server derives `readOnlyHint: true` for it from those policies, so hosts can call it without asking. `config.version` names the native version it runs, the current one when omitted.

An action of kind `cel` works the same way, such as a `calc` tool whose description tells the model what to compute with it. It needs no policies.

### Models

A model, such as `typesafe_jev`, asks a provider's model typed questions about a state and returns typed answers. Twisp ships each model and holds its provider's key. A tool, an agent, or an MCP server calls one only when its `tools` list it, and a tool program calls it as `tools.typesafe_jev(...)`. Each call sends its input outside Twisp, so an MCP server marks it, and whatever declares it, as open world.

Unlike `graphql` and `cel`, a model has no actions of your own: a write of kind `model` is rejected. To narrow one, fix part of its input in your reference to it; to give it another name or description, wrap it in a Starlark tool. See [Models](https://www.twisp.com/docs/actions/models.md).

### Why agents declare `graphql` and `cel` and programs do not

A tool program is code you wrote, reviewed, and published: every call it makes is your decision, and the program's own policies and the [policy chain](https://www.twisp.com/docs/reference/actions/actions.md#policy-chain) bound what those calls can do. So `graphql()` and `cel()` are part of the runtime, like `fail()`. An agent's model decides its own calls at run time. An agent is offered exactly what its definition lists, so you opt in to arbitrary GraphQL deliberately, by listing `graphql`, or give it a narrower tool instead. An MCP server is the same: it offers exactly the tools it lists, and a `program` or an `invoke` through it can use `graphql` and `cel` only when the server lists them.

## Tools for MCP servers

These tools act for an MCP server's request, and only an MCP server can list them. Each call is the request's one call: an execution of the native tool, a child of the request, recorded with the [stated intent](https://www.twisp.com/docs/reference/actions/mcp.md#stated-intent) on the request. See [MCP Servers](https://www.twisp.com/docs/actions/mcp-servers.md).

### `program`

`program` runs a Starlark program the external agent writes, over the server's own tools, as one unit: every write it makes commits together, or none does.

- **When to use it.** List it on a server an agent builds or operates with, so the agent can do a multi-step change atomically, such as creating accounts, a tran code, and a first transaction, and preview it first. It adds no access: a program can do nothing the server's tools could not do one call at a time.
- **When not to.** A server for a narrow job, such as a support desk, is clearer with its specific tools alone. `program` allows everything, so its annotations come from the server's policies, and hosts ask before every call unless the server is read-only.
- **Input and output.** `src`, at most 64 KiB, `input`, passed as `event["data"]`, and `commit`, required. With `commit: false` the result is `{value, writes, unreadable_writes, omitted_writes}`: what `run` returned, and the rows it would write that the principal may read. With `commit: true`, `{value}`.
- **Recorded.** An execution of the native `program` tool whose input includes the source. Each call the program makes is its child, including those a failed program rolled back. See [Programs](https://www.twisp.com/docs/reference/actions/mcp.md#programs).

### `invoke`

`invoke` runs one of your tools or callable agents on an input the external agent chooses: a stored version, or an unpublished draft. With `commit: false`, the default, it previews and commits nothing; with `commit: true` it runs a published, enabled version for real.

- **When to use it.** On a server an agent builds tools and agents with, so it can create a tool disabled, preview drafts until it works, then enable it and check it live. List it only there: a draft can call any tool the principal and the server may invoke.
- **Input and output.** `action_id` and `input`, required, and optional `version`, `definition`, and `commit`. A tool answers at once with `execution_id`, `status`, `output` or `error`, and for a preview its `calls` and `writes`. An agent answers with a task: `task_id`, `status: "working"`, `poll_interval_ms`, and a `hint`.
- **Recorded.** An execution of the native `invoke` tool, with a draft in full. The invoked tool is its child; an invoked agent is started by the request. A refused invocation is that execution, `FAILED`. See [Invoking an action](https://www.twisp.com/docs/reference/actions/mcp.md#invoke).

### `get_task` and `cancel_task`

A callable agent runs for minutes, so a call that runs one answers with a task. Hosts with the MCP Tasks extension poll it with `tasks/get`. For hosts without it, a server that lists both `get_task` and `cancel_task` starts the task anyway and lets the agent poll and cancel it with tools; a server that does not list both refuses such a call with `mcp_task_required`.

- **When to use them.** List both on any server that offers a callable agent, or `invoke`, to hosts that may not have the extension. They reach only the tasks of the same server and session.
- **Input and output.** Both take `task_id`. `get_task` answers with `task_id`, `status` (`working`, `completed`, `failed`, or `cancelled`), `poll_interval_ms` while working, and the `result` of a completed task or the `error` of a failed one. `cancel_task` answers with `task_id` and a `hint`, also for a task that already finished. A task the session cannot reach is a tool error, `mcp_task_not_found`.
- **Recorded.** Each call is an execution of the native tool. The read that returns an agent's output records it as a `TOOL` use. `get_task` is read-only; `cancel_task` is not, since a running agent's writes roll back. See [Tasks](https://www.twisp.com/docs/reference/actions/mcp.md#tasks).

### `audit`

The [local environment's](https://www.twisp.com/docs/infrastructure/local-environment.md) `default` server also lists `audit`, a tool that reads the session's own record back. It is not native: it is an ordinary Starlark tool with `SELECT`-only policies that the environment installs alongside the server, and you can change it, copy it to your own server, or remove it like any of your tools.

- **When to use it.** Ask the agent to summarize what it designed and built, and why, or to find where something went wrong, from the record rather than its memory of the conversation.
- **Input and output.** The external agent passes optional `since`, `limit` (100 by default), and `include_discovery`; the server fixes `session_id` and `server` to its own. The output lists the session's most recent requests oldest first, each with `at`, `did`, the `intent` stated, `status`, an `error` if it failed, and its `execution_id`. The last few requests can take a moment to appear.
- **Recorded.** Like any tool call through the server. See [The default server](https://www.twisp.com/docs/reference/actions/mcp.md#the-default-server).

## Tools for agents

These tools act for an agent's turn. An agent never lists them in `tools`: its configuration enables them, or the turn offers them when it needs them. Each call is an execution of the native tool of its name in the agent's call tree, with the input the model supplied and the result it was shown, and each counts against `limits.tool_calls`. See [Agent tools](https://www.twisp.com/docs/reference/actions/agents.md#agent-tools).

### `read_turn_input`

`read_turn_input` returns one input of the turn whole, by its position.

- **When the model uses it.** A turn shows inputs inline up to 64 KiB, and lists the rest by position. A trigger's [view](https://www.twisp.com/docs/reference/actions/agents.md#input-views) shows only the fields the agent needs. The model reads the whole event when it needs more.
- **How it is offered.** Automatically, on every turn of a session agent, and to an agent without a session when its input is shown through a view.
- **Input and output.** `n`, the input's position. The output is the input: `n`, `identity`, `kind`, `type`, `committed_at`, the `triggers` it matched, and the event's `data` and `previous`.
- **Recorded.** An execution of the native `read_turn_input` tool with the input it returned. See [Agent tools](https://www.twisp.com/docs/reference/actions/agents.md#agent-tools).

### `todo_write`

`todo_write` keeps a checklist the agent maintains as it works, and the turn shows the current list to the model before each step. In a session, the list carries over to later turns.

- **When to use it.** For agents whose turns are multi-step work, such as a reconciliation with several checks, so the model tracks what it has done and what is left. A short, single-purpose turn does not need it.
- **How it is offered.** `harness.builtin_plugins: ["todos"]`.
- **Input and output.** `todos`, the whole updated list: each item has `content`, `activeForm` (shown while it is in progress), and `status`, `pending`, `in_progress`, or `completed`. An empty list clears it. The output is the list as the model will see it, with how many items remain.
- **Recorded.** An execution of the native `todo_write` tool with the list. See [Agent tools](https://www.twisp.com/docs/reference/actions/agents.md#agent-tools).

### Memory tools

With [long-term memory](https://www.twisp.com/docs/actions/memory.md) enabled, the agent recalls matching records before each model call, and has `search_memory` to search or list them itself. `harness.memory.tools` adds `add_memory`, `read_memory`, and `delete_memory`, so the model can save what it learns as it learns it, read a record whole, and delete one it shows wrong.

- **When to use them.** `search_memory` comes with memory. Add the others when the model should decide what to keep, not only the review at the end of each turn; leave them off to let only that review write.
- **Input and output.** `search_memory` takes `query`, `kind`, `labels`, `ids`, `limit`, and `after`. `add_memory` takes `summary` and `kind`, and `content`, `labels`, `scope`, `pinned`, and `replaces` as the configuration allows. `read_memory` and `delete_memory` take an `id`. A call the configuration does not allow fails with a message the model reads, and changes nothing.
- **Recorded.** A search's output lists the records it returned, and an automatic recall is recorded as a `search_memory` call with `recall: true`. An `add_memory` or `delete_memory` call lists the records it wrote or deleted in `memories`. Searches and recalls whose records reached the model are `RETRIEVED` uses. See [Agent memory](https://www.twisp.com/docs/reference/actions/memory.md#agent-memory).

### `search_history`

`search_history` searches what the session's earlier turns said: the messages, the agent's replies, and, if indexed, its tool results.

- **When to use it.** For session agents with long-running sessions, whose older messages get summarized and whose earlier tool results get cleared. The model is told to search before guessing at, or asking again for, something an earlier turn established.
- **How it is offered.** On every turn of a session agent whose `harness.history.index` is `messages` or `messages_and_tools`, unless `harness.history.search` is `false`.
- **Input and output.** `query`, `ids`, and `limit`. Each result has the event's `id`, its `turn`, and its text, after a line naming who it is from, such as `turn 1, assistant`. Pass a result's `id` in `ids` to read a long event whole.
- **Recorded.** An execution of the native `search_history` tool whose output lists the events returned, and a `RETRIEVED` use. See [Session history](https://www.twisp.com/docs/reference/actions/memory.md#session-history).

### `programmatic_tool_caller`

`programmatic_tool_caller` runs a short program the model writes, in a sandboxed subset of Python, that calls the agent's tools as async functions with keyword arguments. Only what the program prints comes back to the model; the tools' results stay in the program.

- **When to use it.** For turns that chain, loop over, or filter many tool calls, such as reading activity for twenty accounts and reporting three, without a model round trip per call or large intermediate results in the context. It is on by default.
- **When not to.** Turn it off, with `builtin_tools: []` or a list without it, for an agent whose every call should be a visible step of its own, or narrow it with `allowed_tools`. A program cannot call a tool that requires [approval](https://www.twisp.com/docs/reference/actions/sessions.md#approvals), or an operation that acts outside the ledger.
- **Input and output.** `code`. The output is the text the program printed.
- **Recorded.** An execution of the native tool whose children are the calls the program made. They commit together or not at all: when the program fails, none of their writes remain, and each stays recorded with `rolledBackByExecutionId`. See [Configuring agent tools](https://www.twisp.com/docs/reference/actions/agents.md#configuring-agent-tools).

### `subagent`

`subagent` hands a self-contained subtask to a helper that runs in its own context and returns a final report, so the subtask's intermediate work never fills the agent's context.

- **When to use it.** For research or review the agent only needs the conclusion of. Define presets to fix each helper's instructions, tools, model, and how much of the conversation it sees; then the model picks a preset and supplies only the task.
- **How it is offered.** `harness.builtin_tools`, with `subagent` named, as a list or a mapping with its configuration.
- **Input and output.** `task`, and with presets, `agent_type`, the preset to use. Without presets, the model may instead give the helper `instructions`, a subset of the agent's `tools`, and how much of the conversation it sees in `context`. The output is the helper's final reply.
- **Recorded.** An execution of the native tool whose children are the helper's calls, which commit with it. Each of the helper's model calls is in the agent's transcript with purpose `subagent`, and counts against the agent's limits. A helper can search memory but never write it. See [Configuring agent tools](https://www.twisp.com/docs/reference/actions/agents.md#configuring-agent-tools).

### `retrieve_offloaded_content`

A tool result larger than `harness.context.offload.over_tokens` is set aside, out of the context, and the model is shown a preview that keeps the result's shape, with a reference. `retrieve_offloaded_content` reads it back.

- **When the model uses it.** When the preview does not answer its question. Prefer a `pattern` or a `line_range` to the whole result, which brings every token back into the context.
- **How it is offered.** Automatically, with context management. A tool whose `tool.output.offload` is `NEVER` is never set aside; use that for a tool whose whole result the agent always needs.
- **Input and output.** `reference`, required, and optional `pattern`, a regular expression or keyword, `line_range`, `{start, end}`, and `context_lines` around each match, 5 by default. The output is the matching lines, numbered, or the whole result without a pattern or range.
- **Recorded.** An execution of the native tool with the reference and the text returned. See [Agent tools](https://www.twisp.com/docs/reference/actions/agents.md#agent-tools) and [`harness.context.offload`](https://www.twisp.com/docs/reference/actions/agents.md#agent-configuration).

### `retrieve_context`

`retrieve_context` reads back content the context manager set aside: a session agent's earlier turns' tool results, which each new turn clears by default, and content a summary replaced. The note left in its place names the reference.

- **When the model uses it.** When it needs an earlier result in full, such as the exact rows a check returned two turns ago. To find something an earlier turn said without a reference, it uses `search_history`.
- **How it is offered.** Automatically, with context management. `harness.context.prior_tool_results: keep` carries earlier turns' results forward instead of clearing them.
- **Input and output.** As for `retrieve_offloaded_content`: `reference`, and optional `pattern`, `line_range`, and `context_lines`.
- **Recorded.** An execution of the native tool with the reference and the text returned. See [Agent tools](https://www.twisp.com/docs/reference/actions/agents.md#agent-tools).

### Context tools

With `harness.context.manager` set to `agentic`, the model manages its own context: `summarize_context` replaces the oldest messages with a summary, `truncate_context` drops them, and `pin_context` marks messages that both must keep.

- **When to use them.** For agents whose turns run long and whose model should decide what it still needs, rather than summarizing at a fixed threshold as `auto` does. Pinning keeps constraints and key facts through every summary.
- **How they are offered.** `harness.context.manager: agentic`.
- **Input and output.** `summarize_context` takes optional `keep_recent`, `summary_ratio`, and `message_type`; `truncate_context` takes optional `keep_recent` and `message_type`; `pin_context` takes `select`, and optional `filter` and `action`. Each returns a line saying what it did.
- **Recorded.** An execution of the native tool of its name with its input and the line returned. A summary's model call, with purpose `compact`, is in the agent's transcript under the `summarize_context` call. See [Agent tools](https://www.twisp.com/docs/reference/actions/agents.md#agent-tools).

## Where to go next

- [Tools](https://www.twisp.com/docs/actions/tools.md): Write your own tools, call and start them, and nest calls.
- [Agents](https://www.twisp.com/docs/actions/agents.md): Configure an agent's tools, skills, memory, and context.
- [MCP Servers](https://www.twisp.com/docs/actions/mcp-servers.md): Offer tools to agents running outside Twisp.
- [Tools reference](https://www.twisp.com/docs/reference/actions/tools.md#native-tools): Native tools, the policy chain, and tool references.
