Overview
Tool nodes execute pre-configured tool templates from your tool library. Unlike web tool nodes which define HTTP requests inline, tool nodes reference existing tools that can be reused across multiple agents and flows. This promotes consistency, maintainability, and reduces configuration time.
Key characteristic: Tool nodes execute actions (API calls, database queries, external integrations) and then transition to the next node based on results.
When to Use
Use tool nodes to:
- Look up customer data from CRM systems
- Check inventory, availability, or status
- Submit forms or create records
- Process payments or transactions
- Send notifications (email, SMS, webhooks)
- Retrieve data from databases
- Execute business logic on external systems
- Call any HTTP API with reusable configuration
Use Tool Node when:
- The tool will be used in multiple places
- The tool needs comprehensive documentation
- The tool requires consistent configuration
- You want centralized tool management
Use Web Tool Node instead when:
- Making a one-off API call specific to this flow
- Prototyping before creating a template
- The API call is unlikely to be reused
→ Compare: Web Tool Node
Core Configuration
Basic Setup
{
type: "tool",
label?: string,
description?: string,
// Tool configuration is stored in agentSettings.tools where tool.nodeId === node.id
// No tool reference fields (toolId, toolName, toolType) on the node itself
// Node-specific parameters (can override tool template parameters)
parameters: ToolParameter[], // default: []
// Execution
timeout: number, // milliseconds, default 30000
// Error handling
onErrorBehavior: "continue" | "retry" | "fail", // default: "continue"
errorMessage?: string,
// Response handling
overrideResponse: boolean, // default: false
customResponse?: string,
outputMapping: Record<string, string>, // default: {}
// Variable extraction
extractVariables: ExtractVariablesConfig,
// Processing message
processingMessage?: string,
processingMessageType: "static" | "prompt", // default: "static"
// Transitions
transitions: Transition[]
}
Tool Reference Architecture: The tool itself (toolId, toolType, overrides, version) is stored in agentSettings.tools array with tool.nodeId matching this node’s ID. The node only contains execution settings and parameter overrides.
- Add a Tool Node to your flow
- Click Select Tool in the node configuration
- Choose from your tool library
- Tool details auto-populate (name, description, parameters)
What happens behind the scenes:
- Selecting a tool creates an entry in
agentSettings.tools array
- This entry has
nodeId set to this node’s ID to link them
- Tool configuration (toolId, toolType, persistentId, version, overrides) is stored in that entry
- The node itself only contains execution settings (timeout, error handling, output mapping, parameters)
Available tool types:
- FUNCTION: Server-side HTTP API requests (full override support)
- MCP: Model Context Protocol tools (no overrides allowed)
- WEB_TOOL: Browser-based tools for SDK deployments (limited overrides)
[→ Learn more about tool types and architecture/features/tools)
Parameter Mapping
Map flow variables and static values to tool input parameters.
Static Values
Hardcoded values that never change.
Tool Node: Send_Welcome_Email
tool: SendGrid_Email
Parameters:
template_id: "welcome-v2"
from_email: "[email protected]"
from_name: "Acme Support Team"
Variable References
Use data collected earlier in the flow using {{variable_name}} syntax.
Tool Node: Send_Confirmation_Email
tool: SendGrid_Email
Parameters:
to_email: {{customer_email}}
to_name: {{customer_name}}
template_id: "order-confirmation"
order_id: {{order_id}}
System Variables
Reference built-in system variables.
Tool Node: Log_Call_Event
tool: Analytics_Logger
Parameters:
caller_id: {{caller_id}}
call_id: {{call_id}}
timestamp: {{current_time}}
agent_id: {{agent_id}}
session_id: {{session_id}}
→ See all system variables: Variables Guide
Mixed Static and Variables
Combine both for flexible configurations.
Tool Node: CRM_Customer_Lookup
tool: Salesforce_Query
Parameters:
phone: {{caller_phone}} # Variable
include_orders: true # Static
fields: "name,email,account_id" # Static
limit: 1 # Static
Parameter Types
Tool parameters can have different data types:
{
name: string,
value: string, // Can contain {{variables}}
type: "string" | "number" | "boolean" | "object",
required: boolean
}
Example with mixed types:
Parameters:
customer_name: { { name } } # string
order_total: { { cart_total } } # number
send_confirmation: true # boolean
shipping_address: { { address_json } } # object
Output Mapping
Extract data from tool responses into flow variables using JSON path syntax.
JSON Path Syntax
Use $.path.to.field notation to reference fields in the response.
Tool response:
{
"success": true,
"data": {
"customer": {
"id": "CUST-12345",
"name": "John Smith",
"email": "[email protected]"
},
"account": {
"status": "active",
"balance": 1250.5,
"tier": "premium"
}
}
}
Output mapping:
Output Mapping:
customer_id: $.data.customer.id # "CUST-12345"
customer_name: $.data.customer.name # "John Smith"
customer_email: $.data.customer.email # "[email protected]"
account_status: $.data.account.status # "active"
account_balance: $.data.account.balance # 1250.50
membership_tier: $.data.account.tier # "premium"
Variables extracted via output mapping become available immediately in subsequent nodes.
Tool Node: Lookup_Account
tool: CRM_Lookup
outputMapping:
customer_name: $.name
account_balance: $.balance
Conversation Node: Discuss_Account
message: "Hello {{customer_name}}, I see your current balance is ${{account_balance}}."
Array Access
Access array elements by index.
Response:
{
"orders": [
{ "id": "ORD-001", "total": 99.99 },
{ "id": "ORD-002", "total": 149.99 }
]
}
Mapping:
Output Mapping:
latest_order_id: $.orders[0].id # "ORD-001"
latest_order_total: $.orders[0].total # 99.99
Nested Objects
Navigate deeply nested structures.
Output Mapping:
street: $.data.customer.address.street
city: $.data.customer.address.city
zip: $.data.customer.address.postal_code
Error Handling
Configure how the flow responds when tool execution fails.
Flow continues even if tool fails. Best for optional operations.
Tool Node: Update_CRM_Notes
tool: CRM_Update_Notes
Error Handling:
onErrorBehavior: continue
errorMessage: "I wasn't able to update your notes, but let's continue."
Transitions:
- Always → Next_Step
Use when:
- Tool is non-critical (analytics, logging)
- Flow can proceed without tool result
- Degraded experience is acceptable
Retry (For Intermittent Failures)
Automatically retries failed tool calls.
Tool Node: Check_Inventory
tool: Inventory_API
Error Handling:
onErrorBehavior: retry
retryAttempts: 2
retryDelay: 1000 # 1 second between retries
errorMessage: "I'm having trouble checking inventory. Let me try again..."
Transitions:
- Equation: {{inventory_available}} > 0 → In_Stock_Flow
- Always → Out_Of_Stock_Flow
Use when:
- API has intermittent failures
- Network issues are common
- Tool is important but can fail temporarily
Fail (For Critical Operations)
Stops flow execution and ends call when tool fails.
Tool Node: Process_Payment
tool: Stripe_Charge
Error Handling:
onErrorBehavior: fail
errorMessage: "I'm unable to process your payment at this time. Please try again later or contact support."
Transitions:
- Equation: {{payment_status}} == "success" → Payment_Success
Use when:
- Tool is critical to conversation
- Cannot proceed without successful result
- Failure requires human intervention
Error Messages
Provide clear, user-friendly error messages.
# ❌ Bad: Technical jargon
errorMessage: "HTTP 500 Internal Server Error"
# ✅ Good: User-friendly
errorMessage: "I'm experiencing technical difficulties. Let me transfer you to a specialist who can help."
Response Handling
Default Behavior (Silent)
By default, tool nodes execute silently—no message is spoken about the tool execution.
Tool Node: Lookup_Customer
tool: CRM_Lookup
overrideResponse: false # Default
# Tool executes, extracts variables, transitions to next node
# Agent says nothing about the tool call
Custom Response Override
Speak a custom message after tool execution using extracted variables.
Tool Node: Lookup_Customer
tool: CRM_Lookup
Output Mapping:
customer_name: $.name
account_tier: $.tier
Response Override:
overrideResponse: true
customResponse: "Thank you, {{customer_name}}. I see you're a {{account_tier}} member."
Variable interpolation:
- Use
{{variable_name}} syntax
- Variables from output mapping are available
- Variables from earlier nodes are available
- System variables are available
Processing Message
Show message while tool executes (especially for slow APIs).
Tool Node: Search_Knowledge_Base
tool: KB_Search
Processing Message:
message: "Let me search our knowledge base for that information..."
messageType: static
timeout: 15000 # 15 seconds
Static vs Prompt:
Static: Exact message every time.
processingMessage: 'Please hold while I check that for you...'
processingMessageType: static
Prompt: AI generates contextual message.
processingMessage: "Tell the user you're looking up their request and to please hold."
processingMessageType: prompt
In addition to output mapping (which extracts from tool responses), tool nodes support conversation-based variable extraction.
When to Use
Use variable extraction when:
- Tool requires user confirmation before executing
- You want to ask questions before calling the tool
- Tool needs additional context from conversation
Configuration
Tool Node: Book_Appointment
tool: Calendar_API
Extract Variables:
enabled: true
variables:
- name: preferred_date
description: "Preferred appointment date"
extractionPrompt: "Extract date in YYYY-MM-DD format"
dataType: string
isRequired: true
- name: preferred_time
description: "Preferred time"
extractionPrompt: "Extract time in HH:MM format"
dataType: string
isRequired: true
Parameters:
customer_id: {{customer_id}}
date: {{preferred_date}}
time: {{preferred_time}}
Note: Variable extraction happens during conversation before tool execution. Most tool nodes use output mapping instead.
Timeout Configuration
Set maximum wait time for tool execution.
Tool Node: External_API_Call
tool: Slow_API
timeout: 20000 # 20 seconds
Recommendations:
- Fast APIs (< 2s): 5000ms
- Standard APIs: 10000ms
- Slow operations: 20000-30000ms
- Maximum allowed: 30000ms (30 seconds)
When timeout occurs:
- Follows
onErrorBehavior setting
- Displays
errorMessage if configured
- Can continue, retry, or fail based on configuration
Long timeouts create poor user experience. Consider async tools or processing messages for slow operations.
Use Cases & Examples
Example 1: Customer Lookup
Scenario: Look up customer by phone number.
Tool Node: Lookup_Customer
tool: CRM_Customer_Lookup
Parameters:
phone_number: {{caller_id}}
include_history: true
Output Mapping:
customer_id: $.data.id
customer_name: $.data.name
customer_email: $.data.email
account_status: $.data.status
membership_tier: $.data.tier
last_order_date: $.data.last_order
Response Override:
overrideResponse: true
customResponse: "Welcome back, {{customer_name}}! I have your account details."
Error Handling:
onErrorBehavior: continue
errorMessage: "I'm having trouble accessing our customer database. Let's verify your information manually."
Transitions:
- Equation: {{account_status}} == "active" → Active_Account_Flow
- Equation: {{account_status}} == "suspended" → Suspended_Flow
- Always → New_Customer_Flow
Example 2: Check Inventory
Scenario: Verify product availability before taking order.
Conversation Node: Collect_Product_Info
message: "What product are you interested in?"
Extract Variables:
- product_sku: "Extract product SKU or name"
Transitions:
- Always → Check_Stock
Tool Node: Check_Stock
tool: Inventory_Check_API
Parameters:
sku: {{product_sku}}
warehouse: "primary"
Output Mapping:
stock_level: $.inventory.available
next_restock_date: $.inventory.next_shipment
Processing Message:
message: "Let me check if we have that in stock..."
messageType: static
Error Handling:
onErrorBehavior: retry
retryAttempts: 2
Transitions:
- Equation: {{stock_level}} > 0 → In_Stock_Flow
- Equation: {{stock_level}} == 0 → Out_Of_Stock_Flow
Example 3: Process Payment
Scenario: Charge customer credit card.
Tool Node: Process_Payment
tool: Stripe_Create_Charge
Parameters:
amount: {{order_total}}
currency: "usd"
customer_id: {{stripe_customer_id}}
description: "Order #{{order_id}}"
receipt_email: {{customer_email}}
Output Mapping:
charge_id: $.id
payment_status: $.status
receipt_url: $.receipt_url
Processing Message:
message: "Processing your payment. Please do not hang up..."
messageType: static
Error Handling:
onErrorBehavior: fail
errorMessage: "Your payment could not be processed. Please contact your bank or try a different payment method."
Response Override:
overrideResponse: true
customResponse: "Your payment has been processed successfully. A receipt has been sent to {{customer_email}}."
timeout: 15000 # 15 seconds
Transitions:
- Equation: {{payment_status}} == "succeeded" → Payment_Success
- Always → Payment_Failed
Example 4: Send Notification
Scenario: Send confirmation email after booking.
Tool Node: Send_Confirmation_Email
tool: SendGrid_Email
Parameters:
to: {{customer_email}}
template_id: "appointment-confirmation"
dynamic_data: {
customer_name: {{customer_name}},
appointment_date: {{appointment_date}},
appointment_time: {{appointment_time}},
location: {{appointment_location}}
}
Processing Message:
message: "I'm sending you a confirmation email now..."
Error Handling:
onErrorBehavior: continue
errorMessage: "I wasn't able to send the confirmation email, but your appointment is booked."
Transitions:
- Always → Appointment_Confirmed
Example 5: Multi-Step Database Query
Scenario: Look up customer, then fetch their orders.
Tool Node: Lookup_Customer
tool: Database_Query_Customer
parameters:
phone: {{caller_phone}}
outputMapping:
customer_id: $.id
transitions:
- Always → Fetch_Orders
Tool Node: Fetch_Orders
tool: Database_Query_Orders
parameters:
customer_id: {{customer_id}}
limit: 5
outputMapping:
order_count: $.total
latest_order_id: $.orders[0].id
latest_order_status: $.orders[0].status
transitions:
- Equation: {{order_count}} > 0 → Has_Orders_Flow
- Always → No_Orders_Flow
Scenario: Only call pricing API for premium members.
Router Node: Check_Membership
transitions:
- Equation: {{membership_tier}} == "premium" → Get_Premium_Pricing
- Always → Get_Standard_Pricing
Tool Node: Get_Premium_Pricing
tool: Pricing_API
parameters:
tier: "premium"
customer_id: {{customer_id}}
outputMapping:
discount_percentage: $.discount
transitions:
- Always → Display_Pricing
Tool Node: Get_Standard_Pricing
tool: Pricing_API
parameters:
tier: "standard"
outputMapping:
discount_percentage: $.discount
transitions:
- Always → Display_Pricing
Override tool configuration for specific contexts (e.g., web vs phone).
Configuration
Tool Node: Contact_Form_Submit
tool: API_Submit_Form
Web Tools Overrides:
id: "tool-instance-uuid"
httpHeaders:
X-Client-Type: "web-sdk"
X-Browser-Info: "{{userAgent}}"
params:
source:
overrideValue: "web-chat"
Use cases:
- Different headers for web vs phone contexts
- Override API endpoints for testing
- Customize tool behavior per deployment
[→ Learn more: Web Tools Guide/features/tools#web-tools)
Transitions
Tool nodes support all transition types:
Natural Language
Evaluate conversation context.
Transitions:
- Natural Language: "User is satisfied with the result" → Continue_Flow
- Natural Language: "User wants to modify something" → Modify_Flow
Note: Tool nodes don’t have conversations by default. Natural language transitions evaluate context from previous nodes.
Structured Equation
Route based on extracted variables.
Transitions:
- Equation: {{order_status}} == "completed" → Order_Complete
- Equation: {{order_status}} == "pending" → Order_Pending
- Equation: {{order_status}} == "failed" → Order_Failed
Always
Fallback transition.
Transitions:
- Equation: {{success}} == true → Success_Path
- Always → Error_Path
→ Learn More: Transitions
Best Practices
✅ Do’s
Use tool templates for reusable operations
- Create templates for APIs used across multiple flows
- Maintain consistency across agents
- Update once, affects all usages
Map outputs to descriptive variable names
# ✅ Good
outputMapping:
customer_full_name: $.name
account_balance_usd: $.balance
# ❌ Bad
outputMapping:
name: $.name
bal: $.balance
Provide user-friendly error messages
# ✅ Good
errorMessage: "I'm having trouble checking your account. Let me transfer you to someone who can help."
# ❌ Bad
errorMessage: "API error 500"
Set realistic timeouts
- Don’t make users wait unnecessarily
- Balance user experience with API requirements
- Use processing messages for slow operations
Test with actual API responses
- Verify output mapping JSON paths
- Test error scenarios
- Validate variable extraction
Use continue for non-critical tools
- Analytics and logging shouldn’t block flows
- Provide graceful degradation
❌ Don’ts
Don’t hardcode sensitive data in parameters
# ❌ Bad
parameters:
api_key: "sk_live_1234567890"
# ✅ Good
parameters:
api_key: {{env.STRIPE_API_KEY}}
Don’t skip error handling
- Always configure onErrorBehavior
- Provide error messages
- Consider retry logic
Don’t use tool nodes for one-off calls
- Use web tool nodes for single-use APIs
- Reserve tool nodes for reusable templates
Don’t make tools blocking unnecessarily
- Use continue when possible
- Consider async tools for long operations
- Provide processing messages
Don’t forget to map critical outputs
- Extract all data you’ll need downstream
- Use descriptive variable names
- Document what each variable contains
Troubleshooting
Solution:
- Verify tool exists in tool library
- Check tool is active
- Refresh the page
- Verify tool is in current project
Issue: Parameters not being sent correctly
Solution:
- Check variable names match exactly (case-sensitive)
- Verify variables exist (were extracted earlier)
- Review parameter type (string vs number vs boolean)
- Test with static values first
Solution:
- Verify JSON path syntax:
$.path.to.field
- Check actual API response format
- Test JSON path with tool response
- Ensure response contains expected fields
Solution:
- Increase timeout value
- Check API performance
- Add retry logic
- Consider async tools
- Add processing message
Issue: Variables not available in next node
Solution:
- Verify output mapping is configured
- Check variable names match exactly
- Ensure tool completed successfully
- Review flow transitions
Schema Reference
{
type: "tool",
label?: string,
description?: string,
// Tool configuration stored in agentSettings.tools (not on node)
// Tool is linked via tool.nodeId === node.id
// Node-specific parameters
parameters: Array<{
name: string,
value: string, // Supports {{variable}} syntax
type: "string" | "number" | "boolean" | "object",
required: boolean,
// Enhanced fields for custom parameters
description?: string,
dataType?: "string" | "number" | "boolean" | "array" | "object",
defaultValue?: string
}>,
// Execution settings
timeout: number, // Default: 30000ms
// Variable extraction (optional)
extractVariables: {
enabled: boolean,
variables: Array<Variable>
},
// Response handling
overrideResponse: boolean, // Default: false
customResponse?: string,
outputMapping: Record<string, string>, // JSON path → variable name, default: {}
// Error handling
onErrorBehavior: "continue" | "retry" | "fail", // Default: "continue"
errorMessage?: string,
// Processing message
processingMessage?: string,
processingMessageType: "static" | "prompt",
// Transitions
transitions: Transition[],
// Position
position: { x: number, y: number }
}
Next Steps