Skip to main content
These patterns combine step types, Command Center, and integrations into workflows you can adapt for production. See the JSON cookbook for full graph examples.

Approve then send

Pause before any outbound action that affects customers or production data.

Graph structure

  1. Draft stepllm_call or mcp_call generates content (email body, WhatsApp message, CRM update payload)
  2. human_tasktask_type: "approval" with draft in task_payload
  3. Send stepmcp_call to gmail (send_email), whatsapp (send_message), or another connector — depends_on the human task, uses approved payload

Example human task payload

{
  "task_type": "approval",
  "task_payload": {
    "title": "Send order confirmation",
    "description": "Review before sending to {{input.customer_email}}",
    "draft_subject": "{{steps.draft-email.result.subject}}",
    "draft_body": "{{steps.draft-email.result.body}}"
  }
}
Complete approvals from Command Center. Downstream steps read the completion result.
Do not skip the human task for regulated or high-risk outbound messaging. A rejected task stops the branch — design downstream steps to handle rejection gracefully or use condition to branch.

Inbound webhook triggers

Start workflows from external systems (CRM, payment processor, monitoring alert).

Setup

  1. Create a workflow whose first step validates {{input.*}} fields
  2. Create an inbound webhook subscription — see Inbound webhooks
  3. Configure the external system to POST to the subscription URL with the signing secret
  4. Map POST body fields to workflow input

Validate-first pattern

Always validate required input before calling external tools:
{
  "id": "validate-input",
  "type": "lua_script",
  "name": "Validate webhook payload",
  "script": "if not input.order_id then error('order_id required') end\nreturn { order_id = input.order_id }",
  "timeout_s": 5
}
Or use condition on downstream steps: "condition": "{{input.order_id}}"

Idempotency

External systems may retry webhooks. Design workflows to be idempotent:
  • Check if the order/event was already processed (MCP query step)
  • Use external IDs in tool_args so duplicate runs do not double-send
AgentRuntime does not provide built-in cron scheduling today. For recurring runs, use an external scheduler that calls the API or fires an inbound webhook on a timetable.

Error handling with retries

Per-step retries

Set retry_count on steps that call flaky external APIs:
{
  "id": "fetch-data",
  "type": "mcp_call",
  "name": "Fetch from API",
  "tool_name": "postgres_query",
  "retry_count": 3,
  "timeout_s": 30
}
The runtime retries after failure up to retry_count times before marking the step failed.

Timeouts

Set timeout_s on every external call. Defaults are not unlimited — long-running MCP or LLM calls without timeouts can stall runs.
Step typeSuggested starting timeout
MCP tool call30–120s depending on API
LLM call60–180s for long generations
Lua script5–30s (hard cap 30s)
for_eachSum of body timeouts × parallelism

Failure propagation

When a step fails after retries:
  • The run marks the step failed
  • Downstream steps that depends_on the failed step are skipped
  • The run appears in Command Center Failed recently
Recover by fixing the root cause (connection, credits, tool args), publishing a new workflow version if needed, and starting a new run.

Human escalation on failure

Route low-confidence or failed LLM output to human review instead of failing silently: Use condition or a Lua branch to set a flag, then add a human_task on the low-confidence path.

Parallel fan-out

Use for_each to process a list with bounded parallelism:
{
  "id": "notify-each",
  "type": "for_each",
  "for_each_items": "{{steps.fetch-recipients.result.contacts}}",
  "for_each_max_parallel": 5,
  "for_each_body": {
    "type": "mcp_call",
    "tool_name": "send_message",
    "tool_args": {
      "to": "{{foreach.item.phone}}",
      "body": "{{steps.build-template.result.text}}"
    },
    "timeout_s": 30
  }
}
Keep for_each_max_parallel low for rate-limited APIs (WhatsApp, email providers).

Memory-enriched steps

When memory is enabled, workflow prepare-step can inject long-term context before LLM steps. See Memory (preview). Pattern:
  1. Index conversations or files into memory
  2. LLM step prompt references memory search results passed via prepare-step context
  3. Human task approves actions informed by retrieved knowledge

Pattern checklist

PatternHuman task?Retries?Trigger
Approve then sendYesOn draft step optionalManual / API
Webhook automationOptionalOn MCP stepsInbound webhook
Scheduled reportOptionalOn extract stepsExternal cron → API
Bulk processingOptionalOn for_each bodyAPI / webhook

End-to-end guides

These patterns are expanded into full step-by-step recipes in Guides: See all guides.