에이전트 도구 응답 253KB, 그중 70%가 판단에 안 쓰였습니다
개인 비서 에이전트가 매일 아침 「오늘 뭐 하지」를 정리해 알려주는 브리핑을 돌립니다. 그 브리핑은 그래프 기반 PM 도구의 종합 현황 도구를 한 번 호출하는 것으로 시작했습니다. 응답 크기가 253KB, 토큰으로 약 6만이었습니다.
매일 아침 컨텍스트의 맨 앞자리에 6만 토큰이 깔린 채로 하루 판단이 시작된 셈입니다. 그런데도 브리핑 품질이 특별히 좋지는 않았습니다. 많이 주면 좋다는 전제를 그때 처음 실측해봤습니다.
253KB 중 115KB는 언제 열어도 비어 있었습니다
응답을 필드 단위로 갈라보니 115KB가 프로젝트별 작업목록이었습니다. 전체의 70%입니다. 프로젝트 상세 조회 아홉 개를 다이어트 없이 그대로 이어붙인 형태였습니다.
문제는 그 115KB가 상시 0건이나 다름없었다는 점입니다. 제 워크플로가 일을 먼저 하고 나중에 등록하는 사후등록 방식이라, 진행중 상태로 남아 있는 작업이 거의 없습니다. 구조상 판단에 기여할 수 없는 데이터를 매일 아침 실어 나른 것입니다.
실제 「오늘 할 일」의 원천은 두 갈래뿐이었습니다. 아직 분류하지 않은 임시함과 마감이 임박한 항목입니다. 나머지는 화면에서는 쓰일지 몰라도 브리핑에서는 한 글자도 쓰이지 않았습니다.
그 필드들이 거기 있던 이유는 필요해서가 아니었습니다. 그 도구가 원래 웹 대시보드 화면용 API 였고, 에이전트 도구를 만들 때 그것을 그대로 재활용했기 때문입니다. 화면은 스크롤이 있으니 많이 받아도 손해가 작지만, 에이전트는 받은 것을 전부 컨텍스트에 올립니다.

세 가지 선택지 중 새로 파는 쪽을 골랐습니다
선택지 | 내용 | 판단 |
|---|---|---|
A | 기존 종합 도구를 슬림화한다 | 화면 5곳이 물려 있어 필드를 빼면 화면이 깨진다 |
B | 에이전트 전용 도구를 새로 판다 | 채택 |
C | 프롬프트에서 필요한 부분만 쓰게 지시한다 | 컨텍스트에 올라온 시점에 토큰은 이미 태워졌다 |
A 안은 화면 다섯 곳이 이미 그 응답에 물려 있어 필드를 빼는 순간 화면이 깨집니다. 화면과 에이전트는 요구가 정반대입니다. 화면은 넓게 받아 사람이 눈으로 훑고, 에이전트는 좁고 판단 가능한 것만 받아야 합니다.
C 안은 성립하지 않습니다. 컨텍스트에 올라온 시점에 토큰은 이미 태워졌습니다. 「필요한 부분만 써라」는 지시는 비용을 한 푼도 줄이지 못합니다.
그래서 화면 API 는 손대지 않고 에이전트 전용 도구를 새로 팠습니다. 브리핑이 실제로 쓰는 세 덩어리만 조립했습니다. 어제 총평, 안 끝난 것, 오늘 할 것입니다. 종합 현황 도구는 도구 목록에서 제거해 총 개수는 그대로 유지했습니다.
예산을 3.2KB로 잡았는데 첫 구현이 12KB였습니다
설계 문서에는 응답 예산을 3.2KB 로 적었습니다. 첫 구현을 돌려 실물 응답을 재보니 12.0KB 였습니다. 네 배 가까이 빗나갔고, 원인은 추정 방식 자체에 있었습니다.
진행중 항목의 크기를 산정할 때 마침 0건이던 카테고리들만 보고 전체를 판단했습니다. 실제 쿼리는 보류 10건과 미답변 질문 7건까지 끌어옵니다. 표본이 0인 구간을 보고 예산을 잡으면 언제나 과소 추정이 나옵니다.
덩치의 정체는 사람이 자유 입력한 텍스트였습니다. 미답변 질문의 본문이 고객 문의 전문이라 건당 441자에서 957자까지 갔고, 7건만으로 5.6KB 를 차지했습니다. 정형 필드는 크기가 예측되지만 사람이 쓴 문장은 건당 편차가 몇 배입니다.
150자에서 자르고 말줄임 표시를 붙이는 것만으로 12.0KB 가 8.1KB 가 됐습니다. 실물 응답은 8,119바이트입니다. 스펙 문서의 예산 숫자는 3.2KB 에서 8KB 로 정정했습니다. 실측이 스펙과 다를 때 고쳐야 하는 쪽은 실측이 아닙니다.

어제 총평은 새로 만들지 않고 이미 있던 324바이트를 실어 날랐습니다
어제 총평 자리에는 이미 30일 연속 쌓이고 있던 하루 요약 필드가 있었습니다. 크기가 324바이트입니다. 무거운 어제 활동 전량 14.7KB 와 부가 맥락 2KB 는 떼어냈습니다.
연속성 표현도 「완료」에서 「안 끝난 것」으로 바꿨습니다. 어제 끝낸 13건은 오늘 판단에 영향이 없습니다. 작업 사이의 선행·후속 계보도 검토했지만 전체 그래프 엣지 1,781개 중 한 건도 잡히지 않아 넣지 않았습니다.
브리핑 시각과 데이터 생성 시각이 어긋나 있었습니다
다이어트를 하다가 별개의 구멍을 하나 발견했습니다. 하루 요약은 사람이 저장을 눌러야 남는데, 실제 저장 시각이 전부 06:00 이후였습니다. 07:50, 06:52, 07:31, 08:26 입니다.
06:00 에 도는 브리핑은 어제 요약을 구조적으로 볼 수 없었습니다. 데이터가 부실해서가 아니라 아직 만들어지지 않은 시각에 읽고 있었습니다. 05:30 배치를 넣어 요약 생성을 앞당겼고, 이미 있으면 건너뜁니다.
건너뛰는 이유는 중복 저장이 아까워서가 아니라 LLM 재호출을 막기 위해서입니다. 이 배치가 그 시스템의 첫 스케줄러이기도 합니다. 그전까지 정기 배치는 0개였습니다.
서버와 로컬이 동시에 뜰 때 배치가 두 번 도는 것은 분산 락으로 막았습니다. 이미 쓰던 RDB 를 락 저장소로 그대로 썼고, 락 시간 기준을 DB 시계로 두어 두 기계의 시각 차이를 무시하게 했습니다.
도구 설명에 안 주는 것을 계약으로 박았습니다
응답은 시간이 지나면 반드시 다시 부풉니다. 뭘 주는지만 적혀 있는 문서에서는 필드 추가가 언제나 정당해 보입니다. 그래서 도구 설명에 안 주는 것을 목록으로 명시했습니다.
완료 노트 본문
완료 목록
작업 전량
링크
안 주기로 한 것이 계약으로 박혀 있으면 필드를 더하려는 사람이 그 줄을 먼저 만납니다. 검증 항목에도 실물 응답의 금지 필드 유출 0건을 넣었습니다. 신규 테스트 14개를 포함해 백엔드 전량과 MCP 86개가 통과했습니다.
곁가지로 갈린 논점이 하나 더 있습니다. 응답을 Top3 로 추려줄 것인가입니다. 추려주지 않기로 했습니다.
도구 안쪽은 캘린더 같은 바깥 맥락을 모릅니다. 여기서 판단을 한 겹 더 얹으면 브리핑이 두 번 판단하게 되고, 두 판단이 어긋나면 자기모순이 나옵니다. 바깥 맥락을 가진 쪽이 판단하고 안쪽은 원자료를 줍니다.

이 수치를 그대로 가져다 쓰면 안 됩니다
작업목록이 상시 0건이었던 것은 제 사후등록 습관 때문입니다. 진행중 상태를 성실히 관리하는 팀이라면 그 115KB 가 판단의 핵심일 수 있습니다. 쓰이지 않는다는 판정은 워크플로에 의존합니다.
길이 컷은 정보 손실이기도 합니다. 150자로 자른 문의는 무엇을 물었는지는 알려주지만 어떻게 답해야 하는지는 알려주지 못합니다. 브리핑은 목록이 목적이라 괜찮았지만, 답변 초안까지 만드는 용도라면 이 컷이 그대로 품질 하한이 됩니다.
전량 제공 원칙도 규모에서 깨집니다. 항목이 수백 건이 되면 결국 어딘가에서 추려야 합니다. 지금은 원자료가 한 화면에 담기는 규모라 성립하는 결정입니다.
도구 응답을 줄이기 전에 점검할 것
그 도구가 하루에 몇 번 불리는지 먼저 셉니다. 자주 안 불리면 다이어트 이익도 작습니다.
응답을 필드 단위로 갈라 바이트를 잽니다. 설계 문서의 예산이 아니라 실물 응답이 기준입니다.
각 덩어리가 최근 한 달 판단에 실제로 쓰였는지 확인합니다. 0건인 구간만 보고 크기를 추정하지 않습니다.
사람이 자유 입력한 텍스트에는 길이 컷을 기본값으로 겁니다.
화면용 API 를 에이전트 도구로 재활용하고 있는지 봅니다. 요구가 반대라면 새로 파는 편이 쌉니다.
컨텍스트 예산은 재는 순간에만 존재합니다. 설계 문서에 3.2KB 라고 적혀 있어도 실물 응답이 12KB 면 그게 그 시스템의 사실입니다. 이 작업에서 제 추정이 틀린 대목은 전부 재보고 나서야 드러났습니다.
응답 크기를 「많이 주면 좋다」로 두면 뺄 근거가 생기지 않습니다. 판단에 쓰인 비율로 재기 시작하면 뺄 것이 눈에 보입니다. 253KB 중 70%가 그 자리에 있던 이유는 필요해서가 아니라 아무도 재보지 않았기 때문입니다.