← Master Index
Vol. 15 Module 15.1 Lecture

Agent Loop

Agent Fundamentals

How This Lesson Fits the Module & Volume

You now have plans, reasoning, memory, reflection, and function calling. The agent loop is the runtime that stitches them: observe → infer → act → observe, until success, failure, or a halt rule. This is the executable heart of Module 15.1.

A one-off while loop is enough to learn. Production loops add persistence—LangGraph checkpointers, HITL interrupts, and later MCP clients as the tool transport. The next lecture, agentic workflows, asks when a loop should be replaced by a mostly deterministic graph.

Learning Objectives

By the end of this lesson, students should be able to:

  • Describe the observe–think–act loop and why it must be bounded.
  • Implement a complete Python loop with tool dispatch, step limits, and finalization.
  • List halt conditions: max steps, token/dollar budget, no-progress, policy deny, user cancel.
  • Log each iteration for eval and episodic memory.
  • Contrast a naive while loop with a durable LangGraph cycle.
  • Avoid infinite tool ping-pong and silent swallow of errors.
Definition

An agent loop is the control cycle that repeatedly (1) sends conversation + tool schemas to a model, (2) executes any requested tools, (3) appends observations (and optional memory/reflection), and (4) stops when the model returns a final answer or a halt condition fires.

Loop vs One-Shot Completion

Halt signalMeaningTypical action
No tool_callsModel thinks it is doneReturn content to user
Max stepsBudget exhaustedPartial answer + escalate
Repeated same tool+argsNo progressBreak; ask human or replan
Policy denyAutonomy bound hitHITL or safe refusal
User cancel / timeoutExternal stopCheckpoint and exit

A Complete Thin Loop

import json from openai import OpenAI client = OpenAI() MAX_STEPS = 6 TOOLS = [{ "type": "function", "function": { "name": "search_kb", "description": "Search policy docs.", "parameters": { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"], }, }, }] def search_kb(query: str) -> str: return "Password resets: Settings > Security > Reset. SSO users contact IT." DISPATCH = {"search_kb": lambda **kw: search_kb(**kw)} def run_agent(user_text: str) -> str: messages = [ {"role": "system", "content": "Solve the user request. Use tools for policy facts. Stop when you can answer."}, {"role": "user", "content": user_text}, ] seen: set[str] = set() for step in range(MAX_STEPS): msg = client.chat.completions.create( model="gpt-4o-mini", messages=messages, tools=TOOLS, tool_choice="auto" ).choices[0].message messages.append(msg) if not msg.tool_calls: return msg.content or "" for call in msg.tool_calls: fingerprint = f"{call.function.name}:{call.function.arguments}" if fingerprint in seen: return "HALT: repeated tool call with no progress. Please rephrase or escalate." seen.add(fingerprint) args = json.loads(call.function.arguments) fn = DISPATCH.get(call.function.name) obs = json.dumps({"error": "unknown_tool"}) if fn is None else fn(**args) messages.append({"role": "tool", "tool_call_id": call.id, "content": obs}) print(f"[step {step}] {call.function.name} {args} -> {obs[:80]}") return "HALT: step budget exceeded." print(run_agent("How do SSO users reset passwords?"))

Naive Loop vs Durable Graph

Thin while loop

  • Easy to teach and unit-test
  • Dies if the process dies
  • HITL is DIY

LangGraph cycle

  • Checkpoints / resume
  • Explicit edges + interrupts
  • Better for long jobs

Either needs

  • Step + cost budgets
  • Tool allowlists
  • Traces for eval / 15.2 memory

Strengths

  • Handles unknown hop counts
  • Composable with any tool set
  • Clear place for logging
  • Maps 1:1 to ReAct

Tradeoffs

  • Unbounded loops explode cost
  • Harder SLAs than a DAG
  • Error handling is on you
  • Eval must be trajectory-aware
Common Misconception

“A real agent has no max iterations—that would limit autonomy.” Unbounded loops are outages waiting to happen. Autonomy is bounded by design (autonomous agent). Always ship step, time, and spend caps, plus no-progress detection.

Knowledge Check

  1. Short Answer: Name the four beats of the agent loop. Answer: Send to model, execute tools, append observations, stop or repeat.
  2. True/False: No tool_calls usually means the model is returning a final answer. Answer: True.
  3. Multiple Choice: Repeated identical tool fingerprints suggest: (a) success, (b) no progress / stuck loop, (c) better pooling. Answer: (b).
  4. Short Answer: Why log each step? Answer: Eval, debugging, episodic memory, cost tracking.
  5. True/False: LangGraph is required to have an agent loop. Answer: False—a thin while-loop is a valid loop; graphs add durability.
  6. Multiple Choice: MAX_STEPS primarily protects: (a) fonts, (b) cost/latency runaway, (c) BPE vocab. Answer: (b).
  7. Short Answer: What should happen on unknown tool names inside the loop? Answer: Fail closed with a structured error observation (do not crash blindly).
  8. Short Answer: Which next lecture asks when not to use a free loop? Answer: Agentic workflow.
  9. Multiple Choice: HITL inside a loop is typically: (a) pause before risky tools, (b) disable JSON, (c) drop memory. Answer: (a).
  10. True/False: Agent eval can ignore trajectories and score only the final sentence. Answer: False—tool misuse matters even if the final text looks fine.

Key Takeaways

  • The agent loop repeatedly calls the model and tools until a final answer or halt rule.
  • Bound steps, detect no-progress, validate tools, and log every iteration.
  • Thin loops teach the idea; LangGraph (and similar) add durability and interrupts.
  • Unbounded looping is not autonomy—it is a missing product constraint.
  • Next: agentic workflows—when to mix loops with deterministic pipelines.
Trainer’s Guide

Whiteboard: Add a token-budget halt beside MAX_STEPS. Show where you would insert a refund HITL gate.

Lab: Inject a buggy tool that always returns “try again.” Confirm the fingerprint halt fires before step 6.

Recap: The agent loop is bounded observe–think–act. Continue with Agentic Workflow.