Runtime tools
Define runtime tools inline in a dispatch request instead of saving them to your account. Use them for SDK-driven workflows, temporary configurations, testing, and one-off tasks. Runtime tools support five types: external, custom, Flow, subagent, and local.
When to use runtime tools
Use runtime tools in the following cases:
- Define tools dynamically in an SDK-driven workflow.
- Test a tool configuration before you save it.
- Keep a temporary tool out of your account’s saved tool definitions.
- Define a self-referential tool that calls the Runtype API.
Tool types
Every runtime tool needs a name, a description, a toolType, and a parametersSchema. The parametersSchema must be a JSON Schema object with "type": "object" at the top level. Every type except local also needs a config object.
Choose one of the following runtime tool types.
External
Call an HTTP API. Set config.url and config.method, and optionally set config.headers and config.body. The method is GET, POST, PUT, or DELETE. The body is a JSON string, not an object. Use template variables such as {{city}} for tool parameters and {{secret:WEATHER_API_KEY}} for managed secrets in the URL, headers, and body.
The following example defines an external tool that sends a JSON body:
The subject and priority parameters supply the {{subject}} and {{priority}} values. Replace TICKETS_API_KEY with the name of the managed secret that stores the API key.
Custom
Run sandboxed JavaScript, TypeScript, or Python code. Set config.code, and optionally set config.language, config.sandboxProvider, and config.timeout. In the default environment, your code reads the tool inputs from the parameters object.
The following example calculates a discounted price with JavaScript:
The timeout value is in milliseconds, up to 30000. Set language to javascript, typescript, or python. The default is javascript.
The sandboxProvider field selects the execution environment. The default, cloudflare-worker, runs JavaScript only. For TypeScript or Python, set sandboxProvider to runtype-sandbox or daytona. Otherwise, the tool call fails with an unsupported-language error. For how each environment passes parameters, see Creating custom tools.
Custom tool code has no network access unless the tool sets networkAccess. To send a managed secret, declare it in secrets: the code receives a placeholder token as secrets.NAME, and the egress proxy replaces it with the real value only on requests to the declared host. For the fields, see Call an API from custom code.
Flow
Run a Flow as a tool. Set config.flowId to the saved Flow ID and use parameterMapping to map tool inputs to Flow inputs.
By default, the tool returns the value that the Flow’s final executed step wrote to its output variable. For example, it returns what a trailing transform-data step returned. The following optional fields narrow that value:
outputVariablereturns a named Flow variable instead of the final step output. The variable must be assigned during the run, and names that begin with_are reserved.outputMappingis a dot path into the value that the tool returns. Suppose the final step writes{ "score": 0.9 }to its output variableanalysis. Bothscoreandanalysis.scorereturn0.9.
The following example maps a tool input to a saved Flow:
Replace YOUR_FLOW_ID with the ID of the Flow that you want to run.
On an agent dispatch, a Flow tool can also define the Flow inline. Replace flowId with a flow object that has a non-empty steps array. Runtype rejects an inline flow on a Flow dispatch prompt step and on an agent execute request. Reference a saved Flow with flowId there.
Subagent
Delegate a focused task to a child agent. The child runs in its own context window and returns only its final result to the parent. By default, the child doesn’t receive the parent’s conversation. Set inheritMessages to true to pass the current messages to the child.
Subagent tools use exactly one of agentId or agent. Set allowedTools to limit the child to a subset of its own configured tools.
The following example runs a saved agent as a subagent tool:
Replace YOUR_AGENT_ID with the ID of the saved agent. To define the child inline, replace agentId with an agent object and keep only one of these fields.
The following fields configure a subagent tool:
Run a subagent in the background
By default, a subagent tool runs attached: the parent waits for the child’s result. Set execution.mode to detached to start the child in the background. The tool call returns a run handle right away, and the parent continues its turn.
The following fields configure a detached subagent:
The narrate notice requires a saved parent agent and a conversationId on the request. Without them, set notify to none.
Local
Run a local tool in the client that drives the dispatch. A local tool doesn’t need a config object. When the model calls the tool, Runtype pauses the run and streams the tool name and parameters to your client. Your client runs the handler and resumes the execution with the result.
Use local tools for actions that must run in the caller’s environment, such as prompting the end user or reading local state. An SDK process or CLI session can run local tools. The Runtype dashboard doesn’t run your local tools.
The following example defines a local tool:
The TypeScript SDK runs the pause-and-resume loop for you. The following example runs a saved agent with one local tool:
Replace YOUR_AGENT_ID with the ID of the saved agent, and replace promptInTerminal with your own function that returns the answer. To handle the pause and resume yourself, see Pause and resume on an agent dispatch.
Local tools run only when a live caller drives the execution. On an unattended run, such as a messaging channel, a webhook, or a batch run, Runtype removes local tools from the turn and logs a warning that names them. Use an external, custom, or Flow tool for work that must run unattended.
Let an agent spawn subagents
Let an agent choose what to delegate at runtime by adding subagentConfig to its tools configuration. Runtype adds the built-in spawn_subagent tool. For each call, the model chooses the task, the tools from toolPool, and an optional system prompt.
The following tools configuration enables dynamic subagent spawning:
The toolPool must be a subset of the parent’s resolved tools. Set allowNesting to true to let a subagent spawn its own subagents.
The following fields control dynamic subagent spawning:
Pass runtime tools in a dispatch request
Add runtime tools to the tools.runtimeTools array on a prompt step.
The following request defines one runtime external tool on the Assistant prompt step:
The {{query}} variable resolves from the tool input. The flowMode value virtual runs the inline Flow without saving it.
Combine runtime tools with saved tools and built-in tools in the same prompt step.
The following configuration combines a saved tool, a built-in tool, and a runtime tool:
Replace YOUR_TOOL_ID with the ID of the saved tool.
Add runtime tools to an agent dispatch
To give a saved agent extra tools for one request, add them to agent.tools.runtimeTools. The agent’s saved tools stay available.
The following request adds one runtime tool to a saved agent:
Replace YOUR_AGENT_ID with the ID of the saved agent. An agent execute request (POST /v1/agents/{id}/execute) also accepts runtime tools in tools.runtimeTools.
When an agent with Agent loop turned on has 20 or more tools, Runtype holds its runtime tools back behind a tool_search tool, and the model loads a runtime tool by searching for it. To send every runtime tool on every turn, add "toolSearch": { "enabled": false } to agent.tools. For the full behavior, see Tool search.
Secrets
Reference a managed secret by name in an external tool’s URL, headers, or body. To add a managed secret, open Settings and select Secrets.
The following example references a managed secret in an external tool header:
Replace WEATHER_API_KEY with the name of the managed secret. Other tool types can’t reference managed secrets.
The API key that sends the dispatch request must have the SECRETS:READ or SECRETS:* permission to resolve secret references. Otherwise, the request fails with a 403 error.
Dispatch requests don’t accept a top-level secrets map. A non-empty map returns a 400 error. An agent dispatch returns RUNTIME_AGENT_TRANSIENT_SECRETS_UNSUPPORTED, and a Flow dispatch returns RUNTIME_FLOW_TRANSIENT_SECRETS_UNSUPPORTED. An empty map is ignored. Runtype encrypts managed secret values at rest and doesn’t log them or return them in responses.
Hide parameters from the model
Add hiddenParameterNames to a runtime tool to fill a parameter from an execution variable instead of from the model. Runtype removes each listed parameter from the schema that the model sees. When the tool runs, Runtype sets the parameter to the execution variable with the same name, and that value replaces any value the model sent.
The following example hides the _tenant parameter and uses it in a request header:
Replace ORDERS_API_KEY with the name of the managed secret that authenticates Runtype to your API. Runtype merges hidden values into the tool arguments before it fills the URL, headers, and body, so {{_tenant.id}} resolves from the hidden _tenant value.
Runtype resolves a hidden parameter based on its name:
Use _tenant and _endUser for identity values. Runtype sets these variables from the execution’s end-user identity, not from the model, so the model can’t change them. For how Runtype establishes that identity, see End-user identity and credentials.
Only _tenant and _endUser come from Runtype’s identity handling. Do not rely on another name
with a leading _ to keep caller-supplied values out of a tool call.
Also authenticate Runtype to your backend with a {{secret:NAME}} header, so your API does not trust a request on the hidden value alone.
Runtype replaces resolved hidden values with [REDACTED] in the tool_start and tool_input_complete stream events. The hiddenParameterNames field on those events lists the redacted parameters. The tool receives the real values.
You can set hiddenParameterNames on runtime tools in dispatch requests, in saved agent definitions, and in the tools.runtimeTools override of an agent execute request.
Use the verified identity in a saved tool
A tool saved in your account and attached by tool ID has no hiddenParameterNames field. Instead, Runtype treats _endUser and _tenant as hidden in a tool that references them in either of these ways:
- An external tool’s
url,headers, orbodycontains a template such as{{_endUser.id}}or{{_tenant.id}}. - The tool’s
parametersSchemahas a property named_endUseror_tenant.
For such a tool, Runtype applies the rules for a hidden name with a leading _:
- Runtype removes the property from the schema that the model sees.
- Runtype fills the value only from the execution’s
_endUseror_tenantvariable. The model’s tool arguments and the requestmetadatacannot supply it. - If the execution has no value, Runtype doesn’t call the tool. The model receives an error as the tool result. The exception is a root that the tool references only before a template fallback, such as
{{_endUser.id || 'guest'}},{{_endUser.id ?? 'guest'}}, or{{_endUser.id|guest}}. Runtype then calls the tool and the template renders the fallback. - Runtype sends the value only where the tool’s templates reference it. Runtype doesn’t add it to the query string or to a body it builds from the remaining arguments.
The same rules apply to an inline runtime tool that references _endUser or _tenant without declaring it in hiddenParameterNames, and to a saved tool that a Flow’s tool-call step calls. A tool-call step’s own _endUser or _tenant parameter never replaces the execution’s value.
A Flow that runs as a tool gets _endUser and _tenant from the execution that called it, never from the tool arguments. If that execution has no verified identity, the nested Flow has no _endUser or _tenant variable.
Pass the verified identity to an MCP server
To send the verified tenant or end user to a remote MCP server, add a header template to the server in the agent’s tools.mcpServers. Use the headers auth type:
Replace ERP_MCP_TOKEN with the name of the managed secret that authenticates Runtype to your MCP server. You do not declare hiddenParameterNames for an MCP server. Runtype treats every header value that references a variable with a leading _ as a hidden identity value:
- Runtype fills
{{_tenant.id}}only from the execution’s_tenantvariable. The model’s tool arguments and the requestmetadatacannot supply it. - If the execution has no
_tenant, Runtype does not call the MCP tool. The model receives an error as the tool result. - If the model sends an argument named
_tenant, Runtype removes it from the call. - Runtype sends the header on tool calls only. The
tools/listrequest that discovers the server’s tools does not include it.
This applies to MCP servers on an agent and on a Flow’s prompt step. It does not apply to MCP servers saved in your account and attached by tool ID, because Runtype resolves those headers from the saved server.
To let the MCP server verify the identity itself, use "Authorization": "Bearer {{_identity.token}}". Runtype signs a short-lived assertion for the server’s host on each tool call. For the claims and how to verify them, see Send a verifiable identity assertion to your API.
MCP credentials go on the server, never on a saved MCP tool. A saved MCP tool only points at a server, so its config rejects {{secret:NAME}} references. Put the credential in one of these places instead:
- The
authof a server you register withPOST /v1/mcp/servers. Attach the server’s tools to the agent by tool ID. - The
auth.headersof the agent’stools.mcpServersentry, as in the preceding example.
Both accept {{secret:NAME}} references. Only the tools.mcpServers entry can also carry {{_tenant.id}}.
Retry tools safely after an interrupted run
A run can be interrupted while a tool call is in progress. When the run resumes, Runtype doesn’t call that tool again automatically, because it can’t tell whether the first call finished. If the model calls the tool again, it receives an error that asks it to check the result before it retries. The model then decides whether to check, retry, or move on.
A tool that only reads data is safe to call again. To let a resumed run call it again, set idempotent to true:
Leave idempotent unset for any tool that writes, sends, charges, or creates. Built-in tools that only read or search are already marked safe to call again. MCP tools follow the server’s idempotentHint and readOnlyHint annotations.
Require a committed intent before a tool runs
Before an Agent calls a server-side tool, Runtype records an intent: a durable note that the call is about to start. By default the intent is best-effort. If Runtype can’t record it, the tool still runs.
Set tools.intent to mandatory on an Agent so that a tool that isn’t idempotent runs only after its intent is recorded:
tools.intent accepts mandatory or best-effort. The default is best-effort.
With mandatory, if Runtype can’t record the intent, it doesn’t call the tool. The tool call fails, and the model receives an error that starts with TOOL_INTENT_NOT_COMMITTED:
The call had no effect, so the model can call the tool again.
The setting has these limits:
- It applies to Agents only. A flow prompt step doesn’t record tool intents, so the flow validator warns with
TOOL_INTENT_POLICY_AGENT_ONLYwhen a prompt step sets it. - It applies only where the run keeps a tool journal, which durable Agent runs do. A run without a tool journal calls the tool as it would without the setting.
- Tools marked
idempotentkeep the best-effort intent, because calling them again is safe. - A dispatch request can set
tools.intenttomandatoryfor a saved Agent. A request can’t lower a saved Agent’smandatorytobest-effort.
Each intent also records whether the tool was idempotent when the call started. When a run resumes after an interruption, Runtype calls an interrupted tool again only if it was idempotent then and is still idempotent now. Marking a tool idempotent later doesn’t make an interrupted call run again. Removing idempotent stops an interrupted call from running again.
Ask the end user for tool inputs
An external or custom tool can ask the end user for some of its inputs before it runs. The model fills the other parameters, and the end user fills the requested fields in a form.
To ask for input, add config.elicit with a message, a requestedSchema, and "merge": "parameters". The following example asks the end user for the meeting date:
The model sees only the topic parameter. When it calls the tool, the end user sees the message and a form for date. Runtype merges the answer into the tool parameters and then calls the API.
The tool definition must follow these rules:
- Set
"additionalProperties": falseon bothparametersSchemaandrequestedSchema. - Define each requested field exactly as it appears in
parametersSchema, with the same required setting. - Use only
string,number,integer, andbooleanfields. Each field can have a title, a description, an enum, string length bounds, and numeric bounds. - Don’t request a field whose name starts with
_or that is listed inhiddenParameterNames.
If the end user cancels or declines the form, Runtype doesn’t call the tool. The model receives a cancellation result instead.
Tool input requests work on AG-UI surfaces for top-level agent calls that use a Surface key. They don’t work inside subagent calls, in Claude Managed Agents, or in Persona. For the stream events and the resume request, see Ask for input before dispatch.
Limits
Runtime tools have the following limits:
- Runtime tools per request: no limit on the number of tools. The
runtimeToolsin a request can be at most 1 MB in total, across all steps, when serialized as JSON. - External tool request timeout: 30 seconds.
- Custom tool
timeout: 30,000 ms at most. Saved custom tools accept longer timeouts. For more information, see Creating custom tools. - Subagent tool timeout:
timeoutMs, 5 minutes by default. - Inline MCP servers per prompt step: 5.
A model provider can reject a long tool list even though Runtype accepts it. For example, OpenAI accepts at most 128 tools. Runtype reports that rejection with the error code TOOL_COUNT_REFUSED_BY_PROVIDER. For a large tool set, use a multi-turn Agent with tool search, which loads runtime tools only when the model searches for them.
For client tool limits and MCP tool call timeouts, see Limits in the developer guide.
Troubleshoot validation errors
Runtype validates runtime tools before the run starts. An invalid tool returns an HTTP error with an error message, and nothing runs. The most common causes are the following:
- A missing
name,description,toolType,parametersSchema, or non-localconfig. - A
parametersSchemawithout"type": "object"at the top level. - A tool name that matches the reserved
runtype_set_statename after Runtype lowercases it and replaces other characters with_. - A custom tool
timeoutgreater than30000. - An inline subagent
agentwithoutallowedTools.
For the full list of error messages and fixes, see Troubleshooting in the developer guide.
Next steps
Continue with one of the following pages:
- Creating custom tools: save sandboxed code tools
- Creating external tools: save HTTP API tools
- Managing secrets: add the secrets that external tools reference
- Runtime tools developer guide: pause and resume executions, grant tool approvals, and use client-side tools
- What are Tools?: compare tool types
- Tool approvals: require approval before a tool runs, and approve or resume from the API