Module 2 · Part A of 3

The Workflow Agent

A single ReAct loop handles most one-shot tasks, but harder problems sometimes need structure that decides work before the next tool result arrives. A workflow agent means an agent system where your harness controls a workflow: a graph of model calls, deterministic code steps, tool calls, and specialist loops. This shape helps when sub-tasks that run in parallel can share results, when a plan can be written before tools run, or when routing should follow a rule instead of the last observation.

The harness can scope a workflow around a model call, a deterministic step, a specialist loop, or a group of parallel branches. At each boundary, it decides what context crosses, what can branch, and which results feed the next pipeline stage. Fan-out and fixed routing make that control visible without replacing the ReAct loop from the previous page.

Two key patterns that differ in when the model decides

REACTIVE · STEP-BY-STEP

ReAct (Reason + Act)

At each step the model reads the latest observation before it picks an action and runs a tool, then sizes up whatever came back and chooses again. The agent reacts to whatever the previous tool call returned, so the path through the tools takes shape as it runs. That makes ReAct strong when the path depends on intermediate results and weak when many steps could have run at once.

Paper: Yao et al., 2022.

DELIBERATIVE · PLAN-THEN-EXECUTE

ReWOO (Reason Without Observation)

The model writes the full plan upfront in one LLM call before any tool runs at all. A deterministic executor then runs every tool that the plan named, often in parallel, and a second LLM call reads what came back to synthesize the results. Because the plan never sees a tool result, the model "reasons without observation." That makes ReWOO strong when the steps are independent and weak when later steps need to react to earlier ones.

Paper: Xu et al., 2023.

ReAct interleaves a reasoning step with each tool call, reacting to every observation before deciding the next move.
ReWOO writes the full plan before any tool runs, executes the steps without re-asking the model, then synthesizes once.
In practice, you can have both. Many real systems borrow from each approach at once. The tools a ReAct loop calls might internally run a planned, ReWOO-style pipeline, and a planner that lays its work out in advance still needs sub-agents to execute each step, which are usually ReAct loops in their own right. Compose these software components wherever their strengths fit, reserving a Workflow Agent for tasks that split into independent workstreams.

When a single loop beats splitting into agents

Without independent workstreams, the coordination overhead of multi-agent composition buys nothing, and one plain loop stays faster and easier to debug.

The overhead tax in concrete terms. Every agent boundary adds model-call latency and routing logic. It also creates another source of malformed messages and replaces a readable timeline with a trajectory that fans across workers.

That tax is fixed regardless of the task, so the question becomes whether the work returns enough to cover it. A linear job that one prompt already handles will never recoup the extra calls and the routing logic that they require. The split begins to earn its keep only once the task itself carries the kind of structure that a single loop has no choice but to flatten down into one timeline. Any one of the conditions below makes the trade pay off.

Applied · PipelineRun the full plan-execute-synthesize pipeline?

Running a ReWOO pipeline against the NVIDIA glossary

The cell below runs a ReWOO pipeline against the NVIDIA glossary, using helpers.webSearch (the ranked glossary search you met in Module 1c) for every retrieval the plan calls for. The glossary explorer shows the full index this searches and lets you run any query the planner might emit:

Promise.all is JavaScript's helper for starting several promises and waiting until all of them finish. Here it is just the concurrency mechanism: it does not call the model and it does not decide which searches to run.

  1. Planner. One schema-bound LLM call emits a JSON list of 3-5 search queries.
  2. Executor. Plain JavaScript. Every query runs concurrently via Promise.all, with no LLM calls at this stage.
  3. Synthesizer. A second LLM call reads every result and writes the brief, citing each search by index.

Two LLM calls total, plus N parallel glossary searches. Edit the research goal and watch the planner's query list change.

The ReWOO pattern plans every tool call up front, runs them in parallel, then synthesizes in one final call. Xu et al. (2023).

Routing a ticket to one specialist with a fixed enum

Routing is a different shape of multi-agent in which a triage agent classifies the input and hands it to one specialist. Because the classifier must emit one of a fixed enum of categories, the output needs a tight contract. A fixed enum is a closed list of allowed labels; if the model returns anything else, the router should reject the route or retry under stricter instructions instead of guessing. Each specialist downstream owns a narrow system prompt and does not need to see the triage agent's reasoning.

The four-value enum picks exactly one specialist to handle the request.

Fanning one shared input out to specialists at once

The ReWOO pipeline was parallel by construction, since every query it planned ran concurrently against the glossary. A more common parallel pattern fans one shared input out to several specialists that each carry their own system prompt and all run at once. In the trace, total wall time tracks the slowest specialist while the others overlap inside that window, the Gantt chart shows each specialist's duration, and all specialists share one web-search result so cost stays bounded.

Deep · FactoryFactor repeated specialists into one declaration?

Declaring specialists from a factory instead of hand-writing each

Each of the four exercises above built a small agent by hand from the same few pieces of boilerplate that production code should never have to retype for every new specialist. Those pieces are a role label, a system prompt, a tool list, and an invocation. The factory pattern parameterises those four moving parts, so you declare specialists instead of writing them:

  • Role. A short label, used for logs and routing.
  • System prompt. The behaviour contract: what it does, what it refuses, and how it phrases its replies.
  • Tools. The JSON-Schema-described functions it can call, if any.
  • Invoke contract. A consistent shape (specialist.run(input)) that returns the final reply.

CrewAI, LangChain, and LangGraph all expose this same factory under names that vary by framework, whether Agent or create_agent or a role/goal dataclass. The cell below builds two specialists from the same four parameters, an arithmetic tutor and a translator that both run on one input with their replies rendered side by side.

Before you continue

  1. The ReWOO planner above emits a JSON list of queries. What is the failure mode if a later query needs a fact from an earlier query's result? Which of the two patterns from the top of this page do you switch to?
  2. The triage router has a fixed enum of categories. What should the router do if the model emits a category that is not in the enum? Is the JSON schema enough by itself, or do you also need application-side validation?
  3. The factory exercise parameterises four things (role, system prompt, tools, invoke). What would you add as a fifth parameter to prevent a specialist from drifting into another specialist's domain when the input is ambiguous?
The next two parts carry this composition idea forward. Part B (Indices) points the same idea at corpora rather than at other agents so that a knowledge layer becomes an agent wrapping a body of data behind a query interface. Part C (Deep Agents) takes it further still, into a planner agent that dispatches sub-agents in fresh contexts and persists their working state to a virtual filesystem.

References

Comprehensive list at Going Further · References.

Try it · the triage router, live

Ask a support question and the artifact classifies it into one category with a single model call before it routes that ticket to the matching specialist's system prompt and streams the answer back in that voice. It runs the same classify-then-specialist pattern shown above. The categories here are a customer-support set rather than the IT help-desk enum. Its four values are billing, technical, account, and other. Only the category list changes when the domain changes, while the routing mechanism underneath stays identical.

← Module 1c: Tools at Scale