← Insights
Perspectives · May 20, 2026 · 10 min read

Build agents with agents: the loop that actually works

EssayEngineeringFrameworks

The first time you point Claude at a problem and say "build me an agent," it writes a prompt, picks a model, ships a 200-line file, and demos beautifully. The fifth time, you notice the demo only works on the example you used to write it. Building agents with agents is real: Claude can plan, write, and refactor agents quickly. The failure mode is real too: a megaprompt with no trace, no eval, no decomposition, and a fresh regression every time the model or task changes. Teams shipping working agents no longer treat this as a single generation. They treat it as a loop.

1. Start with the eval, not the prompt

Writing the prompt first is intuitive and wrong. The prompt is a hypothesis. Without a way to falsify it, you'll iterate forever and convince yourself you're done.

The fix is mechanical: before any system prompt exists, write down three rows of an eval set. Each row is (input, expected_observable) — never (input, full_expected_output), because outputs are paragraphs and you can't pattern-match a paragraph. Pick observables you can check with a regex, a JSON schema, an LLM-as-judge rubric, or a tool side effect.

Three rows is enough to start. One happy path, one edge case, one failure where the agent must refuse. If you can't write those three rows, you don't have a spec — you have a wish. Adding sections to the system prompt before evals exist is just decorating the wish.

2. Scope each agent like a function

The next mistake is treating the agent as a personality. Personalities are unboundable; functions are. A useful agent has a signature: one or two named inputs, one named output shape, one named success condition. Anything else — backstory, tone, emoji policy — is decoration.

When the scope is a function, the parent agent (Claude, in this loop) can reason about it. "Given these inputs and this success condition, what tools do I need? What's the smallest system prompt that gets there?" That conversation is short and concrete. The conversation about "make it helpful and friendly and also good at code" is infinite.

3. Let the parent agent scaffold the child

Once you have the eval and the function signature, hand both to Claude. Ask it to draft the system prompt, the tool list, the permission policy, and the first set of fixtures. Treat the output the way you'd treat code from a strong contractor: skeptical, but assume the structure is sound.

What you should not do is type the system prompt by hand. The parent agent will produce a better first draft in ninety seconds than you will in an afternoon, because it has read more agents than you have. Your edits start from a baseline, not from a blank page. Agent basics is where the loop's anatomy stops being a metaphor.

4. Tools are the real prompt

Read any production agent's system prompt and you'll find it's mostly tool descriptions. The prose at the top sets tone; the tools set capability. Every tool name, parameter name, and one-line description is part of the prompt the model actually plans against.

Two consequences. First, rename ruthlessly. A tool called query_db is ambiguous; search_orders_by_email is not. The model's plans get cleaner as your tool surface gets clearer, and the cleanup is cheaper than re-prompting. Second, prefer one good tool over three prompt instructions. "Always validate the email before sending" becomes a send_email tool that validates internally and refuses with a typed error. The prompt shrinks; the behavior is enforced in code.

The right size for a tool is "an action a reviewer can audit in one log line." If you can't write a one-line log entry that fully describes the side effect, the tool is too big. MCP servers formalizes this — your tool surface becomes the contract between the agent and the rest of the system.

5. Decompose with subagents, not megaprompts

The temptation is to keep adding sections to a single system prompt until the agent can "do it all." This is the same shape as one-file React apps. It works at small scale and rots fast.

The alternative is subagents. The main agent stays small and orchestrates; it delegates to specialized children — a planner, a retriever, a reviewer, a writer — each with its own scoped function and eval set. The main agent's context window stays cheap and predictable; the children burn their own context on their slice of the problem and report a compact result back.

Two practical wins: parallelism (independent subagents run concurrently, latency drops) and context hygiene (the main agent never has to read the 80kb of retrieved docs the retriever sifted through). The cost is one more layer to think about. Worth it past the second tool. Multi-agent design is the lesson that makes this concrete.

6. Hooks are the immune system

Subagents and tools give the agent capability. Hooks decide what it's allowed to do with that capability. A hook runs before or after a tool call — it can rewrite arguments, deny the call, log the trace, run a linter on the file the agent just wrote.

This is the boring layer. It is also where most production incidents would have been prevented. A pre-tool hook that refuses rm -rf on paths outside /tmp. A post-tool hook that runs tsc --noEmit after every file write and pipes failures back to the agent. A refusal hook that turns "the API key is XYZ" into a redaction before it ever reaches the log.

Hooks are deterministic. They run on every call. They are the part of the system you can write unit tests for, and they catch the failures that probabilistic checks would have missed at 2 a.m. The Claude Agent SDK exposes 22 hook events for exactly this reason; the right answer is usually "more hooks than felt necessary." Agent security walks the threat model.

7. Debug by replaying the trace, not by re-prompting

The single biggest difference between teams who ship agents and teams who keep tweaking them is what they do when something breaks.

The tweaking team re-runs the agent on the failing input, watches it fail differently, edits the prompt, repeats. Hours pass. The fix doesn't generalize.

The shipping team treats every agent run as a structured log — every message, every tool call, every observation. When something breaks, they open the trace, find the exact step that diverged, and ask the parent agent what would have to change in the prompt or tool to make that step correct. The fix is a diff against a specific decision, not a vibes-based rewrite. The eval set grows by one row — the failing input becomes a permanent regression test. The agent gets monotonically better.

A trace is just an array of typed events. Build the harness once, reuse it everywhere. Every fix lands the same way: open the trace → edit the prompt or tool or hook → re-run the eval set → commit when green.

Putting it together

The loop is short and the same every time:

  1. Eval — three rows minimum, before anything else.
  2. Scope — the agent is a function with a signature.
  3. Scaffold — the parent agent drafts the system prompt and tools; you review.
  4. Tools — they are the real prompt; rename and shrink.
  5. Decompose — subagents over megaprompts past tool #2.
  6. Hook — deterministic gates around every tool.
  7. Replay — debug the trace, not the symptom; every fix grows the eval set.

None of these steps requires more model capability than is already shipping in 2026. They require the discipline to treat agent development as engineering, not chat. Most teams skip the first step (evals) and the last step (replay), then wonder why the agent regresses every time the model is upgraded.

The durable asset is not any one agent. The model will be replaced. The prompt will be rewritten. The tools will be renamed. The asset is the loop: the eval set, the trace harness, the hook battery, and the subagent decomposition. That is what compounds. A year from now, that is the part most likely to still be working. Pick the loop first, and the agent gets built almost as a side effect.

Related paths