> ## Documentation Index
> Fetch the complete documentation index at: https://koreai.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# How to design a supervisor that routes users to specialist agents

<Badge icon="arrow-left" color="gray">[Back to how-to guides](/agent-platform/abl/how-to/overview#agent-architecture-and-design)</Badge>

Use this guide when one conversational entry point must identify what the user needs, choose the right specialist, and pass enough context for that specialist to continue.

## Concept

A supervisor is the front door for a multi-agent experience. Its primary job is not to solve every problem. Its job is to understand the request, choose the right owner, and transfer context.

A specialist agent owns one business capability. A good specialist has a narrow goal, the right tools or data access, clear limitations, and a completion path.

Routing is the decision that connects the user request to the correct owner. In ABL, the executable route is `HANDOFF`. `AGENTS:` is an optional roster that makes the supervisor easier to read, but it does not route by itself.

## Decision guide: routing condition styles

| Style                     | Example                                   | Use when                                                |
| ------------------------- | ----------------------------------------- | ------------------------------------------------------- |
| Declared intent category  | `WHEN: intent.category == "order_status"` | You want stable route labels for testing and reporting. |
| Structured condition      | `WHEN: customer_id IS SET`                | The route depends on known fields or variables.         |
| Quoted semantic condition | `WHEN: "the user is asking for a refund"` | The route is best described as plain-language guidance. |

Quote natural-language conditions. Unquoted text can be parsed as variable names and produce undefined-variable warnings.

## Minimal working example: support supervisor project

This example is a project-level set. Put the supervisor and target agents in the same project.

<AccordionGroup>
  <Accordion title="Support Supervisor">
    `agents/support-supervisor.agent.abl`

    ```yaml expandable=true theme={null}
    SUPERVISOR: Support_Supervisor
    GOAL: "Route support requests to the right specialist"

    AGENTS:
      account: Account_Support_Agent
      orders: Order_Status_Agent
      human: Live_Agent

    INTENTS:
      account: "Account access or password help"
      order_status: "Order tracking or delivery help"
      human_help: "User asks for a person or the request is unclear"

    GATHER:
      customer_id:
        prompt: "What customer ID should I use for this request?"
        type: string
        required: true

    HANDOFF:
      - TO: Account_Support_Agent
        WHEN: intent.category == "account"
        PASS: [customer_id]
        SUMMARY: "Customer needs account or password support"
        RETURN: true
      - TO: Order_Status_Agent
        WHEN: intent.category == "order_status"
        PASS: [customer_id]
        SUMMARY: "Customer needs order status or delivery support"
        RETURN: false
      - TO: Live_Agent
        WHEN: intent.category == "human_help"
        PASS: [customer_id]
        SUMMARY: "Customer asks for a person or the request is unclear"
        RETURN: false
    ```
  </Accordion>

  <Accordion title="Account Support Agent">
    `agents/account-support-agent.agent.abl`

    ```yaml theme={null}
    AGENT: Account_Support_Agent
    GOAL: "Resolve account access and password support requests"

    GATHER:
      customer_id:
        prompt: "What customer ID should I use?"
        type: string
        required: true

    COMPLETE:
      - WHEN: customer_id IS SET
        RESPOND: "I can continue account support for {{customer_id}}."
    ```
  </Accordion>

  <Accordion title="Order Status Agent">
    `agents/order-status-agent.agent.abl`

    ```yaml theme={null}
    AGENT: Order_Status_Agent
    GOAL: "Resolve order status and delivery support requests"

    GATHER:
      customer_id:
        prompt: "What customer ID should I use?"
        type: string
        required: true

    COMPLETE:
      - WHEN: customer_id IS SET
        RESPOND: "I can continue order support for {{customer_id}}."
    ```
  </Accordion>

  <Accordion title="Live Agent">
    `agents/live-agent.agent.abl`

    ```yaml theme={null}
    AGENT: Live_Agent
    GOAL: "Transfer the customer to a human support queue"

    COMPLETE:
      - WHEN: true
        RESPOND: "I will connect you with a human support specialist."
    ```
  </Accordion>
</AccordionGroup>

The supervisor gathers `customer_id`, then passes it with `PASS`. `RETURN: true` on account support means bounded specialist work can return to the supervisor. `RETURN: false` on order status and live agent means the target keeps ownership.

Since none of the `HANDOFF` entries above declare `HISTORY`, each specialist now receives the full conversation history by default (the current platform default when `HISTORY` is omitted). Also, because each `WHEN` here is a single-field comparison (`intent.category == "account"`), an unset field simply makes the comparison evaluate `false` — no error, and the trace shows your literal source text.

## Common variations

### Plain-language routing variation

Use quoted semantic conditions when business users can describe a route more clearly in natural language than as a strict expression. Treat this as an alternative supervisor project to the previous example; do not combine both supervisors in the same deployment unless the project explicitly declares the intended entry supervisor.

<AccordionGroup>
  <Accordion title="Billing Supervisor">
    `agents/billing-supervisor.agent.abl`

    ```yaml theme={null}
    SUPERVISOR: Billing_Supervisor
    GOAL: "Route billing questions to the right specialist"

    HANDOFF:
      - TO: Pending_Payments
        WHEN: "user is asking about payment status, unpaid balance, invoice due date, or how to pay"
        SUMMARY: "Customer needs help with pending payments or payment instructions"
      - TO: Refund_Guidance
        WHEN: "user is asking about a refund, reimbursement, returned payment, claim payout, or refund timeline"
        SUMMARY: "Customer needs refund guidance or refund status help"
    ```
  </Accordion>

  <Accordion title="Pending Payments Agent">
    `agents/pending-payments.agent.abl`

    ```yaml theme={null}
    AGENT: Pending_Payments
    GOAL: "Help customers understand pending payments and payment instructions"

    COMPLETE:
      - WHEN: true
        RESPOND: "I can help with pending payments and payment instructions."
    ```
  </Accordion>

  <Accordion title="Refund Guidance Agent">
    `agents/refund-guidance.agent.abl`

    ```yaml theme={null}
    AGENT: Refund_Guidance
    GOAL: "Help customers understand refund status and refund next steps"

    COMPLETE:
      - WHEN: true
        RESPOND: "I can help with refund status and refund next steps."
    ```
  </Accordion>
</AccordionGroup>

Keep semantic routes distinct. If two routes could match the same request, customers may experience inconsistent routing.

## Designing the context package

Every handoff should answer three questions.

| Question                           | Design guidance                                                                                    |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| What does the target need to know? | Pass only useful fields, such as `customer_id`, `order_id`, `issue_summary`, or `transfer_reason`. |
| Why is the transfer happening?     | Use `SUMMARY` so the target starts with a concise reason.                                          |
| Should control come back?          | Use `RETURN: true` for bounded specialist work and `RETURN: false` for permanent transfer.         |

Do not pass every field by default. Pass the context the target needs to continue safely.

## Fallback and ambiguity design

Do not rely on the roster as a fallback. If no handoff is selected, the supervisor remains the active agent and should clarify, retry, or route to a fallback based on your design.

For production supervisors:

* Add a route for human help, unsupported requests, or unclear requests.
* Make route descriptions mutually exclusive.
* Add test utterances that intentionally look ambiguous.
* Inspect traces to confirm the selected handoff target.
* If your runtime configuration supports multi-intent disambiguation, verify that the user is asked to choose when a message contains multiple requests.

## Verification

1. Validate the supervisor and all target agents together.
2. Send: "I forgot my password." Expect `Account_Support_Agent`.
3. Send: "Where is my order?" Expect `Order_Status_Agent`.
4. Send: "I need to talk to someone." Expect `Live_Agent`.
5. Confirm `customer_id` is gathered before routes that pass it.
6. Inspect trace/debug output for handoff target, return behavior, and context passed.

## Production readiness checklist

* Every `TO` target exists and has a clear owner.
* Every `PASS` field is populated before handoff.
* Every route has a distinct condition and summary.
* A human or fallback route exists.
* Route tests cover success, no-match, ambiguous, and escalation paths.
* Trace/debug output is reviewed for each route before go-live.
* Support owners agree on what `RETURN: true` and `RETURN: false` mean for their customer journey.

## Common mistakes

| Mistake                       | Why it happens                                                    | How to avoid it                                           |
| ----------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------- |
| Treating `AGENTS:` as routing | The roster looks like configuration.                              | Add `HANDOFF` entries for executable routes.              |
| Passing unavailable context   | The route references a field that was never gathered or produced. | Gather it, read it from memory, or remove it from `PASS`. |
| Omitting fallback             | Happy-path routing looks complete.                                | Add human, unsupported, or clarification handling.        |
| Overlapping route conditions  | Business categories are not mutually exclusive.                   | Test ambiguous utterances and tighten route descriptions. |

## Troubleshooting

| Symptom                                       | Likely cause                                  | What to check                                                    |
| --------------------------------------------- | --------------------------------------------- | ---------------------------------------------------------------- |
| No transfer happens                           | No handoff route was selected.                | Check `HANDOFF`, `WHEN`, intent category, and fallback coverage. |
| Wrong target receives the user                | Route conditions overlap.                     | Rewrite conditions and add route-specific test utterances.       |
| Target asks for information already collected | Context was not passed or field names differ. | Check `PASS`, target `GATHER`, and trace/debug context.          |
