04 — Your First Workflow
Until now every example used a single agent. In this lesson you will build a workflow — a graph of processing steps that passes data from one agent to the next in a defined order.
Agents vs Workflows
| Agent | Workflow | |
|---|---|---|
| Steps | Dynamic — the LLM decides what to do | Predefined — you define the execution path |
| Control | The model drives the loop | You control the flow explicitly |
| Use case | Open-ended conversation, tool use | Multi-step business processes, pipelines |
Tip
If you can describe the process as a flowchart, a workflow is the right choice. If the task is open-ended and conversational, use an agent.
Core concepts
Executors
An executor is a single processing unit in a workflow. It can be:
- An Agent (LLM-powered)
- A plain Python function (deterministic logic)
Edges
An edge connects two executors and determines the flow of messages. The output of one executor becomes the input of the next.
The healthcare scenario
We will build a patient triage pipeline:
- TriageAgent — classifies a patient complaint by severity (LOW / MEDIUM / HIGH).
- RoutingAgent — reads the triage result and recommends a hospital department.
The code
File: examples/04-workflow/sequential_workflow.py
import asyncio
import os
from dotenv import load_dotenv
from agent_framework import Agent, WorkflowBuilder
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
load_dotenv()
async def main() -> None:
client = FoundryChatClient(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
model=os.environ.get("FOUNDRY_MODEL", "gpt-5.4-mini"),
credential=AzureCliCredential(),
)
# Agent 1: Triage
triage_agent = Agent(
client=client,
name="TriageAgent",
instructions=(
"You are a hospital triage assistant. "
"Given a patient complaint, classify its severity as LOW, MEDIUM, or HIGH "
"and briefly explain your reasoning. "
"Output format: 'Severity: <LEVEL>. Reason: <text>'"
),
)
# Agent 2: Routing
routing_agent = Agent(
client=client,
name="RoutingAgent",
instructions=(
"You are a hospital department router. "
"Given a triage assessment, recommend the most appropriate department "
"(e.g. General Practice, Cardiology, Neurology, Emergency). "
"Output format: 'Department: <name>. Recommendation: <text>'"
),
)
# Build the workflow
workflow = (
WorkflowBuilder(start_executor=triage_agent)
.add_edge(triage_agent, routing_agent)
.build()
)
# Run
patient_complaint = "I have had a persistent headache for two weeks and occasional dizziness."
print(f"Patient complaint: {patient_complaint}\n")
result = await workflow.run(patient_complaint)
for event in result:
if event.type == "executor_completed":
for resp in event.data:
if hasattr(resp, "executor_id"):
print(f"{resp.executor_id}: {resp.agent_response}\n")
if __name__ == "__main__":
asyncio.run(main())
Step-by-step walkthrough
1. Create two agents
Each agent has a focused role and clear output format. Keeping instructions narrow helps the LLM produce predictable results.
2. Build the workflow graph
workflow = (
WorkflowBuilder(start_executor=triage_agent)
.add_edge(triage_agent, routing_agent)
.build()
)
WorkflowBuilder(start_executor=...)creates the builder with the first executor in the graph.add_edge(source, target)connects two executors — the output oftriage_agentbecomes the input ofrouting_agent.build()validates the graph and returns an immutableWorkflowinstance.
3. Run the workflow
result = await workflow.run(patient_complaint)
for event in result:
if event.type == "executor_completed":
for resp in event.data:
if hasattr(resp, "executor_id"):
print(f"{resp.executor_id}: {resp.agent_response}\n")
The framework executes triage_agent first, passes its output to
routing_agent, and returns a WorkflowRunResult. Iterating over the result
gives you WorkflowEvent objects — filter for executor_completed events to
get each agent's response along with its name via executor_id.
What you can build from here
Workflows support much more than two sequential agents:
| Pattern | Description |
|---|---|
| Conditional edges | Route to different executors based on a condition |
| Fan-out / fan-in | Run multiple executors in parallel and aggregate results |
| Loops | Repeat steps until a condition is met |
| Human-in-the-loop | Pause the workflow and wait for user input |
| Checkpointing | Save and resume long-running workflows |
These advanced patterns are covered in the official workflow samples.
Try it
You should see the triage assessment followed by a department recommendation.
Key takeaways
- A workflow is a directed graph of executors connected by edges.
- Executors can be agents or plain functions.
- Edges define the data flow between executors.
- Workflows give you explicit control over multi-step processes.