The final tutorial example demonstrates external tool integration—calling APIs during workflow execution and controlling which tools are available at each step.Documentation Index
Fetch the complete documentation index at: https://docs.syllable.ai/llms.txt
Use this file to discover all available pages before exploring further.
Objective
In this example, you’ll learn:- How to use the
callaction to invoke external tools - How to use
tools.allowfor progressive tool disclosure - How to use
tools.callto force tool execution - How to integrate external validation requests and notifications into your workflow
The Scenario
Your contact form needs to integrate with external systems:- Request email-domain validation using an external API
- Send a notification to CRM when the form is completed
- Restrict tool access during sensitive data collection steps
Implementation
Here’s the complete tool definition:Key Concepts
The call Action
The call action invokes an external tool from a lifecycle hook. Cortex automatically decides the routing path based on whether the arguments supply all of the target tool’s required parameters:
| Required params supplied? | Route | What happens |
|---|---|---|
| All present (or tool has none) | Inject (synthetic) | Tool call bypasses the LLM and executes in a single turn. |
| Some missing | Hint (LLM-guided) | A pending_tool_call is queued; the LLM generates the call on the next turn with forced tool_choice. |
COLLECT_EMAIL example above, validate_email_domain requires one param (email) and arguments provides it via template — so Cortex takes the inject route: the tool executes synthetically without LLM involvement.
If you omitted the email key from arguments, Cortex would take the hint route: the LLM would see a pending_tool_call hint and generate the call itself.
Important: The workflow engine does not automatically copy external tool results into inputs.* or local.*. If later routing depends on a tool result, add a follow-up submit step that captures normalized result fields, or rely on endpoint-persisted vars.*.
Template variables in arguments:
{{inputs.user_email}}— Current step input{{user_name}}— Global variable (saved from earlier step){{local.counter}}— Task-local variable
Progressive Tool Disclosure with tools.allow
Control which tools are visible at each step:
- Security: Prevent access to sensitive tools during early steps
- Focus: Agent only sees relevant tools for the current task
- Progressive disclosure: Unlock capabilities as the workflow advances
tools.allow.
Auto-Advancing with tools.call
tools.call: true forces the LLM to produce a tool call on turns where no pending call action exists. In practice, this forces the submit tool — making it the standard mechanism for auto-advancing bridge steps.
tools.call and call actions operate on different turns and compose naturally:
- Step is entered,
on.enterfires thecallaction send_crm_notificationhas all required params provided → inject route: tool executes synthetically (single turn)- On the next turn, no pending call remains →
tools.call: trueforces the submit tool - The step submits and the workflow advances
call action took the hint route instead (missing required params), the sequence would be: turn 1 queues the hint → turn 2 the LLM generates the tool call (forced tool_choice) → turn 3 tools.call: true forces submit.
Use cases for tools.call: true:
- Auto-advancing bridge steps after a
callaction completes - Forcing submit on terminal steps with no inputs
- Making zero-input steps fully deterministic
External Tool Assumptions
This example assumes two external tools are available: 1.validate_email_domain
{"valid": true/false, "domain": "example.com", "message": "..."}
2. send_crm_notification
{"success": true, "lead_id": "12345"}
How It Works
Step-by-Step Flow
Tool Visibility Per Step
| Step | Available Tools |
|---|---|
| COLLECT_NAME | submit_contact_info |
| COLLECT_EMAIL | submit_contact_info, validate_email_domain |
| COLLECT_TIME | submit_contact_info |
| CONFIRM_AND_NOTIFY | submit_contact_info, send_crm_notification |
Best Practices
1. Minimize Tool Access
Only expose tools that are needed for the current step:2. Use call for Mandatory Operations
When a tool must be called (validation, notification), use the call action:
3. Combine tools.call with on.enter for Data Fetching
When you need data before the step can proceed:
4. Handle Tool Failures Gracefully
External tools can fail. Consider adding error handling steps:5. Normalize Tool Results Before Branching
If a future step needs structured data from an external tool, do not assume the result is automatically written into workflow state. Instead:- queue the external tool call,
- let the agent read the tool result,
- have the agent resubmit normalized fields such as
validation_statusordirectory_name, - branch only on
inputs.*,local.*, or knownvars.*.
Try It
To test this workflow, you’ll need:- The workflow JSON above assigned to an agent
- External tools (
validate_email_domain,send_crm_notification) available in your environment
call actions and test the tools.allow behavior independently.
Summary
Congratulations! You’ve completed the Step Workflows tutorial. You now know how to:- Create basic workflows with steps and terminal states (Example 1)
- Collect and validate inputs with automatic schema generation (Example 2)
- Chain multiple steps with transitions and data persistence (Example 3)
- Add polish with lifecycle actions, say messages, and counters (Example 4)
- Route conditionally based on user input (Example 5)
- Handle validation failures with retry loops (Example 6)
- Integrate external tools with progressive disclosure (Example 7)

