For the complete documentation index, see llms.txt. This page is also available as Markdown.

Authoring autonomous routines

Build a typed automation end to end: schemas, the terminal emit_output rule, timeouts, webhooks, triggering, and receiving the callback.

Context — Assumes Autonomous routines (the run lifecycle and failure taxonomy) and Authoring routines (node craft — it all applies here). This guide builds one automation end to end: a KYC decision processor.

YAML examples follow manifest schema 6.1.5. Manifest and content shapes are schema-versioned and differ across runtime versions — see Versioning & compatibility.

What we're building

A third-party KYC provider finishes verifying an applicant. We want the agent to assess the result, decide approve / reject / escalate, and deliver the decision to our backend — no human, no conversation.

1. Design the contract first

The schemas are the interface your callers code against. Write them before the nodes:

autonomous:
  input_schema:
    type: object
    required: [applicant_id, verification_result]
    properties:
      applicant_id:
        type: string
      verification_result:
        type: object
        required: [status]
        properties:
          status:
            enum: [GREEN, AMBER, RED]
          checks:
            type: array
            items:
              type: object
  output_schema:
    type: object
    required: [decision, explanation]
    properties:
      decision:
        enum: [approved, rejected, escalate]
      explanation:
        type: string
  timeout_seconds: 60
  callback_url_allowlist:
    - api.example.com

Schema craft:

  • Closed enums on decision fields. Your backend switches on decision; an enum makes drift impossible. (The runtime adds additionalProperties: false to every object node automatically.)

  • required everything you'll consume. Optional output fields breed KeyErrors downstream.

  • Validate inputs strictly. A bad payload should be a 400 at the door (input_validation_failed), not a confused model mid-run.

  • Allowlist callbacks. Without callback_url_allowlist any URL is accepted; with it, only the listed hostnames (a leading . matches the apex and subdomains; a full-URL entry matches by its hostname). Wildcards are not supported.

2. Write the nodes

An autonomous routine is built from TOOL, THINK, and routing-only nodes — there are no CHAT nodes, because there's no customer in the conversation to speak to; the result leaves the run as typed JSON via emit_output, not as a message. (Node-type details: Autonomous routines.) Two extra rules beyond the usual node craft:

  1. The validated input is visible to every node (it arrives as a tool result in history) — reference its fields by name in instructions.

  2. Every terminal node (no outbound transitions) must be a TOOL node calling built-in:emit_output. Terminal THINK nodes are rejected at validation time.

Branched flows end every terminal node the same way — branch directly from the think node's transitions:

Budget the iteration cap: the cap counts per-turn engine preparation passes, not nodes. Each sequential think/tool step consumes roughly one iteration, and emit_output is itself a tool call — a think → tool → emit chain needs roughly 3. But a node whose tools run together in one parallel batch is still just one iteration, so this is an approximation that over-counts routines with parallel tool fan-out. The default cap is 5 (runtime.max_engine_iterations). Runs that hit the cap before emit_output fail with max_engine_iterations_reached.

3. Reference it from the manifest

Autonomous routines are listed like any other:

The autonomous: block in the routine YAML is what activates the trigger endpoint — there is no separate manifest switch. The boot log confirms registration per routine (timeout and webhook status included).

4. Trigger it

Immediate 202:

Always send an idempotency_key from a retry-capable caller — a duplicate key returns the existing run (HTTP 409) instead of running twice.

5. Receive the callback

Your endpoint gets one POST per run, authenticated with the agent's bearer key. Acknowledge fast; the server retries non-2xx responses with backoff (default 5 attempts).

Handle status: "failed" by error.code — the failure taxonomy maps each code to the knob that fixes it. The full payload schema is in Events & callbacks.

6. Optional: let the provider trigger it directly

Skip your own trigger plumbing by giving the routine a webhook:

Point the provider at POST /webhooks/kyc-decision, configured to sign the raw body with the shared secret. The provider's payload becomes the run's input (it must satisfy input_schema), provider retries dedupe automatically, and no callback is sent — webhook runs are fire-and-forget and always run in an ephemeral session; consume results from traces (set traces.trace_id_field so they're findable by your business key) or have a tool node before the terminal one write the outcome to your systems. For one URL dispatching to several routines, use manifest-level webhooks — see Autonomous routines.

To verify the wiring before pointing the real provider at it, sign a test body yourself:

The body bytes must match the signed bytes exactly (the signature covers the raw body, not a re-serialisation). A 401 means signature mismatch — check algorithm, prefix, header name, and that both sides hold the same secret. Re-sending the same body returns the original run (HTTP 200) instead of firing twice.

Testing checklist

Last updated

Was this helpful?