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

Choose one of the following runtime tool types.

External

Call an HTTP API. Configure the URL, method, headers, and body in config. Use template variables such as {{city}} for tool parameters and {{secret:WEATHER_API_KEY}} for managed secrets.

The following example defines an external tool that requests weather data:

External tool
1{
2 "name": "get_weather",
3 "description": "Get current weather for a city",
4 "toolType": "external",
5 "parametersSchema": {
6 "type": "object",
7 "properties": {
8 "city": { "type": "string" }
9 },
10 "required": ["city"]
11 },
12 "config": {
13 "url": "https://api.example.com/v1/current?city={{city}}",
14 "method": "GET",
15 "headers": {
16 "Authorization": "Bearer {{secret:WEATHER_API_KEY}}"
17 }
18 }
19}

The city parameter supplies the {{city}} value. Replace WEATHER_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 and config.timeout.

The following example calculates a discounted price with JavaScript:

Custom tool
1{
2 "name": "calculate_discount",
3 "description": "Calculate a discount percentage",
4 "toolType": "custom",
5 "parametersSchema": {
6 "type": "object",
7 "properties": {
8 "price": { "type": "number" },
9 "discount": { "type": "number" }
10 },
11 "required": ["price", "discount"]
12 },
13 "config": {
14 "code": "return { discounted_price: price * (1 - discount / 100) }",
15 "timeout": 5000,
16 "language": "javascript"
17 }
18}

The timeout value is in milliseconds. Set language to javascript, typescript, or python; the default is javascript.

Flow

Run a saved Flow as a tool. Set config.flowId to the saved Flow ID. Use parameterMapping to map tool inputs to Flow inputs and outputMapping to extract a value from the Flow result.

The following example maps a tool input to a saved Flow:

Flow tool
1{
2 "name": "analyze_sentiment",
3 "description": "Run sentiment analysis on text",
4 "toolType": "flow",
5 "parametersSchema": {
6 "type": "object",
7 "properties": {
8 "text": { "type": "string" }
9 },
10 "required": ["text"]
11 },
12 "config": {
13 "flowId": "YOUR_FLOW_ID",
14 "parameterMapping": { "input_text": "text" },
15 "outputMapping": "sentiment_result"
16 }
17}

Replace YOUR_FLOW_ID with the ID of the Flow that you want to run.

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 does not 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 tools that the child can use. Runtype intersects that list with the parent’s available tools.

The following example runs a saved agent as a subagent tool:

Subagent tool
1{
2 "name": "research_topic",
3 "description": "Research a topic and return a summary",
4 "toolType": "subagent",
5 "parametersSchema": {
6 "type": "object",
7 "properties": {
8 "task": { "type": "string" }
9 },
10 "required": ["task"]
11 },
12 "config": {
13 "agentId": "YOUR_AGENT_ID",
14 "allowedTools": ["builtin:exa", "builtin:firecrawl"],
15 "maxTurns": 5,
16 "outputFormat": "text"
17 }
18}

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:

FieldDefaultDescription
agentIdNoneSaved agent ID. Set this or agent, not both.
agentNoneInline agent definition. Set this or agentId, not both.
allowedToolsRequired for inline agentsTools that the child can use. Runtype intersects this list with the parent’s available tools.
maxTurns5Maximum number of agent-loop iterations for the child.
maxCostParent budgetSpend cap for the child. The cost counts toward the parent’s budget.
timeoutMs300000Time limit for the child in milliseconds.
outputFormattextReturn text, json, or last_message.
inheritMessagesfalsePass the parent’s current messages to the child when set to true.
taskTemplateNoneTemplate the child’s first message from the tool-call parameters.

Dynamic subagents (spawn_subagent)

Let an agent choose what to delegate at runtime by adding subagentConfig to its tools configuration. Runtype adds the built-in spawn_subagent tool. The model chooses the task, tools from toolPool, and an optional system prompt for each call.

The following tools configuration enables dynamic subagent spawning:

Dynamic subagent configuration
1{
2 "tools": {
3 "toolIds": ["builtin:exa", "mcp:linear:create_issue"],
4 "subagentConfig": {
5 "toolPool": ["builtin:exa", "mcp:linear:*"],
6 "defaultMaxTurns": 5,
7 "maxTurnsLimit": 10,
8 "maxSpawnsPerRun": 5,
9 "allowNesting": false
10 }
11 }
12}

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:

FieldDefaultDescription
toolPoolRequiredTools that the parent can grant to spawned subagents.
defaultMaxTurns5Default turn cap for each spawned subagent.
maxTurnsLimit10Maximum turn cap that a spawned subagent can use.
maxSpawnsPerRun5Maximum number of spawned subagents per parent run.
defaultModelParent modelModel that spawned subagents use by default.
allowNestingfalseWhether a subagent can spawn its own subagents.
defaultTimeoutMs300000Default time limit for each spawned subagent in milliseconds.

Local

Run a local tool in the client that drives the dispatch. When the model calls it, Runtype pauses the run and sends the tool call to that client. The client runs the handler and resumes the run with the result. A local tool does not need a config object.

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 does not implement your local tool.

The following example defines a local tool without a config object:

Local tool
1{
2 "name": "ask_user",
3 "description": "Ask the end user a clarifying question",
4 "toolType": "local",
5 "parametersSchema": {
6 "type": "object",
7 "properties": {
8 "question": { "type": "string" }
9 },
10 "required": ["question"]
11 }
12}

Passing 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:

Dispatch request
1{
2 "flow": {
3 "name": "My Assistant",
4 "steps": [
5 {
6 "id": "step-1",
7 "type": "prompt",
8 "name": "Assistant",
9 "order": 1,
10 "enabled": true,
11 "config": {
12 "model": "gpt-5.4-mini",
13 "systemPrompt": "You are a helpful assistant.",
14 "tools": {
15 "runtimeTools": [
16 {
17 "name": "search_web",
18 "description": "Search the web",
19 "toolType": "external",
20 "parametersSchema": {
21 "type": "object",
22 "properties": {
23 "query": { "type": "string" }
24 },
25 "required": ["query"]
26 },
27 "config": {
28 "url": "https://api.example.com/search?q={{query}}",
29 "method": "GET"
30 }
31 }
32 ]
33 }
34 }
35 }
36 ]
37 },
38 "options": {
39 "streamResponse": true,
40 "flowMode": "virtual"
41 }
42}

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:

Combined tools
1{
2 "tools": {
3 "toolIds": ["YOUR_TOOL_ID", "builtin:exa"],
4 "runtimeTools": [
5 {
6 "name": "my_runtime_tool",
7 "description": "Run a runtime tool",
8 "toolType": "external",
9 "parametersSchema": {
10 "type": "object",
11 "properties": {}
12 },
13 "config": {
14 "url": "https://api.example.com/status",
15 "method": "GET"
16 }
17 }
18 ]
19 }
20}

Replace YOUR_TOOL_ID with the ID of the saved tool.

Secrets

Use managed secrets in hosted Flow execution. Open Settings and select Secrets to configure them. Reference a managed secret by name in supported HTTP fields.

The following example references a managed secret in an external tool header:

Managed secret reference
1{
2 "headers": {
3 "Authorization": "Bearer {{secret:WEATHER_API_KEY}}"
4 }
5}

Replace WEATHER_API_KEY with the name of the managed secret. Use managed secret references only in external tool configuration fields.

The top-level dispatch secrets map is retired on both dispatch targets: a non-empty map is refused with 400 RUNTIME_AGENT_TRANSIENT_SECRETS_UNSUPPORTED on an agent dispatch and 400 RUNTIME_FLOW_TRANSIENT_SECRETS_UNSUPPORTED on a flow dispatch. An empty map is accepted and does nothing. Managed secret values are encrypted at rest and are not logged or returned in responses.

Limits

Runtime tools have the following limits:

  • Runtime tools per request: 50 across all steps.
  • Custom tool timeout: 30 seconds.

Ask for input before dispatch

Saved and inline external and custom tools can declare config.elicit: { message, requestedSchema, merge: 'parameters' }. The final parametersSchema and requestedSchema must be closed objects. Requested fields belong to the human: their primitive types, constraints and requiredness must match the final schema. Supported field types are string, number, integer and boolean, with titles, descriptions, enums, string length bounds and numeric bounds. References, unsupported keywords, cross-field constraints, reserved names and hidden parameter overlap are rejected.

The model sees only the remaining parameters. The runtime validates those arguments, collects the human-owned fields, validates the merged object, then requests any ordinary approval for the final arguments. Approval resume reuses the validated input. Changing the tool definition or model arguments requires restarting the invocation. Cancel or decline skips dispatch and returns a cancellation result for the original tool call.

This requires a host that can persist and resume input. The portable runtime host opts in with enableToolElicitation: true; both agent and flow lanes support it. Authenticated root AG-UI agents use the existing form interrupt and resume endpoint. Nested product execution, managed agents and dashboard Persona clients without form-answer support remain disabled. Server tool arguments stay private unless the builder opts the tool in through the AG-UI surface’s behavior.discloseToolArguments.tools, for example ['schedule_meeting']. That rule exposes model-owned arguments in interrupt metadata and tool-call events. Hidden values are still removed before persistence and disclosure.

Unified streaming emits the existing await event with awaitReason: 'tool_elicitation' and the existing form elicitation payload. There is no new event type. Resume authorization and routing use the server’s checkpoint, not the displayed reason. MCP elicitation keeps its existing reason and resume behavior.

Next steps

Continue with one of the following pages: