Pattern A: Agent as Workflow Step

The agent operates as one step within a larger deterministic workflow. The workflow handles sequencing, data flow, and branching. The agent handles the reasoning-intensive step.

flowchart LR S1["Step 1: Matcher<br/>(deterministic)"] --> S2["Step 2: ReAct Agent<br/>(reasoning)"] S2 --> S3["Step 3: PbotApproval<br/>(human review)"] S3 --> S4["Step 4: Custom Table<br/>(log results)"] style S2 fill:#f3e8ff,stroke:#9333ea

When to Use

  • Most of the process is deterministic, but one step requires judgment
  • You want the workflow to control overall flow while delegating reasoning to the agent
  • The agent is a specialist embedded in a structured pipeline
  • You need predictable sequencing before and after the reasoning step

Complete Example: Invoice Exception Investigation

A reconciliation workflow that matches invoices to payments, then uses an agent to investigate any unmatched exceptions.

json
{
  "name": "invoice_reconciliation_with_investigation",
  "definition": {
    "actions": [
      {
        "type": "matcher",
        "properties": {
          "left": "@input.invoices",
          "right": "@input.payments",
          "matchOn": ["invoice_id"],
          "tolerance": 0.02,
          "outputMatched": "reconciled",
          "outputUnmatchedLeft": "exceptions"
        }
      },
      {
        "type": "loop",
        "filter": {
          "condition": { "greaterThan": [{ "length": "@exceptions" }, 0] }
        },
        "properties": {
          "mode": "foreach",
          "items_path": "@exceptions",
          "item_variable_name": "exception",
          "actions_to_execute": [
            {
              "type": "loop",
              "properties": {
                "mode": "react",
                "objective": "Investigate why invoice {{exception.invoice_id}} for ${{exception.amount}} from {{exception.vendor}} has no matching payment. Check for partial payments, alternate vendor names, or recent credits. Recommend: approve, reject, or escalate.",
                "tools": [
                  { "type": "action", "name": "search_payments" },
                  { "type": "action", "name": "lookup_vendor" },
                  { "type": "action", "name": "check_credits" }
                ],
                "max_iterations": 8,
                "on_stuck": { "iterations": 3, "action": "escalate" },
                "result_key": "investigation"
              }
            }
          ],
          "max_concurrency": 3,
          "failure_strategy": "continue_on_error",
          "collect_results": true,
          "result_key": "all_investigations"
        }
      },
      {
        "type": "PbotApproval",
        "filter": {
          "condition": { "greaterThan": [{ "length": "@exceptions" }, 0] }
        },
        "properties": {
          "comment": "Review {{exceptions.length}} investigated exceptions",
          "request_payload": {
            "investigations": "@all_investigations"
          }
        }
      },
      {
        "type": "custom-table",
        "properties": {
          "table": "reconciliation_log",
          "operation": "write",
          "keys": ["run_id"],
          "values": ["@__run_id"],
          "fields": {
            "matched_count": "@reconciled.length",
            "exception_count": "@exceptions.length",
            "processed_at": "@now"
          }
        }
      }
    ]
  }
}

How It Works

  1. Matcher (deterministic) — matches invoices to payments by ID with 2% tolerance
  2. Foreach + ReAct (agent) — for each unmatched invoice, an agent investigates why. Up to 3 run in parallel
  3. PbotApproval (human) — a reviewer sees all investigations and approves or rejects
  4. Custom Table (deterministic) — logs the reconciliation run

The workflow controls the pipeline. The agent only runs within its step. It can't skip the approval step or modify the matcher configuration.


Key Properties

  • filter on the agent step — the agent loop only runs if there are exceptions. If everything matched, it's skipped entirely
  • max_concurrency: 3 — limits parallel agent executions to avoid LLM rate limits
  • on_stuck: escalate — if an agent can't figure out an exception, it pauses for human help rather than failing
  • collect_results: true — all investigation results are gathered into @all_investigations for the approval step

→ Next: Pattern B: Agent as Trigger