Skip to content

Course · Claude Code · Subagents

Keep noisy work out of your main thread with subagents

Every file the agent reads lands in the same context window you work from. The context window is the finite space that holds your conversation, your instructions, and every tool result; once a file is in it, it stays until the session compacts (summarizes old context in place) or ends. Most investigations read far more than they conclude, and that reading is scaffolding: opened once, quoted once, never needed again. This chapter is about where that reading should happen. Not how hard the agent thinks, which is the model and effort question, but which window absorbs the noise.

The example is a small payments service, and every page in the chapter restates the facts it needs, so you can start anywhere.

The service is Express plus TypeScript. POST /payments and GET /balance/:accountId are handled in src/index.ts. Money is recorded by a Ledger class in src/payments/ledger.ts, which exposes append, balance, and history. Two test files, tests/payments.test.ts and tests/ledger.test.ts, hold six tests, and all six pass. Neither file posts a payment and then reads a balance, so nothing checks that the route and the ledger agree.

Start the service in one terminal with npm run dev, then pay an account and check its balance from another:

Terminal window
curl -s -X POST localhost:3000/payments \
-H 'content-type: application/json' \
-H 'idempotency-key: demo-1' \
-d '{"accountId":"acct_1","amount":1999,"currency":"USD"}'
curl -s localhost:3000/balance/acct_1

The POST replies 201 with a completed payment: a fresh id, the account, the amount with its fee. The GET replies {"accountId":"acct_1","balance":0}. Pay again with a new idempotency key and the balance stays 0, for every account, after every payment.

Nothing crashed and the suite is green, yet the service reports success while every account sums to zero. That is a question worth answering before anyone trusts it, and all the evidence is inspectable: the route handler, the Ledger class, and two test files that never connect them. If your working copy carries changes from earlier chapters, read your own code as it stands; the payments example source prepared for this course is the reference this walkthrough quotes, and the getting-started chapter describes where that source comes from.

Answering the question inline means reading src/index.ts end to end, then src/payments/ledger.ts, then both test files, plus the greps that find every caller of append, balance, and history. High volume in, one paragraph out. In your main window, all of that volume stays.

A subagent is the move for exactly this shape. It is a separate Claude instance with its own context window: you hand it a task, it reads and greps and accumulates in its memory, and when it finishes it returns a single summary to your main conversation. The reads never enter your thread. You keep the conclusion; the subagent keeps the noise, and discards it.

Subagents are not agent teams. Teams are an experimental, higher-cost mode, disabled by default, in which independent Claude sessions share a task list and message one another directly. Use a subagent when only the result matters; consider a team only when workers must genuinely coordinate, after reading the current agent teams documentation.

The chapter carries the zero-balance question through four moves. Each page stands on its own:

Three terms recur, and they mean different things. A subagent is any worker with its own context window that returns a summary. A background subagent is one that runs while you keep typing; Ctrl+B sends a running task there and /tasks lists them. A custom agent is a subagent whose tools, model, and instructions are saved in a file so it can be invoked by name.

By the end, “should this work think in my thread or somewhere else?” is a question you ask before every noisy task. Start by delegating the investigation.