Writing actions
Context variables
The agent does not need to see your data in order to route it. Arguments enter a run as named variables, and the runtime substitutes real values in the moment before a tool call executes.
The model works with the names of your values. The runtime supplies the values.
How substitution works
Every argument becomes a $-prefixed entry in the run’s context. When the model calls a tool and passes a variable name, the runtime swaps in the value on the way out.
args { password: "correct-horse…" } → ctx { $password: "correct-horse…" }In the transcript
hashPassword({ raw: "$password" })What the runtime sends
hashPassword({ raw: "correct-horse…" })What that buys you:
- Payloads stay out of your prompt, and therefore out of any provider’s logs.
- Token counts stay flat regardless of how large the values are — a short id and a large document cost the same to route.
Capturing results back into context
Tool results can flow the same way. Declare which fields of a response to capture and they become new variables, without the payload ever reaching the model.
responseMaps — for MCP tools
mcpServers: { Postgres: { command: "npx", args: ["-y", "some-postgres-mcp-server"], // After `insert` runs, capture two fields into context. responseMaps: { insert: { $userId: "rows[0].id", $planType: "rows[0].plan" }, }, },},With a responseMap in place, the agent is told only ok. captured: $userId, $planType instead of the payload. The next tool call — sending the welcome email — can reference $userId without the row having passed through the model.
contextOutput — for custom tools
custom: { hashPassword: Object.assign( tool(async ({ raw }) => bcrypt.hash(raw, 10), { /* … */ }), { contextOutput: { $hashedPassword: "." } }, // "." captures the whole result ),},Path expressions
Both responseMaps and contextOutput use the same path syntax to pick fields out of a result.
| Expression | Selects |
|---|---|
field | A top-level field. |
nested.field | A field one or more levels down. |
array[0].field | A field of a specific element. |
array[].field | That field from every element — extracts a column. |
. | The whole result. An empty string does the same. |