Workflows vs Agents
Key Points
- Agents: free-form; LLM decides flow at every step. Flexible; harder to predict / debug.
- Workflows: structured; deterministic where possible; LLM only at well-defined points. Predictable; easier to test.
- Use workflows for known procedures. Use agents for exploratory tasks.
- Hybrid: workflow with agentic steps inside.
When workflow
1. User submits PR
2. CI runs tests
3. If pass: send to LLM for code review
4. Post review as comment
5. Notify author
Steps are deterministic; LLM is one tool in a known sequence.
public async Task RunPrReview(int prId, CancellationToken ct)
{
var pr = await _git.GetPrAsync(prId, ct);
var tests = await _ci.RunTestsAsync(pr.Branch, ct);
if (!tests.Passed) return;
var review = await _reviewerAgent.InvokeAsync($"Review this diff:\n{pr.Diff}", ct);
await _git.PostCommentAsync(prId, review.Text, ct);
await _notifier.SendAsync(pr.Author, "PR reviewed", ct);
}
Workflow engines for richer cases: Durable Functions, Temporal.io. See Workflow Engines.
When agent
1. User: "Help me plan my trip to Rome"
2. Agent: ask about budget, dates, interests
3. Agent: search flights/hotels
4. Agent: present options
5. User refines
6. Agent iterates
Path unpredictable; LLM drives.
Hybrid: workflow with agent steps
1. User submits ticket
2. Classify (LLM tool call) → category
3. Route to workflow per category
4. Each workflow has agent steps where appropriate
Most production AI is hybrid.
Comparison table
| Aspect | Agent | Workflow |
|---|---|---|
| Predictability | Low | High |
| Debugging | Hard | Easier |
| Cost | Variable | Predictable |
| LLM stochasticity | Pervasive | Confined |
| Test | LLM-as-judge / human | Standard |
| Failure recovery | Hard | Engine handles |
| Versioning | Hard | Engine versioning |
Decision heuristic
In Agent Framework
Agent Framework supports both styles. Agents via the orchestration patterns (sequential, concurrent, group chat, handoff, magentic). Workflows via your own code with agents as components.
For full workflow engines, pair with Durable Functions:
[Function(nameof(PrWorkflow))]
public static async Task<Result> PrWorkflow(
[OrchestrationTrigger] TaskOrchestrationContext ctx)
{
var pr = await ctx.CallActivityAsync<Pr>(nameof(GetPr), prId);
var tests = await ctx.CallActivityAsync<TestResult>(nameof(RunTests), pr);
if (tests.Passed)
{
var review = await ctx.CallActivityAsync<string>(nameof(InvokeAgent), pr);
await ctx.CallActivityAsync(nameof(PostComment), (prId, review));
}
return new(/* ... */);
}
Engine handles retries, durability; activities call agents.
Eval
- Workflows: assert step outputs; deterministic tests.
- Agents: harder; LLM-as-judge, behavior tests.
Senior considerations
- Default to workflow; only fallback to agents when truly needed.
- Constrain agents to small steps within workflow.
- Trace with OTel to see flow visually.
- Production: most successful agent-based products are workflow-shaped under the hood.