Duration: 4 hours | Difficulty: Intermediate–Advanced | Prerequisites: Modules 01–04
Learning Objectives
By the end of this module, you will be able to:
- Explain what AI agents are and how they differ from simple LLM chains
- Implement the ReAct (Reason + Act) pattern from scratch
- Build agents with tool use and function calling
- Design agent loops with proper planning, execution, and reflection
- Handle errors and edge cases in agent systems
1. What Are AI Agents?
From Chains to Agents
A chain is a fixed recipe. An agent picks steps at runtime: read state → think → maybe call a tool → repeat. Think improvising cook vs meal kit with numbered bags.
Chain: Step 1 → Step 2 → Step 3 → Done (fixed path)
Agent: Observe → Think → Act → Observe → Think → Act → ... → Done
(dynamic path, decided at runtime by the LLM)The Agent Loop
┌─────────────────────────────────────────┐
│ AGENT LOOP │
│ │
│ 1. OBSERVE: What's the current state? │
│ ↓ │
│ 2. THINK: What should I do next? │
│ ↓ │
│ 3. ACT: Execute a tool or respond │
│ ↓ │
│ 4. Check: Am I done? │
│ ↓ │
│ No → Go to step 1 │
│ Yes → Return final answer │
└─────────────────────────────────────────┘| Chain | Agent |
|---|---|
| Predictable | Flexible |
| Easier to test | Needs budgets + tracing |
| Great for ETL-ish flows | Great for open-ended tasks |
Fun Fact: Most “agents” in prod are small finite-state machines with an LLM inside—not sci-fi autonomy.
2. The ReAct Pattern
ReAct interleaves natural-language thought with actions (tool calls) and observations (tool results). Older tutorials used Thought: / Action: / Observation: text parsing; modern APIs prefer structured tool calls—but the idea stays: reason, act, observe, repeat.
| Piece | Role |
|---|---|
| Thought | Plan visible (helps debugging) |
| Action | Tool name + args |
| Observation | Ground truth from your code |
Try This! Log every observation in JSON—your future self is debugging at 2 a.m.
Key Takeaway
ReAct is really explicit scaffolding so the model doesn’t “silent tool call” in free text.
3. Tool Use with Function Calling
Providers expose JSON schemas; the model returns tool_calls you execute in Python and feed back as role: "tool" messages.
Key Example: Minimal loop: assistant requests tools until it returns plain text.
[object Object], json
,[object Object], openai ,[object Object], OpenAI
client = OpenAI(api_key=,[object Object],)
,[object Object], ,[object Object],(,[object Object],) -> ,[object Object],:
data = {
,[object Object],: {,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],},
,[object Object],: {,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],},
}
,[object Object], data.get(city, {,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],})
TOOLS = [
{
,[object Object],: ,[object Object],,
,[object Object],: {
,[object Object],: ,[object Object],,
,[object Object],: ,[object Object],,
,[object Object],: {
,[object Object],: ,[object Object],,
,[object Object],: {,[object Object],: {,[object Object],: ,[object Object],}},
,[object Object],: [,[object Object],],
},
},
}
]
messages = [
{,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],},
{,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],},
]
,[object Object], ,[object Object],:
resp = client.chat.completions.create(
model=,[object Object],, messages=messages, tools=TOOLS, tool_choice=,[object Object],
)
msg = resp.choices[,[object Object],].message
messages.append(msg)
,[object Object], ,[object Object], msg.tool_calls:
,[object Object],(msg.content)
,[object Object],
,[object Object], call ,[object Object], msg.tool_calls:
args = json.loads(call.function.arguments)
result = get_weather(**args) ,[object Object], call.function.name == ,[object Object], ,[object Object], {,[object Object],: ,[object Object],}
messages.append(
{,[object Object],: ,[object Object],, ,[object Object],: call.,[object Object],, ,[object Object],: json.dumps(result)}
)4. Agent Memory
Agents need short-term (chat history), working (current plan, variables), and sometimes long-term (notes DB, vector store).
| Memory kind | Implementation sketch |
|---|---|
| Short-term | Trim/summarize last N messages |
| Working | Dict in your orchestrator; inject as system preamble |
| Long-term | Embeddings + DB; retrieve like RAG |
Concept: Chat transcripts are not a database—persist what matters explicitly.
5. Planning Strategies
Plan-and-Execute
Phase 1: ask the LLM for a numbered plan with tool hints. Phase 2: execute steps sequentially (or parallelize when safe). Phase 3: synthesize final answer. Separates strategy from tactics.
| When it helps | When it’s overkill |
|---|---|
| Multi-tool workflows | Single API lookup |
6. Error Handling in Agent Systems
| Failure | Prod response |
|---|---|
| Tool timeout | Retry with backoff; surface friendly error |
| Bad JSON args | Re-prompt model with validation message |
| Infinite loop | max_iterations + circuit breaker |
| Model refuses | Fallback model or degrade to search-only |
Plain-English robust pattern: wrap each tool in try/except, append structured errors to messages, let the model recover once or twice, then bail with a safe template response.
Key Takeaway
Agents fail messy—budgets, logging, and tests are non-optional.
Practice Exercises
Exercise 1: Calculator Agent (Beginner)
Multi-step math via a safe arithmetic tool (not eval on raw user strings).
Exercise 2: Research Agent (Intermediate)
Search + note tools; output structured memo.
Exercise 3: Memory Agent (Intermediate)
Recall user prefs from a lightweight store after 10 turns.
Exercise 4: Plan-and-Execute Agent (Advanced)
CSV path + question → plan → execute with pandas in a sandbox.
Exercise 5: Self-Correcting Agent (Advanced)
Second pass critiques first answer using tool-grounded checks.
Mini-Project: Personal Research Assistant Agent
Tools: search_notes, save_summary, calendar_stub. Enforce max steps, log traces, redact secrets.
Key Takeaways
Key Takeaway
- Agents = LLM + loop + tools + memory, not a separate species of model.
- ReAct makes reasoning and acting inspectable.
- Function calling is the modern plumbing for tools.
- Memory should be intentional, not accidental transcript growth.
- Plan-and-execute reduces thrash on complex tasks.
- Errors and iteration caps are part of the UX contract.