A comprehensive guide and working examples demonstrating the architectural differences between direct function-call workflows and agentic tool-based workflows orchestrated by an LLM.
- What are Direct Function Calls?
- What are Agentic Tool Frameworks?
- When to Choose Each
- Tradeoffs: Performance, Latency, Accuracy, and Cost
- Realistic Example: Document Processing Automation
- Running the Examples
Direct function calls represent a traditional, procedural approach to automation. Each step in a workflow is explicitly defined and executed in sequence.
- Deterministic flow: The sequence of operations is hard-coded
- No dynamic decision-making: Steps execute regardless of context
- Simple debugging: Clear stack traces and explicit logic
- Predictable performance: Latency is known in advance
- Human control: Developers determine the exact workflow
def process_document(pdf_path):
pdf_bytes = load_pdf(pdf_path)
text = extract_text(pdf_bytes)
summary = summarize_text(text) # Always runs
category = classify_document(text)
metadata = extract_metadata(text)
save_results(metadata)
return metadataAgentic workflows use an LLM as an orchestrator that decides which tools to use, in what order, and when to stop.
- Dynamic decision-making: The LLM decides which tools to call based on context
- Self-correcting: Can retry, rearrange, or skip steps based on intermediate results
- Flexible: Can handle novel scenarios without code changes
- Higher latency: Multiple LLM calls add network round-trips
- Less predictable: Depends on LLM behavior and prompt engineering
- Context-aware: Intelligent about task dependencies and relevance
agent = DocumentProcessingAgent()
result = agent.run(goal="Process this PDF and extract structured metadata")
# The LLM decides:
# - Should I summarize? (Maybe skip if PDF is < 500 words)
# - Which classification model to use?
# - What metadata fields are relevant?✅ The process is well-defined and won't change
✅ You need predictable latency (e.g., real-time systems)
✅ Cost is critical (no LLM calls = lower operating cost)
✅ Compliance requires explainable, auditabl workflows
✅ The domain is narrow and rules-based
✅ You want minimal external dependencies
Example domains:
- Invoice processing with a fixed schema
- Batch data pipeline ETL
- Real-time transaction validation
- Medical imaging analysis with strict protocols
✅ The workflow varies based on input characteristics
✅ You need intelligent error handling and recovery
✅ The task requires reasoning across multiple steps
✅ Latency is acceptable (user-facing, async jobs)
✅ Budget allows for LLM API calls
✅ Requirements are ambiguous or evolving
Example domains:
- Customer support automation
- Complex document analysis (mixed formats, types)
- Research automation
- Creative content generation
- Multi-step reasoning tasks
| Metric | Direct | Agentic | Difference |
|---|---|---|---|
| Total Time | 1.59s | 27.01s | 17x faster |
| LLM API Calls | 1 call | 6 calls | 6x fewer |
| API Cost | ~$0.0008 | ~$0.18 | 225x cheaper |
| Predictability | Very predictable | Variable | Direct wins |
| Throughput | High | Medium | Direct wins |
| Scalability | Horizontal | Rate-limited | Direct wins |
| Aspect | Direct | Agentic |
|---|---|---|
| Edge cases | Misses unknown scenarios | Adapts via reasoning |
| Error recovery | Explicit fallbacks | LLM decides recovery |
| Output quality | Consistent | Context-aware (higher quality) |
| Hallucinations | N/A | Possible (mitigated with good prompts) |
| Factor | Direct | Agentic |
|---|---|---|
| Total API Cost | ~$8 | ~$1,800 |
| Processing Time | 4.4 hours | 75 hours |
| Cost per document | $0.0008 | $0.18 |
| Infrastructure | Minimal | High (LLM API limits) |
| Aspect | Direct | Agentic |
|---|---|---|
| Code changes | Modify function logic | Adjust prompts / tools |
| Debugging | Explicit stack traces | Opaque LLM reasoning |
| Testing | Deterministic tests | Probabilistic (seed for consistency) |
| Adaptation | Requires code changes | Prompt engineering |
This project implements a real-world example: intelligently processing PDF resumes to extract structured metadata.
- Load and extract text from resume PDFs
- Classify the document type (Resume, Contract, Invoice, Report, etc.)
- IF document is a RESUME:
- Generate a 100-word intelligent summary using LLM
- Extract structured metadata (name, title, experience, skills)
- Validate extracted information
- ELSE:
- Stop processing (skip optional steps)
- Save results as JSON
def process_document_direct(pdf_path: str) -> DocumentMetadata:
"""Sequential execution with conditional logic."""
# Step 1: Load PDF
pdf_bytes = load_pdf(pdf_path)
# Step 2: Extract text
text = extract_text(pdf_bytes) # Real PDF extraction with PyPDF2
# Step 3: Classify document
classification = classify_document(text)
# Step 4-6: Conditional steps (IF-ELSE)
if classification.document_type == "RESUME":
# Only process if it's a resume
summary = summarize_text(text) # 1 LLM call to gpt-3.5-turbo
metadata = extract_metadata(text, classification)
is_valid = validate_results(metadata)
else:
# Stop - skip optional steps
return empty_result()
# Step 7: Save results
save_results(metadata)
return metadataExecution Trace (Real Results):
Direct Workflow Execution: 1.59 seconds
├─ Step 1: Load PDF ✓ (20ms)
├─ Step 2: Extract text: 2,359 characters ✓ (150ms)
├─ Step 3: Classify document: RESUME (92% confidence) ✓ (80ms)
├─ Step 4: Summarize with LLM ✓ (1,200ms) [1 API call]
│ └─ Summary: "Vamsi Krishna is a Lead Software Engineer with 9+ years..."
├─ Step 5: Extract metadata: 4 fields ✓ (50ms)
├─ Step 6: Validate results: PASSED ✓ (20ms)
└─ Step 7: Save results ✓ (70ms)
Final Result:
- Document Type: RESUME
- Confidence: 92%
- API Calls: 1
- Processing Time: 1.59s
def process_document_agentic(pdf_path: str) -> DocumentMetadata:
"""LLM makes decisions about which tools to call next."""
agent = SimpleAgentOrchestrator(
goal="Extract text from PDF, classify if RESUME, summarize, extract metadata, validate"
)
# Agent loop - LLM decides what to do at each step
while not agent.is_complete:
decision = agent.think() # LLM call - analyzes current state
if decision.action == "load_pdf":
agent.observe(load_pdf(pdf_path))
elif decision.action == "extract_text":
agent.observe(extract_text(agent.pdf_bytes))
elif decision.action == "classify_document":
agent.observe(classify_document(agent.text))
elif decision.action == "summarize_text":
agent.observe(summarize_text(agent.text)) # Nested LLM call
elif decision.action == "extract_metadata":
agent.observe(extract_metadata(agent.text, agent.classification))
elif decision.action == "validate_results":
agent.observe(validate_results(agent.metadata))
elif decision.action == "finish":
break
return agent.get_results()Execution Trace (Real Results):
Agentic Workflow Execution: 27.01 seconds
├─ LLM Decision 1: load_pdf ✓ (3.45s) [1 API call]
├─ LLM Decision 2: extract_text ✓ (4.12s) [1 API call]
├─ LLM Decision 3: classify_document ✓ (4.08s) [1 API call]
├─ LLM Decision 4: summarize_text ✓ (8.95s) [1 API call]
│ └─ Summary: "Vamsi Krishna is a Lead Software Engineer with 9+ years..."
├─ LLM Decision 5: extract_metadata ✓ (3.92s) [1 API call]
├─ LLM Decision 6: validate_results ✓ (2.15s) [1 API call]
└─ Save results ✓ (0.34s)
Final Result:
- Document Type: RESUME
- Confidence: 92%
- API Calls: 6
- Processing Time: 27.01s
- Predictable Process: Resume processing follows a known pattern
- Cost-Sensitive: 1 API call vs 6 saves 225x on costs
- Performance Critical: 1.59s vs 27s is significant at scale
- Simple Logic: IF document is RESUME then summarize/metadata, ELSE stop
- Known Input Type: We're specifically targeting resumes
If requirements change to:
- Process 50+ diverse document types with different rules
- Intelligently skip steps based on document characteristics
- Recover from errors by trying alternative approaches
- Handle completely unknown document formats
Then agentic becomes the better choice. ├─→ Extract Text (always) ├─→ Classify Document Type (always) │ ├─→ If Invoice: │ ├─ Extract line items │ ├─ Calculate totals │ └─ Validate against schema │ ├─→ If Contract: │ ├─ Extract party names │ ├─ Find key dates │ └─ Identify payment terms │ ├─→ If Report: │ ├─ Summarize (always runs) │ ├─ Extract key metrics │ └─ Identify trends │ └─→ Save structured metadata
**Trade-off**: You must hard-code all possible document types upfront. Adding a new type requires code changes.
### Agentic Workflow Version
PDF Input + Goal: "Extract structured metadata" │ ├─→ LLM analyzes task │ ├─→ LLM decides: "I need to understand this document first" │ └─ Call: extract_text_tool() │ ├─→ LLM analyzes extracted text │ ├─→ LLM decides: "This is a contract, not an invoice" │ └─ I'll skip invoice parsing │ ├─→ LLM decides: "The text is long and complex" │ └─ Call: summarize_tool() │ ├─→ LLM decides: "Now I can extract structured data" │ ├─ Call: classify_tool() │ └─ Call: extract_metadata_tool() │ └─→ Return structured results + reasoning
**Trade-off**: More flexible and handles novel documents, but slower and requires good prompting.
---
## Diagrams
### Direct Workflow (Fixed Pipeline)
┌─────────────┐ │ PDF Input │ └──────┬──────┘ │ v ┌──────────────────┐ │ Load PDF │ └──────┬───────────┘ │ v ┌──────────────────┐ │ Extract Text │ └──────┬───────────┘ │ v ┌──────────────────┐ │ Classify Type │ └──────┬───────────┘ │ v ┌──────────────────┐ │ Summarize │ (always) └──────┬───────────┘ │ v ┌──────────────────┐ │ Extract Meta │ └──────┬───────────┘ │ v ┌──────────────────┐ │ Save Results │ └──────┬───────────┘ │ v ┌──────────────────┐ │ Structured Data │ └──────────────────┘
### Agentic Workflow (LLM-Orchestrated)
┌─────────────────────┐ │ PDF Input + Goal │ └──────┬──────────────┘ │ v ┌──────────────────────────────┐ │ LLM Orchestrator │ │ (Analyzes goal, decides │ │ which tool to call next) │ └──────┬───────────────────────┘ │ ├─→ extract_text_tool() │ │ │ v │ [Text extracted] │ ├─→ classify_tool() │ │ │ v │ [Document type identified] │ ├─→ summarize_tool() (conditional) │ │ │ v │ [Context-aware summary] │ └─→ extract_metadata_tool() │ v [Structured metadata] │ v [Return to user]
---
## Running the Examples
### Prerequisites
- Python 3.8+
- OpenAI API key (for real LLM integration)
- A PDF file to process (or use provided samples)
### Installation
```bash
# Clone the repository
git clone https://github.com/Vamsi0473/workflow-design-direct-vs-agentic.git
cd workflow-design-direct-vs-agentic
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Set up environment variables
cp .env.example .env
# Edit .env with your OpenAI API key
Create a .env file in the project root:
OPENAI_API_KEY=sk-proj-your-api-key-here
MODEL_FOR_AGENTIC=gpt-4-turbo-preview
MODEL_FOR_DIRECT=gpt-3.5-turbo
Note: The .env file is protected by .gitignore for security.
python -m direct_workflow.direct_exampleSample Output:
============================================================
DIRECT WORKFLOW: Document Processing
============================================================
Goal: Extract text, classify the document type if it is resume then summarize in 100 words,
extract structured metadata, and validate the results else stop
[Step 1] Loading PDF...
✓ Loaded PDF: Vamsi_Krishna_Resume.pdf
[Step 2] Extracting text...
✓ Extracted text: 2,359 characters
[Step 3] Classifying document...
✓ Document classified as: RESUME
✓ Document is a RESUME - proceeding with summarization, metadata extraction, and validation
[Step 4] Summarizing text...
✓ Summary generated using OpenAI LLM
[Step 5] Extracting metadata...
✓ Extracted metadata: 4 fields
[Step 6] Validating results...
✓ Validation: ✓ PASSED
💾 Saving results...
✓ Saved results to: output/metadata.json
============================================================
✅ Direct workflow complete in 1.59s
============================================================
📊 Results Summary:
Document Type: RESUME
Confidence: 92%
Text Length: 2,359 characters
Processing Time: 1.59s
Metadata Fields: 4
📝 Summary:
Vamsi Krishna is a Lead Software Engineer with 9+ years of experience in cloud-native
applications and CI/CD pipelines...
python -m agentic_workflow.agent_exampleSample Output:
============================================================
AGENTIC WORKFLOW: Document Processing
============================================================
Goal: Extract text, classify the document type if it is resume then summarize in 100 words,
extract structured metadata, and validate the results else stop
Current State: start
Observations: None
=== Step 1: Agent Thinking ===
[Thinking with LLM...]
Reasoning: I need to process this resume document. First, I should load and extract the text.
Decision: load_pdf
[Step 1] Loading PDF...
✓ Loaded PDF: Vamsi_Krishna_Resume.pdf
=== Step 2: Agent Thinking ===
[Thinking with LLM...]
Reasoning: Now I have the PDF, I need to extract the text from it.
Decision: extract_text
[Step 2] Extracting text...
✓ Extracted text: 2,359 characters
=== Step 3: Agent Thinking ===
[Thinking with LLM...]
Reasoning: I have the text. Let me classify the document to understand what type it is.
Decision: classify_document
[Step 3] Classifying document...
✓ Document classified as: RESUME
=== Step 4: Agent Thinking ===
[Thinking with LLM...]
Reasoning: This is a RESUME document. According to the goal, I should summarize it.
Decision: summarize_text
[Step 4] Summarizing text...
✓ Summary generated using OpenAI LLM
=== Step 5: Agent Thinking ===
[Thinking with LLM...]
Reasoning: I've classified and summarized. Now I should extract structured metadata.
Decision: extract_metadata
[Step 5] Extracting metadata...
✓ Extracted metadata: 4 fields
=== Step 6: Agent Thinking ===
[Thinking with LLM...]
Reasoning: I've extracted all required information. Let me validate the results.
Decision: validate_results
[Step 6] Validating results...
✓ Validation: ✓ PASSED
[Step 7] Saving results...
✓ Saved results to: output/metadata.json
============================================================
✅ Agentic workflow complete in 27.01s
============================================================
📊 Results Summary:
Document Type: RESUME
Confidence: 92%
Text Length: 2,359 characters
Processing Time: 27.01s
Metadata Fields: 4
LLM Calls: 6
📝 Summary:
Vamsi Krishna is a Lead Software Engineer with 9+ years of experience in cloud-native
applications and CI/CD pipelines...
# Run all tests (27 passing tests)
pytest tests/ -v
# Run specific test file
pytest tests/test_direct.py -v
pytest tests/test_agentic.py -v
# Run with coverage report
pytest tests/ --cov=direct_workflow --cov=agentic_workflow --cov-report=htmlTo compare both workflows side-by-side:
# Terminal 1: Run direct workflow
time python -m direct_workflow.direct_example
# Terminal 2: Run agentic workflow
time python -m agentic_workflow.agent_exampleExpected Results:
Direct Workflow: 1.59 seconds (1 LLM call)
Agentic Workflow: 27.01 seconds (6 LLM calls)
Speed difference: 17x faster with direct approach
Cost difference: 225x cheaper with direct approach
workflow-design-direct-vs-agentic/
├── README.md # This file
├── requirements.txt # Python dependencies
├── .gitignore # Git ignore rules
│
├── direct_workflow/ # Direct function-call example
│ ├── __init__.py
│ ├── models.py # Pydantic models
│ └── direct_example.py # Main example
│
├── agentic_workflow/ # LLM-orchestrated agent example
│ ├── __init__.py
│ ├── models.py # Pydantic models
│ ├── tools.py # Tool definitions
│ └── agent_example.py # Agent implementation
│
└── tests/ # Test suite
├── __init__.py
├── test_direct.py # Tests for direct workflow
└── test_agentic.py # Tests for agentic workflow
| Aspect | Direct | Agentic |
|---|---|---|
| Best for | Well-defined, rules-based processes | Complex, context-dependent tasks |
| Speed | 1.59s per document | 27.01s per document |
| Cost | ~$0.0008 per document | ~$0.18 per document |
| API Calls | 1 call | 6 calls |
| Flexibility | Low (fixed sequence) | High (dynamic adaptation) |
| Error handling | Explicit try-catch | LLM decides recovery |
| Maintenance | Easy to debug | Prompt engineering required |
| Scalability | Horizontal scaling | LLM rate-limited |
| Edge cases | Must be hard-coded | Handled adaptively |
START: Choosing Between Direct and Agentic
│
├─ Do you know the exact process workflow?
│ ├─ YES → Use DIRECT
│ │ └─ Implement with conditional logic
│ └─ NO → Consider next question
│
├─ Can the process vary significantly by input?
│ ├─ YES → Use AGENTIC
│ │ └─ Implement with tool selection
│ └─ NO → Use DIRECT
│
├─ Is cost critical? (processing millions of items)
│ ├─ YES → Use DIRECT
│ │ └─ Optimize API calls
│ └─ NO → AGENTIC acceptable if other factors justify it
│
└─ Is latency critical? (real-time, <1s required)
├─ YES → Use DIRECT
└─ NO → AGENTIC acceptable for async tasks
In real production systems, you often combine both patterns:
- Agentic for Planning: Use LLM to plan the workflow once
- Direct for Execution: Execute the plan deterministically
- Fallback Strategy: Direct workflow with agentic error recovery
Example:
# Get a plan from the agent (once)
plan = agent.create_plan(document) # 1 LLM call
# Execute the plan directly (deterministically)
for step in plan.steps:
execute_step(step) # No LLM calls
# If errors occur, use agentic recovery
if error_encountered:
recovery_plan = agent.create_recovery_plan(error) # 1 LLM call- Python 3.13.3 - Core language
- OpenAI API - gpt-4-turbo-preview (agentic), gpt-3.5-turbo (direct)
- Pydantic - Data validation with models
- PyPDF2 - PDF text extraction
- pytest - Testing framework
- python-dotenv - Environment configuration
- Async/Await - Concurrency patterns (if needed)
- 27 tests - All passing
- 2 workflow architectures - Fully implemented and compared
- 5 shared tools - Extract, classify, summarize, validate, save
- 2 execution patterns - Direct (1.59s) and Agentic (27.01s)
- 225x cost difference - At scale between approaches
From processing Vamsi_Krishna_Resume.pdf:
Direct Workflow:
- Execution time: 1.59 seconds
- API calls: 1
- Cost: ~$0.0008
- Latency: Predictable
Agentic Workflow:
- Execution time: 27.01 seconds
- API calls: 6
- Cost: ~$0.18
- Latency: Variable
Processing 10,000 documents:
- Direct: 4.4 hours, $8 total cost
- Agentic: 75+ hours, $1,800 total cost
Last Updated: November 2025
Author: Vamsi Krishna
Repository: https://github.com/Vamsi0473/workflow-design-direct-vs-agentic