Skip to content

Delegate a noisy recategorisation to an isolated subagent context

The recategorisation is exactly the kind of task that should never run in your main thread. It’s high-volume - thousands of rows, the same classification judgement applied over and over, pages of output you’ll skim once and never reference again - and self-contained: you don’t need the journey through every row, only the destination, the set of recategorised transactions and a summary of what changed. That shape, verbose work whose output you’ll never look at again, is the textbook case for delegating to a subagent.

A subagent runs as a separate session with its own context window. It doesn’t inherit your full conversation transcript or the files you’ve already opened - it gets a scoped delegation message describing the task, and works from there. That separation is the whole value, and it’s worth seeing the cost you avoid.

Run the recategorisation inline and your window fills with the raw material:

in your main thread (inline) in your main thread (delegated)
───────────────────────────── ───────────────────────────────
3,000 rows read + reasoned over "recategorise history against the
the taxonomy reloaded per batch corrected taxonomy"
every reclassification logged a summary: 412 rows changed
the review you came here to do… the review you came here to do…
↑ buried under row dumps ↑ still right there, in reach

Same answer, wildly different footprint. The work you actually came to do - reviewing the changes, signing off - stays the most recent, most prominent thing in your context, instead of being pushed three thousand rows into the past where the agent half-forgets it. The parent pays only for the aggregated summary, never the full transcript of the worker. That’s the cleanest tie to the thesis this whole course is built on: you close the gap - get the categorisation done against your real history - without bloating the window you’re reasoning in.

A subagent is only as good as the brief, because it starts without your context. So the delegation message has to carry everything the worker needs and nothing it doesn’t. For the recategorisation that means: the corrected category list (which lives in your AGENTS.md from the rules chapter - children inherit the in-scope AGENTS.md, so the taxonomy travels with them), the rule that money is integer cents, and a sharp definition of done.

> Delegate this to a subagent. Recategorise every transaction in the
imported history against the category list in AGENTS.md. For each row
that changes category, record the old and new category and the rule that
fired. Do not touch amounts - they're integer cents and stay untouched.
Return a summary table: count per category before and after, plus any
rows you couldn't classify confidently.

Notice what the brief asks back for: a summary, not the rows. “Return a summary table,” not “show me every reclassification.” A subagent that hands back three paragraphs protects your context; one that hands back three thousand rows has just relocated the flood into your thread instead of keeping it out. The terseness of the return is something you design, not something you hope for.

A subagent gets its own context window, but it does not start from a blank trust posture: by default it inherits the sandbox and approval settings live in your main thread at the moment you spawn it. A custom agent definition can pin its own - marking a summariser read-only, say - and any key it leaves out falls back to the parent’s; runtime overrides you set in your session are reapplied on top either way. The two-axis model from the approvals & sandbox chapter still governs the worker, it just usually governs it through the parent. The recategoriser is reading your transaction history and writing classification changes back; it has no business hitting the network or touching anything outside the data directory. So set that posture in your own session before you hand the task over - scoped to the workspace, network off, which is the workspace-write default - and the worker runs inside it. Different trust levels for different workers is still a security primitive worth using where a worker definition supports it; just don’t assume isolation you didn’t configure. The corollary to remember: loosening your own session to unblock yourself loosens every worker you spawn afterwards, so tighten first, then delegate.

Codex exposes a concurrency cap through agents.max_concurrent_threads_per_session (legacy alias agents.max_threads), while the current public config reference does not document a general maximum-depth key. Leave the concurrency setting unset to use Codex’s default, or set it explicitly after checking the official configuration reference. Do not build a workflow around an undocumented depth knob.

When to keep it in the main thread instead

Section titled “When to keep it in the main thread instead”

Delegation isn’t free. Keep the work in your main conversation when it needs frequent back-and-forth, when several phases share real context - planning into implementation into testing - or when it’s a quick, targeted change where spinning up a fresh worker that has to re-gather context just adds latency. For a tiny clarifying detour (“does this bank export use DD/MM or MM/DD?”), a lightweight in-session side conversation is cheaper than a full subagent spawn; isolation is a cost you opt into, not a default.

The test is the same one as delegating to a person: would I hand this off, get back a paragraph, and be happy? The recategorisation, yes - you want the result and the summary, not the reading. A delicate money refactor you’ll be steering line by line, no - the context the worker throws away is exactly the context you need.

One subagent could grind through the whole history in sequence. But notice the history splits cleanly - by account, by year, by import batch - into slices that don’t depend on each other. When a problem decomposes like that, one worker working serially is leaving speed on the table. Next we fan the work out.