Working with Tools

Tools extend AI capabilities beyond text generation, allowing your flows to call APIs, execute code, search the web, generate images, and integrate with external services.

Tool Types Overview

Runtype supports several types of tools:

TypeDescriptionUse Case
ExternalHTTP API callsIntegrate with any REST API
CustomSandboxed code executionData transformation, calculations
FlowExecute another flow as a toolReusable AI workflows
Built-inProvider tools (DALL-E, etc.)Image generation, web search
MCPModel Context Protocol serversRich integrations (Slack, Notion, GitHub)

Adding Tools to a Flow

Tools are configured in the tools object of a prompt step:

TypeScript SDK
1import { FlowBuilder, RuntypeClient } from '@runtypelabs/sdk'
2
3const client = new RuntypeClient({
4 apiKey: process.env.RUNTYPE_API_KEY,
5})
6
7const result = await new FlowBuilder()
8 .createFlow({ name: 'Agent with Tools' })
9 .prompt({
10 name: 'Agent',
11 model: 'gpt-5.4',
12 userPrompt: 'Help the user with their request',
13 tools: {
14 toolIds: ['tool_abc123'], // Saved custom tools
15 maxToolCalls: 10, // Limit iterations
16 toolCallStrategy: 'auto', // 'auto', 'required', or 'none'
17 },
18 })
19 .run(client, { streamResponse: true })
Python SDK
1from runtype import RuntypeClient
2
3client = RuntypeClient(api_key=os.environ["RUNTYPE_API_KEY"])
4
5for event in client.dispatch({
6 "flow": {
7 "name": "Agent with Tools",
8 "steps": [{
9 "type": "prompt",
10 "config": {
11 "model": "gpt-5.4",
12 "userPrompt": "Help the user with their request",
13 "tools": {
14 "toolIds": ["tool_abc123"],
15 "maxToolCalls": 10,
16 "toolCallStrategy": "auto"
17 }
18 }
19 }]
20 }
21}):
22 print(event)
cURL
$curl https://api.runtype.com/v1/dispatch \
> -H "Authorization: Bearer YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "flow": {
> "name": "Agent with Tools",
> "steps": [{
> "type": "prompt",
> "config": {
> "model": "gpt-5.4",
> "userPrompt": "Help the user with their request",
> "tools": {
> "toolIds": ["tool_abc123"],
> "maxToolCalls": 10,
> "toolCallStrategy": "auto"
> }
> }
> }]
> }
> }'

Tool Call Strategy

The toolCallStrategy controls how the model uses tools:

StrategyBehavior
autoModel decides whether to call tools (default)
requiredModel must call at least one tool
noneTools available but not suggested

Use required only for a single forced tool call (maxToolCalls: 1, no agent loop) — for example, forcing a structured-output or routing tool. Do not combine required with a multi-step loop (maxToolCalls greater than 1, or an agent with loopConfig.maxTurns greater than 1): the model is then forced to call a tool on every step and can never finish with a text answer, so the response comes back empty. For multi-step agents, keep toolCallStrategy: "auto".

External Tools

External tools make HTTP requests to any API:

1// Create via API or dashboard, then reference by ID
2const externalTool = {
3 name: 'get_weather',
4 description: 'Get current weather for a city',
5 toolType: 'external',
6 parametersSchema: {
7 type: 'object',
8 properties: {
9 city: { type: 'string', description: 'City name' },
10 },
11 required: ['city'],
12 },
13 config: {
14 url: 'https://api.weather.com/v1/current?city={{city}}',
15 method: 'GET',
16 headers: {
17 Authorization: 'Bearer {{secrets.weather_api_key}}',
18 },
19 },
20}

Variable substitution: Use {{paramName}} in URLs and headers. Access secrets via {{secrets.keyName}}.

Custom Tools (Code Execution)

Execute JavaScript in a secure sandbox:

1const customTool = {
2 name: 'calculate_discount',
3 description: 'Calculate discounted price',
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: `
15 const discounted = price * (1 - discount / 100);
16 return {
17 original: price,
18 discounted: discounted.toFixed(2),
19 savings: (price - discounted).toFixed(2)
20 };
21 `,
22 timeout: 5000,
23 },
24}

Built-in Tools

Provider-specific tools that work with compatible models:

1tools: {
2 toolIds: [
3 'builtin:dalle', // DALL-E image generation
4 'builtin:web_search', // Web search (provider-dependent)
5 ]
6}

MCP Server Tools

MCP (Model Context Protocol) servers provide rich integrations. There are two ways to use them:

Saved MCP Servers

Configure once in your account, use anywhere by tool ID:

1tools: {
2 toolIds: [
3 'mcp:context7:resolve-library-id', // Context7 docs server
4 'mcp:myslack:send_message', // Your saved Slack server
5 'mcp:notion:create_page', // Your saved Notion server
6 ]
7}

Tool ID format: mcp:<serverName>:<toolName>

Runtime MCP Servers

Pass server config inline for dynamic credentials:

1tools: {
2 mcpServers: [
3 {
4 id: 'notion',
5 url: 'https://my-notion-mcp.example.com/mcp',
6 auth: {
7 type: 'bearer',
8 token: process.env.NOTION_MCP_TOKEN,
9 },
10 timeout: 30000,
11 },
12 ]
13}

See MCP Servers Guide for detailed MCP documentation.

Runtime Tools

Define tools inline without saving them:

1tools: {
2 runtimeTools: [
3 {
4 name: 'fetch_user',
5 description: 'Fetch user by ID',
6 toolType: 'external',
7 parametersSchema: {
8 type: 'object',
9 properties: {
10 userId: { type: 'string' },
11 },
12 required: ['userId'],
13 },
14 config: {
15 url: 'https://api.example.com/users/{{userId}}',
16 method: 'GET',
17 },
18 },
19 ]
20}

Runtime tools are ideal for:

  • Dynamic tool definitions
  • Testing before saving
  • User-provided tool configurations

See Runtime Tools Guide for more details.

Combining Tool Types

Mix different tool types in one prompt:

1tools: {
2 // Saved tools (by ID)
3 toolIds: [
4 'tool_abc123', // Custom saved tool
5 'builtin:dalle', // Built-in tool
6 'mcp:slack:send_message' // Saved MCP server tool
7 ],
8 // Inline runtime tools
9 runtimeTools: [
10 { name: 'temp_tool', ... }
11 ],
12 // Runtime MCP servers
13 mcpServers: [
14 { id: 'dynamic', url: '...', auth: {...} }
15 ],
16 maxToolCalls: 15,
17 toolCallStrategy: 'auto'
18}

Passing Secrets

Never hardcode API keys. Use the secrets field:

1const result = await client.dispatch({
2 flow: { ... },
3 secrets: {
4 weather_api_key: process.env.WEATHER_API_KEY,
5 notion_token: process.env.NOTION_TOKEN
6 }
7})

Access in tool configs: {{secrets.weather_api_key}}

Security: Secrets are never logged, stored, or returned in responses.

Best Practices

Set maxToolCalls to prevent infinite loops. Start with 5-10 for simple tasks, increase for complex agents.

Tool descriptions help the model understand when to use each tool. Be specific about inputs and outputs.

Keep toolCallStrategy: "auto" for almost every prompt and agent — the model calls tools when it needs them (including to fetch external data) and answers with text when it’s done. Use required only to force a single tool call (maxToolCalls: 1, no agent loop), such as a structured-output or routing tool. Never pair required with a multi-step loop: the model is forced to call a tool on every step and can never return a final answer, so the output comes back empty.

External APIs can fail. Consider error handling in your flow design or use the errorHandling config option.

Next Steps