Skip to content
🎓 Find your path Subscribe

Anatomy of an Agent

Tier 2 · Building 7 min read

Before this, read:

  • Tools 101 — you need to know what a tool call looks like
  • The skills system — skills and agents are different; this article clarifies the line

“Agent” gets used for everything from a one-line shell script to a 10,000-token orchestration loop. On this site, when we say specialist agent, we mean something specific: a Python package that can be invoked on the command line, holds its own state, and does exactly one thing well.

The JD system has ~31 of them. They do not share state carelessly, they do not step on each other, and any one can be upgraded or replaced without touching the others. That modularity doesn’t happen by accident — it comes from a consistent on-disk shape.

Every specialist agent in ~/agent-system/agents/ follows this layout:

agents/
researcher/
__init__.py
main.py ← the entry point; importable or CLI
agent.py ← business logic
kb/ ← optional knowledge base (KB-backed agents)
tests/
test_researcher.py

The directory name is the agent’s identity. The --caller argument in ask_agent, the registry slug, the cron PYTHONPATH path — they all key off this name. Rename the directory and you’ve changed the agent’s address everywhere.

Every agent exposes a CLI via python3.12 -m agents.<name>. Some examples:

Terminal window
# Deep-research agent
python3.12 -m agents.researcher.main "What is the state of POD merch margins in 2026?"
# MBA course expert
python3.12 -m agents.professor --course MBA-560 "What does Madden say about multicollinearity?"
# Health expert
python3.12 -m agents.health_expert "Assess my GH stack: reta 2mg + CJC-no-DAC + ipamorelin"

The CLI is not just a convenience for humans — it’s the contract. The ask_agent inter-agent messaging layer (~/agent-system/agents/shared/ask_agent.py) routes to agents by spawning this same CLI or calling an ask() function from the package. So a specialist agent’s CLI IS its API.

Some agents carry a knowledge base — a directory of research documents the agent retrieves from before answering. The professor agent (agents/professor/) holds course materials. The health-expert agent (agents/health_expert/) holds 8 streams of fitness/peptide research (~180KB cited). The merch-expert agent (agents/merch_expert/) holds POD business economics.

KB agents follow the professor-agent architecture: embed at ingest, retrieve top-K at query time, inject into the system prompt. The key property is scope isolation — a KB-backed agent can go deep on its domain without polluting the general context.

Agents do not hold state inside their own package directory (beyond the KB). Persistent state goes to ~/clawd/domains/<domain>/state/ — yaml files, report.md, task lists. The agent reads and writes those files; it does not own them. This is the files-as-state doctrine applied at the agent level: if the agent package is deleted and recreated, the state survives.

Before you build a new agent, check whether one already exists:

Terminal window
# Search the registry
bash ~/agent-system/scripts/list-agents.sh <keyword>
# Look at what's on disk
ls ~/agent-system/agents/

The reason this rule exists: in April 2026, a QA task spawned ad-hoc Playwright agents to test a fleet when agents/qa_agent/ was already on disk. It cost ~$3 of token spend and produced output in a format the canonical store couldn’t read. The rule is in ~/agent-system/CLAUDE.md as “Commandment XIV — Inventory Before Spawning.”

If you can’t find a match and the gap is real, document it in the agent registry before building.

The system has, as of mid-June 2026, approximately 31 agent packages on disk across ~/agent-system/agents/. That number comes from ls agents/ | wc -l (filesystem-audited), not from marketing copy. They range from fully operational specialists (researcher, professor, merch, health_expert, qa_agent) to experiments and stubs.

What keeps them coherent:

  1. One package = one scope. agents/researcher does research. agents/professor answers course questions. They do not call each other directly — they communicate through the ask_agent layer.
  2. Shared infrastructure lives in agents/shared/. The ask_agent.py router, the llm_client with OpenRouter→Anthropic fallback, the notify helper, and the crm utility are all in shared/. Agents import from there; they do not hand-roll their own HTTP calls.
  3. Tests live inside the package. agents/researcher/tests/ not tests/agents/researcher/. This lets you run pytest agents/researcher/ and know you’ve covered that agent’s contract without worrying about the full fleet.

To make this concrete, here’s what the health-expert agent (shipped 2026-06-08) actually is:

  • Package: ~/agent-system/agents/health_expert/
  • KB: 8 research streams (fitness programming, peptide pharmacology, nutrition, recovery, labs) totaling ~180KB of cited content, embedded at ingest with nomic-embed-text via Ollama
  • CLI: python3.12 -m agents.health_expert "<question>"
  • ask_agent target: "health-expert" (special-cased in ask_agent.py to call the in-process ask() function rather than the bridge)
  • State output: writes its assessments to ~/clawd/domains/health/state/ — not to its own directory
  • Cron: a weekly check-in every Sunday at 8:10am that generates a health status digest to JD’s Telegram

The first real output from this agent (the same day it shipped) was a 4-section master health plan: assessment of a 31-year-old’s compound stack, full 4-day upper/lower split, compound sequencing recommendation, and bloodwork panel. That output lived at ~/clawd/domains/health/state/JD-MASTER-PLAN-2026-06-08.md.

That’s what “anatomy of an agent” means in practice: a scoped package, a CLI, a KB, and state that lands in the right domain directory. Not a god-object; not a one-off script. A package.


Next: You know what an agent looks like on disk. Now learn how to spawn one from another agent — the foreground/background decision and when each is right.