Skip to content

Workflows

A workflow is a group of agents that answer one conversation together. You pick which agent answers first, and you say which agents may hand the conversation to which. Like an agent, a workflow is configuration, not code: saving one deploys nothing.

From the outside a workflow looks like one assistant. You start runs against it the same way, and the person chatting sees one conversation. Inside, the members take turns.

A workflow definition has five keys:

  • description — required. What the workflow is for.
  • entry — required. The member that receives the first message of every conversation.
  • agents — required. The members, by agent name. A workflow has at most 20.
  • edges — the handoffs between members. Optional, but a workflow with more than one member needs them: every member must be reachable from the entry.
  • limits — per-run ceilings. See below.

An edge has a from, a to and a kind, and optionally a when and requires_approval. There are two kinds.

transfer hands the conversation over. The receiving agent answers the user from then on, and can hand it back if it has an edge to do so. The sender’s tools gain a transfer_to_<agent> call, and when is a short hint telling it when to use it.

A transfer can also end at a step instead of an agent. The sender then gets a transfer_to_<step> call, and calling it starts that step’s flow in the same run: for example a scripted practice round made of ask steps. When the flow ends, nobody holds the conversation, so the next message goes back to the entry agent, which can start another round. The step must be at the top level (not inside a for_each or loop), and the flow it starts must not lead back to the agent that transferred, or one turn could loop. Only an agent can transfer to a step; requires_approval works as for any transfer.

delegate hands over a task. The worker gets only the task, not the conversation, and returns its answer to the agent that asked. The user never talks to a worker. Delegation can go three levels deep, and delegate edges cannot form a cycle.

Two edges between the same pair of agents, or an edge from an agent to itself, are refused when you save.

You never declare a role. It follows from the edges, and one agent can have several.

  • The entry agent receives the first message.
  • An agent answers the user when it can hold the conversation: the entry, and every member reachable from it over transfer edges.
  • An orchestrator is any agent with a delegate edge out of it.
  • A worker is any agent a delegate edge points to. A worker that is also an orchestrator delegates in turn, which is how hierarchies are built.

A delegated worker runs inside its orchestrator’s call and never holds the conversation, so its transfer edges do not apply while it works on a task; they apply only when it holds the conversation itself (as the entry, or after a transfer to it). It does not capture citations or write memory of its own; the agent that asked answers for it.

A transfer edge that starts at an agent that can never hold the conversation is refused, because it could never apply.

Most workflows are one of two shapes. The console creates both as templates.

A Router puts a triage agent in front. It reads the first message and transfers to the specialist who should answer. Each specialist can hand the conversation back when the topic changes.

flowchart LR
    triage["triage"] -->|transfer| billing["billing"]
    triage -->|transfer| tech["tech"]
    billing -->|transfer| triage
    tech -->|transfer| triage

A Supervisor keeps the conversation with one lead. The lead delegates research and writing to workers, checks what comes back, and answers the user itself.

flowchart LR
    lead["lead"] -.->|delegate| researcher["researcher"]
    lead -.->|delegate| writer["writer"]

Use a Router when the question decides who should answer. Use a Supervisor when one agent should own the answer and call on others for parts of it.

The console has two more templates. Scripted RAG chat answers questions from one collection. Scheduled digest is the fourth template, after Router, Supervisor and Scripted RAG chat, and has no agents. It reads a feed every weekday, summarises what is new and mails it to your team, and creates the schedule trigger that runs it. You give it a feed address, recipients, a time and a time zone. See Triggers and automation.

Normally the agent holding the conversation gets each new message, and the start of the workflow only sees a message when no agent holds the conversation. Set route_every_turn: true and every message starts at the step the Start box leads to instead, even while an agent holds the conversation. That step is usually a router that decides, message by message, who answers:

route_every_turn: true
agents: [tutor]
steps:
intent:
kind: router
branches:
- { name: practice, description: The learner wants a practice round }
- { name: question, description: The learner asks a question }
round:
kind: reply
text: "Here is your next exercise."
edges:
- { from: start, to: intent }
- { from: intent, to: round, branch: practice }
- { from: intent, to: tutor, branch: question }

The Start box must lead to a step; a workflow whose Start box leads straight to an agent is refused when you save. An edge from the start flow to an agent gives that agent the message with the whole conversation, as it does without the option. One trade-off: the agent holding the conversation no longer decides where the next message goes, so a transfer from one agent to another lasts only for that message unless the start flow sends the next one there too. If you turn the option off later, the next message goes to the agent that answered last, as it would have without the option.

Turn it on in the workflow’s Settings, or in its YAML. A workflow can have its own top-level follow_ups block, with the same keys as on an agent (enabled, count, explore, model). It applies to the workflow’s replies; the follow_ups settings of its member agents are ignored inside it, so every answer behaves the same whichever member gives it.

limits bounds how far a workflow can run. Both keys are optional.

key default maximum
max_handoffs_per_turn 5 20
max_model_calls 50 200

max_handoffs_per_turn counts transfers within one turn, from a user’s message to the reply. max_model_calls counts model calls in one run, across every member, workers included. When a run goes over either one it ends with an error that names the limit, so a pair of agents handing the conversation back and forth cannot run without end.

An edge with requires_approval: true pauses the run before the handoff. The person in the chat allows or denies it. A denial reaches the sending agent as the result of its call, and it carries on from there.

This is the same mechanism as require_approval on an agent’s tools, see Agents & assistants. A paused run ends with status interrupted, and you resume it with a decision. The request and the resume call are described in Threads & runs.

Every member runs at the lowest trust tier among the workflow and its members. One untrusted agent makes the whole workflow untrusted. A member’s own collections and tool limits still apply to its own turns, and a run cannot widen them. See Trust tiers.

A workflow uses the same surfaces as an agent:

  • The same threads and runs API. Start a run against the workflow’s assistant_id. See Threads & runs.
  • The same embed. A reply streams with the name of the agent that wrote it, and you decide whether visitors see it. See Embedding an agent.
  • One trace per run, with a span for each agent, and the cost of each agent’s model calls. The online judges score a workflow’s answers as they do an agent’s. See Read traces and evals.

A workflow can also contain fixed steps beside its agents, such as a router, a search or a scripted reply. See Workflow steps.

Next: Build your first workflow.