Workflow vs Agent: Deterministic Orchestration & Dynamic Tool Selection
Quick Diagnosis
| Situation |
Recommended approach |
Why it fits |
|
All steps known ahead of time (e.g., fetch data → prompt → parse → store) |
Workflow |
Immutable execution, easy testing, predictable token usage |
|
Path depends on content or user intent (e.g., “answer any compliance question”) |
Agent |
Chooses tools at runtime, handles unknown sub‑tasks |
|
Regulatory audit required (immutable logs, version‑controlled prompts) |
Workflow |
Deterministic runs produce repeatable audit trails |
|
Live numeric value needed (credit score, market rate) |
Tool call from workflow (authoritative API) |
Guarantees freshness; does not rely on stale retrieval |
| Batch processing with tight cost budget |
Workflow |
One LLM call per step, predictable token usage |
| Real‑time, ad‑hoc question answering |
Agent |
Dynamic reasoning, on‑the‑fly tool selection |
| Mix of known skeleton + occasional live‑value request |
Hybrid (workflow + runtime API/agent) |
Keeps core deterministic, adds flexibility only where required |
Decision Flow
flowchart TD
A["Is the full execution path known ahead of time?"]
B["Can every required tool be enumerated?"]
C["Use a deterministic workflow"]
D["Is the request likely to need unknown sub‑tasks?"]
E["Add an agent layer for dynamic tool selection"]
F["Can live values be fetched via an API?"]
G["Expose API call from the workflow"]
H["Leave decision to the agent at runtime"]
A -->|Yes| B
B -->|Yes| C
B -->|No| D
D -->|Yes| E
D -->|No| F
F -->|Yes| G
F -->|No| H
Architectural Responsibilities
| Layer |
Core duty |
Typical implementation |
| Deterministic Orchestrator |
Define the fixed sequence, validate inputs, enforce business rules, emit immutable logs |
Azure Logic Apps, Temporal, Airflow, hand‑rolled Python DAG |
| Agent Core |
Detect intent, decide which tool or retrieval source to invoke, manage ReAct‑style loops, handle fall‑backs |
LLM prompting with function‑calling schema, structured reasoning templates |
| Tool / Retrieval Layer |
Provide static knowledge (document store) or fresh data (authoritative API) |
Azure Cognitive Search, public REST endpoints, token‑protected credit‑bureau API |
| Governance & Auditing |
Record every step, version‑control prompts, certify compliance checks |
Write‑once log storage, signed manifests, CI linting of workflow definitions |
| Cost & Latency Monitor |
Track token usage, external‑API count, per‑step latency |
OpenTelemetry exporters, custom metric dashboards |
Python Decision Helper (Teaching‑Only)
# decision_helper.py – pure stdlib, no external packages
import json
from pathlib import Path
from typing import Literal, TypedDict
class DecisionInput(TypedDict):
"""Minimal data required to pick workflow vs. agent."""
steps_known: bool # True if the entire sequence can be enumerated
tools_enumerated: bool # True if every tool can be listed up‑front
live_value_needed: bool # True if an authoritative API must be called
dynamic_subtasks: bool # True if request may spawn unknown sub‑tasks
def choose_strategy(data: DecisionInput) -> Literal["workflow", "agent", "hybrid"]:
"""
Return the recommended execution style.
* `workflow` – fully deterministic pipeline
* `agent` – pure agentic control
* `hybrid` – deterministic skeleton with optional runtime API or agent
"""
# Basic validation – fail fast if the contract is broken
assert isinstance(data["steps_known"], bool), "steps_known must be bool"
assert isinstance(data["tools_enumerated"], bool), "tools_enumerated must be bool"
assert isinstance(data["live_value_needed"], bool), "live_value_needed must be bool"
assert isinstance(data["dynamic_subtasks"], bool), "dynamic_subtasks must be bool"
if