import{c as e,Q as a,j as t,m as n}from"./chunks/framework.BPKcPtvA.js";const u=JSON.parse('{"title":"Module 2: Agent Architecture","description":"","frontmatter":{},"headers":[],"relativePath":"modules/m2-architecture.md","filePath":"modules/m2-architecture.md","lastUpdated":1780488246000}'),i={name:"modules/m2-architecture.md"};function l(o,s,r,p,d,h){return a(),t("div",null,[...s[0]||(s[0]=[n(`
Every agent system is built on four pillars:
┌─────────────────────────────────────────────────────────────┐
│ AGENT SYSTEM │
├──────────────┬──────────────┬──────────────┬────────────────┤
│ TOOLS │ LOOP │ CONTEXT │ MEMORY │
│ Capabilities │ Autonomy │ Awareness │ Persistence │
│ │ │ │ │
│ • Read/Write │ • Think→Act │ • System │ • Mental │
│ • Bash │ →Obs→Repeat │ prompt │ models │
│ • Search │ • Iteration │ • Messages │ • Expertise │
│ • API calls │ limits │ • Tool │ files │
│ • MCP │ • Terminate │ results │ • Scratch │
│ │ conditions │ • Window │ pads │
│ │ │ mgmt │ • Session logs │
└──────────────┴──────────────┴──────────────┴────────────────┘| Channel | Context Cost | Portability | Auto-Discovery | Best For |
|---|---|---|---|---|
| MCP Server | High (full context per call) | High | Yes (MCP protocol) | Multi-client, standardized tools |
| CLI | Medium | High | No | 80% of new tools, direct control |
| File System Scripts | Low (progressive disclosure) | Medium | No | Context-sensitive, portable |
| Skills | Low | Medium | Yes (skill dir) | Agent-native, behavior rules |
search_web not sw. execute_sql_query not run.Some MCP clients don't support Resources. The fix: every Resource gets a mirror Tool that returns identical data:
# Resource: datasets://loaded → may not work in all clients
# Mirror tool:
@tool
def list_loaded_datasets() -> str:
"""List all currently loaded datasets. Returns names and row counts."""
return json.dumps(registry.list_datasets())LLM call → command string → execute → outputNo loop. Single API call generates a command, you run it. Good for: code generation, translation, summarization.
while not terminal_tool_called:
LLM(invoke with tools) → tool call → execute → feed result backCore pattern. 5+ tools, forced tool choice. Terminal tool (e.g., run_final_query) exits. Good for: data analysis, file editing, web research.
while not complete_task_tool_called:
LLM → tool call → execute → observe → continue or completeAdds explicit complete_task terminal action. Clear success/failure conditions. Good for: multi-step workflows with defined finish criteria.
main_agent → spawns sub_agents → collects results → synthesizesMain agent calls LLM sub-calls for parallel work (e.g., check 10 files for relevance in parallel batches). Good for: codebase analysis, parallel research, batch operations.
orchestrator → team_lead → worker_agents → results bubble upDepth-2+ delegation hierarchy. Each agent has domain, tools, memory. Good for: production systems, complex workflows.
Skills are the building blocks of agent behavior. A skill is a self-contained instruction file that an agent loads and follows.
Skills can be scoped to specific directories. The agent only loads skills relevant to the files it's working on:
repo/
├── .claude/skills/
│ ├── global/
│ │ ├── conversational-response.md
│ │ └── security-policy.md
│ ├── frontend/
│ │ ├── react-patterns.md
│ │ └── css-guidelines.md
│ └── backend/
│ ├── api-design.md
│ └── database-migrations.mdOne CLAUDE.md doesn't scale for large projects. Modern agents walk the directory tree and load the closest rules file:
repo/
├── CLAUDE.md # Root rules (all agents)
├── frontend/CLAUDE.md # Frontend overrides
├── backend/CLAUDE.md # Backend overrides
└── deploy/CLAUDE.md # Deployment rulesSkills and agent configs can be packaged as shareable plugins:
my-agent-kit/
├── agent.yaml # Agent definition
├── skills/ # Skill files
├── tools/ # Custom tools
├── hooks/ # Lifecycle hooks
└── README.md # Usage instructionsThis is how ClaudeFAST distributes their 280 skills and 16 agents as commercial kits.
For large codebases, grep is too slow. An LSP (Language Server Protocol) MCP server gives agents symbol-level search:
Agent → MCP Client → LSP MCP Server → Language Server → CodebaseTools exposed: find_definition, find_references, find_symbols, get_hover_info
An agent-readable workspace is organized so an agent can discover everything it needs without being told.
repo/
├── CLAUDE.md ← Agent reads this FIRST
├── init.sh ← Run this to set up environment
├── feature_list.json ← What features exist, what's done
├── Makefile ← Common commands (test, build, lint)
├── tests/ ← Expected outcomes (evidence)
└── docs/ ← Architecture decisions (ADRs)The first thing an agent should do is NOT start coding. It should initialize:
A feature_list.json gives agents a structured inventory of what to build and what evidence proves completion:
{
"features": [
{
"id": "auth-login",
"status": "done",
"evidence": ["tests/test_auth.py::test_login", "src/auth/login.tsx"]
},
{
"id": "auth-register",
"status": "in_progress",
"evidence": []
}
]
}Every session must leave the workspace in a clean state:
The next agent (or the same agent on the next session) should find the workspace as if no one touched it.
Context windows grow unbounded. Every tool result, every LLM response, every intermediate step gets appended. After 20 turns of file editing, your context contains thousands of lines of file contents and logs.
| Approach | How | Trade-off |
|---|---|---|
| Sliding window | Keep last N messages | Lose early context |
| Summarization | Compress old messages into summary | Information loss |
| Structured outputs | Agents output structured data, not free text | Requires schema design |
| Multi-agent isolation | Each agent has focused context window | Complexity, coordination cost |
[System prompt (always)] + [Recent N turns (full)] + [Summary of earlier turns] + [Current tool results]Every agent maintains a personal expertise file:
# .pi/multi-team/expertise/backend-dev-mental-model.yaml
expertise:
- topic: "API patterns used in this project"
notes: "We use tRPC for type-safe API calls. All endpoints follow /api/trpc/{router}.{procedure}"
last_updated: "2026-04-20"
- topic: "Database conventions"
notes: "SQLite with Drizzle ORM. Migrations in packages/db/src/migrations/"
last_updated: "2026-04-22"Rules:
Ephemeral memory for a single session. Good for tracking:
Forcing the LLM to explain every tool call is the highest-ROI prompt engineering technique:
def search_documentation(query: str, reasoning: str) -> str:
"""
Search documentation.
Args:
query: The search terms
reasoning: WHY you are searching for this (required for audit)
"""
...Why it works:
From single-file-agents research, 4 patterns for scaling agent codebases:
| Architecture | Structure | Best For |
|---|---|---|
| Atomic/Composable | atom/ → molecule/ → organism/ | Reusable tool primitives across many agents |
| Layered | api/ → services/ → models/ → data/ | Clear separation of concerns within one agent |
| Pipeline | steps/ → pipeline_manager/ → shared/ | Data transformation flows |
| Vertical Slice | features/{feature}/{api,service,model}/ | Multiple independent agent capabilities |
Objective: Add file operations + web search tools to the agent from Lab 1.
Starter: course/labs/L2-multi-tool/starter.py
Solution: course/labs/L2-multi-tool/solution.py
Objective: Implement sliding window + summarization for long sessions.
Starter: course/labs/L2-context/starter.py
Solution: course/labs/L2-context/solution.py