A subagent’s final report piles up in the main conversation’s context as is, so the cheapest way to save is to add “final report within 300 characters; write the detailed evidence to a file and give only the path” at the end of the instruction. If a person has to type it every time it is easy to forget, so a Claude Code PreToolUse hook can take the prompt of an Agent call and return an input (updatedInput) with that sentence appended. But one sentence does not shorten reports right away, so you have to handle it while measuring the actual report length.
This post is the third in a series that covers, one per day, the devices I built while turning my solo development environment around AI agents (AX, AI transformation). The last one was a hook that opens edited files as Orca tabs automatically.
Why do subagent results fill the main context?
I hand research and reviews that require reading many files to subagents. A subagent works in its own context, so the file contents it reads there do not come over to the main conversation. The final report it returns when it finishes is the one exception. The characters of the report come into the main conversation without losing a single one, and after that they are read again every time the main agent calls a tool.
One day I saw a single review agent’s report, with its tables and evidence lists, make me scroll the screen several times, and I realized that when these pile up, the point of handing the work to a subagent shrinks. The work was ordered outside, but the result was received at length inside.
Why was writing “300 characters” in the instruction not enough?
At first I tried to solve it with a rule. I wrote into my guidelines a rule that, whenever I hand work to a subagent, I always put “final report within 300 characters — write the detailed evidence to a file and give only the path” at the end of the instruction.
After putting the rule in place, I measured the report lengths (2026-10-19): only 1 of 37 reports was 300 characters or fewer, and the median was 650 characters. Looking for the cause, I found that several of the agent definition files I use separately specified an output format that said “report results in detail with an evidence table.” When the one line at the end of the instruction and the output format in the definition file clash, the agent often followed the definition.
How does a hook fix the instruction?
So I changed two things. One is to have the hook attach it instead of expecting a person to type it; the other is to state the order inside the sentence: “this limit takes priority over the output format in the agent definition.”
A PreToolUse hook receives the input just before the tool runs, and if it returns updatedInput, the tool runs with that changed input. Shortened to just the part that appends the sentence to the end of prompt on an Agent call, it looks like this.
CAP = "(This limit takes priority over the output format in the agent definition — final report within 300 characters, write detailed evidence to a file and give only the path)"
def report_cap_input(tool_name, tool_input):
if tool_name not in ("Agent", "Task") or tool_input.get("subagent_type") == "fork":
return None # leave it alone if it is not a delegation, or is a fork
prompt = tool_input.get("prompt")
if not isinstance(prompt, str) or CAP in prompt:
return None # already attached: leave as is (idempotent)
return {**tool_input, "prompt": prompt.rstrip("\n") + "\n" + CAP}
I excluded fork because it is a branch that continues the current conversation as is and has no instruction convention of its own. If the sentence is already there, it is not attached again, so even if the same call passes through the hook several times, the sentences do not pile up. In the real hook, if an exception occurs during processing, it returns None so the original input runs as is. That is better than the delegation itself being blocked because fixing the instruction failed, even if it goes without the sentence.
The hook’s output has the shape below. It outputs guidance for the model (additionalContext) together with the changed input.
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "When you receive the result, print the gist of what you received in one line",
"permissionDecision": "allow",
"updatedInput": { "subagent_type": "general-purpose", "prompt": "Investigate\n(This limit ... path only)" }
}
}
On the day I added this feature, I also added 7 self-tests. They check whether the sentence is appended to the end of an instruction that lacks it, whether other input values stay as they are, whether it does not change anything if the sentence is already there, and whether it leaves message sending and fork alone.
How much did the numbers change?
To be honest, it is still far from the goal. When I measured the last 7 days again on 2026-10-21, delegations whose instruction contained the 300-character phrase were 179 of 198 (90.4%), so the step where a person has to type it was mostly filled. But the reports that actually came back at 300 characters or fewer were 4 of 143 (2.8%), and the median was 574 characters.
The first measurement (37 reports, median 650) and this one cover different periods and counts, so they cannot be compared directly. I only confirmed that the median moved down. Still, because I look at these numbers every day, I no longer fall into the illusion that “I added the rule, so it is solved.” The sentence only supports the floor, and the numbers also told me that the next step is to shorten the output format in the agent definitions themselves.
How has my day changed?
I no longer worry about the end of the instruction when delegating. Whichever agent I hand work to, the hook sets the last line. When a report comes back short, I read only the conclusion in the main conversation and open the file path written in the report only when I need the evidence. When a long report comes in, it is recorded in that day’s metrics as is, so it becomes a clue for finding which agent definition still makes it write at length.
Frequently asked questions
Does using a subagent reduce the main context?
The files and tool results a subagent reads while working do not come over to the main conversation. But the final report comes in as is, so if the report is long, you spend again as much as you saved. It is better to set the report length separately.
Is it okay to output permissionDecision as allow?
You have to output it together to use updatedInput, and allow skips the permission check for that call. My mode does not use confirmation prompts to begin with, so no permission was newly loosened. If you use an environment with confirmation prompts, consider this point first.
Isn’t 300 characters too short?
It was enough to hold a conclusion and a file path. Evidence tables and long lists go into a file, and the main agent opens that file only when needed. Still, this number is a value I set in my environment, so adjust it to your use.