Tool contract
This page describes the contracts that connect tools, policy, approval, hooks, and panels. The current versions are:
| Contract | Version | Covers |
|---|---|---|
| Tool API | raw.tool-api/2 |
Tool manifests, argument validation, effects, and conditional predicates. |
| Panel | raw.panel/2 |
Live side panels and their blocks. |
| Hook | raw.hook/2 |
Hook manifests, event payloads, and decisions. |
Arguments and intended effects
Section titled “Arguments and intended effects”A tool call has two separate kinds of data:
- Arguments are the original input from the model, after validation. They are never rewritten. Hooks, approval, and the handler all see the same arguments.
- Intended effects describe what a call would change, such as the files it would write or delete. They are computed before policy runs.
Intended effects are not results. A call that was approved and then failed has intended effects but no completed outcome. Effects are also not a security boundary, since the handler can still do anything its code permits.
Dispatch order
Section titled “Dispatch order”For each tool call, Raw runs these steps in order. A failure at any step stops the call before the next step.
- Check that the tool is exposed, and that no unconditional
denyrule applies. - Validate the whole input against the JSON Schema and the tool’s
validateArgs. - Prepare intended effects, if the tool declares them, and validate the result.
- Evaluate conditional policy (
tools.rules). - Run
PreToolUsehooks. - Ask for approval when a rule requires it.
- Run the handler.
Effect descriptors must be synchronous and bounded. They may parse and normalize paths, but they must not read files, call a provider, run a shell, or change anything. A descriptor that returns a promise, or that throws, stops the call before the handler runs.
Manifest fields
Section titled “Manifest fields”A tool manifest with api_version: 2 declares the following. Manifests reject unknown fields.
| Field | Required | Description |
|---|---|---|
api_version |
Yes | 2. |
id |
Yes | Folder ID. |
version |
Yes | major.minor.patch. |
name |
Yes | Model-facing name. |
description |
Yes | What the tool does and what its result means. |
input_schema |
Yes | JSON Schema for the arguments. |
entry |
Yes | Module that exports handler and optionally validateArgs, describeEffects. |
condition_sources |
No | Sources a predicate may inspect: arguments and effects. |
effects_schema |
No | Object schema for the effects the tool declares. Required when the tool supports effects. |
panels |
No | Up to four panel declarations. See Panels. |
Predicates
Section titled “Predicates”Every conditional rule states its source explicitly. The source must be one of the tool’s declared condition_sources.
{ "source": "effects", "any": "files[*].path", "regex": "protected\\.txt$" }| Field | Meaning |
|---|---|
source |
arguments or effects. |
any |
A dotted path with [*] for each array step. It must resolve to a string field in the source’s schema. |
regex |
An RE2 pattern, unanchored. |
A path that does not exist in the schema is a validation error. A field that is absent from a valid value does not match. Policies and hook subscriptions use the same predicate evaluator.
Write effects
Section titled “Write effects”The write_file tool declares effects for both its operations form and its patch form.
Each effect is an object with an absolute, lexically normalized path and an operation:
| Operation | Produced by |
|---|---|
write |
overwrite, append, replace_text, replace_lines, and patch add or update. |
delete |
Patch delete. |
rename_source |
Patch move, for the original path. |
rename_destination |
Patch move, for the new path. |
Paths are lexical. A symbolic link is not resolved. Every operation and patch target appears in the effects, so a rule on files[*].path covers both forms.
{ "source": "effects", "any": "files[*].path", "regex": "/protected/" }Approval
Section titled “Approval”When a rule requires approval, the approval callback receives one request object with these fields:
| Field | Description |
|---|---|
identity |
The tool’s canonical identity. |
name |
The model-facing name. |
arguments |
The original arguments. |
effects |
The intended effects, when the tool declares them. |
toolCallId |
The call’s ID. |
signal |
An abort signal. |
The interface shows intended effects apart from the raw arguments. Approving a call does not change its arguments, and it does not turn intended effects into a completed outcome.
Hook payloads
Section titled “Hook payloads”Hooks declare protocol_version: 2. For tool events, the payload contains:
| Field | Description |
|---|---|
tool.arguments |
The original arguments. |
tool.effects |
The intended effects, when the tool declares them. |
tool.source |
"model" for a model call, or "user_action" for a panel action run from the dashboard. A missing value means "model". |
Conditions on effects use the separately declared effects schema. See Hooks for the response protocol.
Panels
Section titled “Panels”A panel is a live view that a tool keeps up to date. Panel state never goes to the model, except for one short confirmation line.
Declaration
Section titled “Declaration”Declare panels in tool.json (panels), in the server’s config (for MCP), or by registration over ACP. Each declaration has these fields:
| Field | Description |
|---|---|
id |
Panel ID, unique within the tool. |
title |
Title shown to the user. |
icon |
Optional. Unknown icons fall back to panel with a warning. |
placement |
sidebar (default) or chat. |
context |
Optional. summary panels also send a bounded reminder to the model after a compaction. |
acp_plan |
Optional. Sends the panel’s checklist as an ACP plan. |
actions |
Optional. Menu items on the panel. |
A chat placement shows the panel inline in the conversation. A sidebar placement shows it in the side panel.
Updates
Section titled “Updates”A tool updates a panel in one of two ways:
- Return a result block of the form
{ "type": "panel", "panel": "<id>", "op": "replace" | "patch" | "close", ... }next to its normal content. Raw removes this block before hooks, caps, providers, and history see the result. - Call
context.panels.update(panel, body)while the handler runs. The call resolves with the newrevision.context.panels.get(panel)returns the last revision and document.
Panel updates are included with the tool result, including when the result is an error.
Blocks
Section titled “Blocks”A panel document is made of blocks. The same block catalog is used in both placements.
| Block | Description |
|---|---|
form |
A request for input, with text, single-select, or multi-select fields. |
mermaid |
A diagram, with its source. If rendering is unavailable, the source is shown as text. |
Form response actions submit or cancel a pending request. They never grant tool permission.
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Declared panels per tool | 4 |
| Panels per session | 16. A closed panel is evicted to make room. |
| Updates per panel per call | 200 |
| Document size | 64 KiB |
Panel actions
Section titled “Panel actions”A panel action is a menu item that runs when the user selects it.
promptactions draft a message for the user. They run in the browser or client.toolactions run the declaring tool again through the normal tool path. Itsallow,ask, anddenyrules and its hooks apply. A click is never approval for anaskrule.
Errors
Section titled “Errors”Panel errors use these codes: panel_invalid, panel_too_large, panel_undeclared, panel_not_owned, panel_unknown, panel_revision_conflict, panel_rate_limited, panel_limit, and panel_closed_context.
A rejected update in a result block never fails the tool. The model receives a line such as panel <id> update rejected: <code> <message>, and the history records the error.
Interaction requests
Section titled “Interaction requests”A local tool can ask the user a question with context.interactions.request({ panel, document, timeout_ms? }). The request contains exactly one form block.
- The default deadline is 30 minutes. A caller may set up to 24 hours.
- A request has one of these states:
pending,answered,cancelled,expired, orinterrupted. - Cancelling the turn cancels the request. Reconnecting a browser leaves the wait in place.
- An answer is validated against the form, and invalid answers are kept pending.
- Answering a question never grants permission for a tool.
The ask_user tool uses this interface. A piped or non-interactive run returns interaction_unavailable immediately.
Related
Section titled “Related”- Tools covers manifests, selection, and rules from a user’s perspective.
- Hooks covers the hook protocol and examples.
- Architecture describes how the registry, policy, and sessions fit together.