서브에이전트의 최종 보고는 메인 대화의 컨텍스트에 그대로 쌓이므로, 지시문 끝에 「최종 보고 300자 이내, 자세한 근거는 파일에 쓰고 경로만」을 넣는 것이 가장 싼 절약법입니다. 사람이 매번 적으면 빠뜨리기 쉬우니 Claude Code 의 PreToolUse 훅에서 Agent 호출의 prompt 를 받아 그 문장을 덧붙인 입력(updatedInput)을 돌려주게 하면 됩니다. 다만 문장 하나로 보고가 바로 짧아지지는 않으니, 실제 보고 길이를 재면서 다뤄야 합니다.
이 글은 혼자 쓰는 개발 환경을 AI 에이전트 중심으로 바꾸면서(AX, AI 전환) 만든 장치를 하루에 하나씩 정리하는 연재의 세 번째 편입니다. 지난 편은 고친 파일을 Orca 탭으로 자동으로 여는 훅이었습니다.
서브에이전트 결과는 왜 메인 컨텍스트를 채울까?
저는 파일을 여러 개 읽어야 하는 조사나 검토를 서브에이전트에게 맡깁니다. 서브에이전트는 자기만의 컨텍스트에서 일하기 때문에, 그 안에서 읽은 파일 내용은 메인 대화로 넘어오지 않습니다. 그런데 일을 마치고 돌려주는 최종 보고만은 예외입니다. 보고 글자는 메인 대화에 한 글자도 줄지 않고 들어오고, 그 뒤로 메인이 도구를 부를 때마다 다시 읽힙니다.
어느 날 검토 에이전트의 보고 하나가 표와 근거 목록으로 화면을 몇 번이나 넘기는 것을 보고, 이것이 쌓이면 서브에이전트에게 맡긴 의미가 줄어든다는 것을 알았습니다. 일은 밖에서 시켰는데 결과는 안에서 길게 받는 셈이었습니다.
지시문에 「300자」를 적는 것만으로는 왜 부족했을까?
처음에는 규칙으로 해결하려고 했습니다. 서브에이전트에게 일을 맡길 때 지시문 끝에 「최종 보고 300자 이내 — 자세한 근거는 파일에 쓰고 경로만」을 늘 넣는다는 규칙을 지침에 적었습니다.
규칙을 둔 뒤 보고 길이를 재 보니(2026-10-19), 300자 이하인 보고는 37건 중 1건, 중앙값은 650자였습니다. 원인을 찾아보니 제가 쓰는 에이전트 정의 파일 몇 개가 「결과는 근거 표와 함께 자세히 보고하라」는 출력 형식을 따로 정해 두고 있었습니다. 지시문 끝의 한 줄과 정의 파일의 출력 형식이 부딪히면, 에이전트는 정의 쪽을 따르는 경우가 많았습니다.
훅은 지시문을 어떻게 고쳐 줄까?
그래서 두 가지를 바꿨습니다. 하나는 사람이 적는 것을 기대하지 않고 훅이 붙이는 것, 다른 하나는 문장 안에 「이 상한이 에이전트 정의의 출력 형식보다 우선한다」고 순서를 밝히는 것입니다.
PreToolUse 훅은 도구가 실행되기 직전에 입력을 받고, updatedInput 을 돌려주면 그 입력으로 바꿔서 실행합니다. Agent 호출일 때 prompt 끝에 문장을 붙이는 부분만 줄이면 이렇습니다.
CAP = "(이 상한은 에이전트 정의의 출력 형식보다 우선한다 — 최종 보고 300자 이내, 자세한 근거는 파일에 쓰고 경로만)"
def report_cap_input(tool_name, tool_input):
if tool_name not in ("Agent", "Task") or tool_input.get("subagent_type") == "fork":
return None # 위임이 아니거나 fork 면 건드리지 않는다
prompt = tool_input.get("prompt")
if not isinstance(prompt, str) or CAP in prompt:
return None # 이미 붙어 있으면 그대로(멱등)
return {**tool_input, "prompt": prompt.rstrip("\n") + "\n" + CAP}
fork 는 지금 대화를 그대로 이어받는 갈래라 따로 지시문 규약이 없으므로 뺐습니다. 이미 문장이 있으면 다시 붙이지 않아서, 같은 호출이 여러 번 훅을 지나도 문장이 겹치지 않습니다. 실제 훅은 처리 중 예외가 나면 None 을 돌려줘 원래 입력 그대로 실행되게 했습니다. 지시문을 고치다 실패해 위임 자체가 막히는 것보다는 문장이 빠진 채 가는 편이 낫기 때문입니다.
훅의 출력은 아래 모양입니다. 모델에게 주는 안내(additionalContext)와 바뀐 입력을 함께 냅니다.
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "결과를 받으면 받은 요지를 한 줄로 출력하라",
"permissionDecision": "allow",
"updatedInput": { "subagent_type": "general-purpose", "prompt": "조사해\n(이 상한은 … 경로만)" }
}
}
이 기능을 넣은 날 자체 시험 7개를 같이 추가했습니다. 문장이 없는 지시문 끝에 붙는지, 다른 입력 값이 그대로인지, 이미 있으면 바꾸지 않는지, 메시지 보내기와 fork 는 건드리지 않는지를 봅니다.
숫자는 얼마나 달라졌을까?
솔직하게 말하면 아직 목표와 멉니다. 2026-10-21 에 지난 7일을 다시 재 보니, 지시문에 300자 문구가 들어간 위임은 198건 중 179건(90.4%)으로 사람이 적는 단계는 거의 채워졌습니다. 그런데 실제로 300자 이하로 돌아온 보고는 143건 중 4건(2.8%)이고, 중앙값은 574자였습니다.
처음 잰 값(37건, 중앙 650자)과 이번 값은 잰 기간과 건수가 달라서 그대로 견줄 수는 없습니다. 중앙값이 내려간 방향만 확인한 정도입니다. 그래도 이 숫자를 매일 보기 때문에 「규칙을 넣었으니 해결됐다」고 착각하지 않게 됐습니다. 문장은 바닥을 받쳐 줄 뿐이고, 에이전트 정의의 출력 형식 자체를 줄이는 일이 다음 단계라는 것도 숫자가 알려 줬습니다.
지금 하루는 어떻게 달라졌나?
위임할 때 지시문 끝을 신경 쓰지 않습니다. 어떤 에이전트에게 맡기든 마지막 줄은 훅이 맞춰 줍니다. 보고가 짧게 오면 메인 대화에서는 결론만 읽고, 근거가 필요할 때만 보고에 적힌 파일 경로를 엽니다. 긴 보고가 오면 그날 지표에 그대로 찍히니, 어느 에이전트 정의가 여전히 길게 쓰게 만드는지 찾는 단서가 됩니다.
자주 묻는 질문
서브에이전트를 쓰면 메인 컨텍스트가 줄어드나요?
서브에이전트가 일하며 읽은 파일과 도구 결과는 메인으로 넘어오지 않습니다. 하지만 최종 보고는 그대로 들어오므로, 보고가 길면 아낀 만큼을 다시 씁니다. 보고 길이를 따로 정해 두는 것이 좋습니다.
permissionDecision 을 allow 로 내도 괜찮을까요?
updatedInput 을 쓰려면 함께 내야 하는데, allow 는 그 호출의 권한 확인을 건너뛰게 합니다. 저는 원래 확인창을 쓰지 않는 모드라 새로 풀리는 권한이 없었습니다. 확인창을 쓰는 환경이라면 이 점을 먼저 따져 보세요.
300자는 너무 짧지 않나요?
결론과 파일 경로를 담기에는 충분했습니다. 근거 표나 긴 목록은 파일에 쓰고, 메인은 필요할 때만 그 파일을 엽니다. 다만 이 숫자는 제 환경에서 정한 값이니 쓰임에 맞게 조정하면 됩니다.