Skip to content

Vamsi0473/workflow-design-direct-vs-agentic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Workflow Design: Direct vs Agentic

A comprehensive guide and working examples demonstrating the architectural differences between direct function-call workflows and agentic tool-based workflows orchestrated by an LLM.

Table of Contents

  1. What are Direct Function Calls?
  2. What are Agentic Tool Frameworks?
  3. When to Choose Each
  4. Tradeoffs: Performance, Latency, Accuracy, and Cost
  5. Realistic Example: Document Processing Automation
  6. Running the Examples

What are Direct Function Calls?

Direct function calls represent a traditional, procedural approach to automation. Each step in a workflow is explicitly defined and executed in sequence.

Characteristics:

  • 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

Example:

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 metadata

What are Agentic Tool Frameworks?

Agentic workflows use an LLM as an orchestrator that decides which tools to use, in what order, and when to stop.

Characteristics:

  • 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

Example:

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?

When to Choose Each

Choose Direct Workflows When:

✅ 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

Choose Agentic Workflows When:

✅ 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

Tradeoffs: Real-World Measurements

Performance & Latency (Measured Results)

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

Accuracy & Adaptability

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)

Real Cost Analysis (Processing 10,000 documents)

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)

Maintainability

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

Realistic Example: Resume Processing Automation

This project implements a real-world example: intelligently processing PDF resumes to extract structured metadata.

Business Requirements

  1. Load and extract text from resume PDFs
  2. Classify the document type (Resume, Contract, Invoice, Report, etc.)
  3. IF document is a RESUME:
    • Generate a 100-word intelligent summary using LLM
    • Extract structured metadata (name, title, experience, skills)
    • Validate extracted information
  4. ELSE:
    • Stop processing (skip optional steps)
  5. Save results as JSON

Direct Workflow Implementation

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 metadata

Execution 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

Agentic Workflow Implementation

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

Why Direct is Better for This Use Case

  1. Predictable Process: Resume processing follows a known pattern
  2. Cost-Sensitive: 1 API call vs 6 saves 225x on costs
  3. Performance Critical: 1.59s vs 27s is significant at scale
  4. Simple Logic: IF document is RESUME then summarize/metadata, ELSE stop
  5. Known Input Type: We're specifically targeting resumes

When to Use Agentic Instead

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

Environment Configuration

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.

Run Direct Workflow Example

python -m direct_workflow.direct_example

Sample 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...

Run Agentic Workflow Example

python -m agentic_workflow.agent_example

Sample 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...

Running Tests

# 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=html

Performance Comparison

To 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_example

Expected 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

Project Structure

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

Key Takeaways

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

Decision Matrix

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

Use Both!

In real production systems, you often combine both patterns:

  1. Agentic for Planning: Use LLM to plan the workflow once
  2. Direct for Execution: Execute the plan deterministically
  3. 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

Technologies Used

  • 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)

Project Statistics

  • 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

Real-World Metrics

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

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages