Skip to main content
The final tutorial example demonstrates external tool integration—calling APIs during workflow execution and controlling which tools are available at each step.

Objective

In this example, you’ll learn:
  • How to use the call action to invoke external tools
  • How to use tools.allow for progressive tool disclosure
  • How to use tools.call to 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:
  1. Request email-domain validation using an external API
  2. Send a notification to CRM when the form is completed
  3. Restrict tool access during sensitive data collection steps
This creates a production-ready workflow with real integrations.

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:
Auto-decide routing: In the 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:
Benefits:
  • 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
Note: The submit tool is always available, regardless of 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:
What happens:
  1. Step is entered, on.enter fires the call action
  2. send_crm_notification has all required params provided → inject route: tool executes synthetically (single turn)
  3. On the next turn, no pending call remains → tools.call: true forces the submit tool
  4. The step submits and the workflow advances
If the 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 call action 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
Returns: {"valid": true/false, "domain": "example.com", "message": "..."} 2. send_crm_notification
Returns: {"success": true, "lead_id": "12345"}

How It Works

Step-by-Step Flow

Tool Visibility Per Step


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:
  1. queue the external tool call,
  2. let the agent read the tool result,
  3. have the agent resubmit normalized fields such as validation_status or directory_name,
  4. branch only on inputs.*, local.*, or known vars.*.

Try It

To test this workflow, you’ll need:
  1. The workflow JSON above assigned to an agent
  2. External tools (validate_email_domain, send_crm_notification) available in your environment
Note: If external tools aren’t available, you can modify the example to remove the call actions and test the tools.allow behavior independently.

Summary

Congratulations! You’ve completed the Step Workflows tutorial. You now know how to:
  1. Create basic workflows with steps and terminal states (Example 1)
  2. Collect and validate inputs with automatic schema generation (Example 2)
  3. Chain multiple steps with transitions and data persistence (Example 3)
  4. Add polish with lifecycle actions, say messages, and counters (Example 4)
  5. Route conditionally based on user input (Example 5)
  6. Handle validation failures with retry loops (Example 6)
  7. Integrate external tools with progressive disclosure (Example 7)
For complete reference documentation, see Step Workflow Reference.