Intermediate30 Minutes

Workflows vs Autonomous Agents & ReAct Loops

A software workflow follows a predetermined path through deterministic tasks and LLM calls. An autonomous agent, in contrast, actively determines its execution route at runtime using an iterative cycle of Observation, Thought, and Action.

Prerequisites
LLM API basicsPython async
Learning Objectives
  • •Distinguish deterministic LLM workflows (DAGs) from dynamic agent loops.
  • •Implement a robust ReAct (Reason + Act) loop with structured tool calling.
  • •Handle recursion limits, token budget protection, and infinite loop guards.

In-Depth Architecture & Mechanics

The Spectrum: Workflow vs Agent

1. **Deterministic Chains**: Step A -> Step B -> Step C. The sequence is fixed in code; LLM calls only generate text or transform data within rigid slots. 2. **Router Chains**: An LLM classifies input and routes to 1 of N predefined paths. The branch is dynamic, but the subsequent flow is fixed. 3. **ReAct Pattern (Yao et al., 2022)**: - **Thought**: The model deliberates over the conversation history, available tools, and goal. - **Action**: The model emits a structured function call with strict parameter typing. - **Observation**: The execution environment invokes the tool, captures the output, and appends the result back to context. - **Looping**: Repeats until the agent emits a 'Final Answer' action or encounters an exit condition.

Failure Modes in Agentic Loops - **Semantic Loops**: The agent repeatedly calls the same tool with equivalent arguments because the observation doesn't explicitly resolve its doubt. - **Context Explosion**: Accumulating raw tool observations can quickly exhaust context windows and balloon inference costs. - **Tool Hallucination**: Emitting function arguments that do not conform to the JSON schema.

System Architecture Flow:
User Goal ──> [ Planner / LLM ]
                   │         ▲
                   ▼         │ Observation
             [ Tool Call ] ──┘
                   │
                   ▼ Final Answer
              [ User Output ]
Worked code example:
Typed ReAct Agent State Loop in Python
python
from typing import Annotated, TypedDict, List, Dict, Any
from pydantic import BaseModel, Field

class AgentState(TypedDict):
    messages: List[Dict[str, Any]]
    iterations: int
    max_iterations: int
    is_complete: bool

def reason_and_plan(state: AgentState) -> Dict[str, Any]:
    if state["iterations"] >= state["max_iterations"]:
        return {"is_complete": True, "messages": [{"role": "assistant", "content": "Reached max iteration budget."}]}
    
    # In real runtime: Invoke LLM with tool definitions
    # Returning mock step for demonstration
    return {"iterations": state["iterations"] + 1}
Architectural Tradeoffs
Autonomy vs Predictability: Full autonomous agents can solve novel edge cases, but latency and cost variance are significantly higher.
Context Richness vs Token Cost: Passing entire tool outputs provides fidelity, but can pollute context and degrade attention.
Common Anti-Patterns
Failing to enforce hard recursion limits (e.g. max_iterations = 10), leading to runaway cost spikes.
Not validating tool outputs before re-injecting them into LLM context.
Using generic prompts instead of strictly typed JSON schemas for tool arguments.

Staff & Principal Interview Questions

Confidence: