엔지니어링 노트메모리와 검색

딥 리서치 조사원은 원문 대신 보고서를 넘긴다, 조사 범위와 빈칸까지

"제품 세 개의 지난 분기 장애 원인을 정리하고, 원인마다 업계가 어떻게 대응했는지 비교해 달라"는 질문은 한 번 검색해서 끝나지 않습니다. 사내 DB 세 곳과 문서, 웹을 따로 뒤져야 합니다. 에이전트 하나가 이 갈래들을 차례로 조사하면 갈래마다 쿼리 결과와 웹 페이지 발췌가 한 대화에 쌓입니다. 네 번째 갈래를 조사할 무렵이면 모델 입력의 대부분을 이미 끝난 갈래의 원문이 차지합니다. 하위 작업에서 쌓인 정보가 다음 작업에 필요 없는데도 컨텍스트에 남는 이 현상을 컨텍스트 오염이라고 부릅니다.

딥 리서치는 이 일을 둘로 나눕니다. 총괄은 계획을 세우고 갈래를 나눠 맡긴 뒤 최종 보고서를 씁니다. 조사원은 갈래 하나를 자기 컨텍스트에서 조사하고, 원문 대신 짧은 보고서만 총괄에게 돌려줍니다. 그런데 원문을 버리면 원문이 알려 주던 것도 사라집니다. 그 결과가 전체를 본 것인지 일부만 본 것인지, 무엇을 찾지 못했는지 총괄은 알 수 없게 됩니다. 이 글은 그 정보를 보고서가 어떻게 대신 싣는지, 그리고 총괄이 다시 혼자 조사하지 않도록 무엇을 막는지 설명합니다.

원문을 줄이는 방법마다 잃는 것이 다르다

조사원에게 일을 나눠도 결과를 어떻게 돌려받느냐에 따라 문제가 그대로 남습니다. 흔히 쓰는 방법은 세 가지입니다.

방법 얻는 것 잃는 것
한 에이전트가 차례로 조사 앞 갈래의 원문을 뒤 갈래가 그대로 본다 갈래가 늘수록 끝난 갈래의 원문이 입력을 채우고, 뒤 갈래는 앞 갈래가 끝나야 출발한다
조사원의 도구 결과를 총괄에게 모두 전달 총괄이 원문으로 판단한다 총괄의 컨텍스트가 혼자 조사할 때와 같아진다
조사원이 자유 형식으로 요약 총괄의 컨텍스트가 가볍다 요약마다 모양이 달라 비교하기 어렵고, 요약이 전체인지 표본인지 적혀 있지 않다

세 번째 방법이 가장 가볍지만 빠진 정보가 큽니다. 조사원이 장애 티켓 가운데 최근 50건만 조회하고 "주요 원인은 배포 실수"라고 썼다면, 그 문장은 전체 티켓을 다 본 결론과 겉모습이 같습니다. 총괄은 이 차이를 알 길이 없고 표본에서 나온 결론을 보고서에 사실로 옮깁니다.

그래서 보고서의 형식을 고정했습니다. 조사원은 원문을 넘기지 않고, 원문이 알려 주던 출처와 조사 범위와 빈칸을 정해진 절에 적어 넘깁니다.

조사원은 정해진 절로 보고하고, 조사 범위는 비워 둘 수 없다

조사원은 총괄이 쓴 과제 설명만 보고 일합니다. 대화도, 사용자도, 다른 조사원의 작업도 보지 못합니다. 조사를 마치면 마지막 메시지로 보고서를 쓰고, 이 보고서가 도구 결과 하나로 총괄의 입력에 실립니다(「에이전트 루프는 하나만 두고, 기능별 동작은 훅으로 끼운다」). 보고서는 대개 한 쪽에 훨씬 못 미치는 길이이고, 다음 절로 이루어집니다.

절 적는 것
발견 사실·숫자·날짜를 한 줄에 하나씩, 중요한 것부터. 줄마다 출처 주소와 확신도(high·medium·low)를 붙인다
조사 범위 무엇을 봤는지 — 어느 출처에서 어떤 기준으로 몇 건을 골랐는지, 그 선택에서 빠진 것과 그 크기
충돌 출처끼리 다른 말을 하는 곳과 어느 쪽을 더 믿는지, 그 이유
빈칸 과제가 물었지만 확인하지 못한 것과 그 이유(찾지 못함, 권한 없음, 출처를 열 수 없음, 예산 소진)
실마리 과제 범위 밖에서 본, 사용자 목적에 중요할 수 있는 단서. 위치만 적는다
출처 메모 DB와 테이블, 문서 모음, 커넥터처럼 다음 조사가 바로 찾아갈 위치

다른 절은 비어 있으면 빼도 되지만 조사 범위는 언제나 채웁니다. 이 절이 없으면 총괄은 완전한 답과 표본을 구별하지 못합니다. 앞의 장애 티켓 예라면 조사 범위에 "최근 티켓 50건만 조회, 분기 전체 건수는 확인하지 않음"이 적히고, 총괄은 이 줄을 보고 보강 조사를 보낼지 정합니다.

발견은 업무 용어로 씁니다. 테이블·컬럼 이름이나 쿼리는 출처 메모에만, 그것도 후속 조사에 필요할 때만 적습니다. 보고서의 독자가 원문을 보지 못한 총괄과 뒤 단계 조사원이기 때문입니다.

형식이 고정되어 있으니 서버는 보고서를 모델 호출 없이 규칙으로 읽습니다. 진행 화면은 발견 절의 첫 줄을 조사원별 한 줄 요약으로 보여 줍니다.

조사원 보고서의 절이 쓰이는 곳: 총괄, 뒤 단계 조사원, 보고서 전 검토, 진행 화면
그림 1. 조사원 보고서의 절이 쓰이는 곳: 총괄, 뒤 단계 조사원, 보고서 전 검토, 진행 화면

뒤 단계 조사원은 앞 보고서의 네 절에서 시작한다

갈래끼리 기대는 경우가 많습니다. 먼저 제품별 장애 목록을 뽑아야 장애마다 패치 이력을 찾을 수 있습니다. 그래서 계획의 항목마다 단계와 선행 항목을 반드시 적게 했습니다. 둘 중 하나라도 빠지면 계획 도구가 그 계획을 거절합니다. 선행 항목의 조사원이 끝나기 전에는 의존 항목의 조사원을 띄울 수 없습니다.

같은 단계에서 지금 띄울 수 있는 항목은 한 번의 호출에 모두 실어야 합니다. 이 규칙이 없으면 모델은 라운드마다 한 명씩 띄웁니다. 실측한 한 모델은 1단계 항목 넷을 그렇게 띄워, 마지막 조사원이 첫 조사원보다 13.6초 늦게 출발했습니다.

뒤 단계 조사원은 앞 조사원의 작업을 보지 못하므로, 시스템이 두 가지를 과제 설명 뒤에 붙입니다. 하나는 전체 계획과 그 안에서 자기 항목의 위치입니다. 다른 하나는 선행 항목 보고서의 발견, 조사 범위, 출처 메모, 빈칸 네 절입니다. 조사원은 발견에서 이미 확인된 것은 건너뛰고, 출처 메모에 적힌 DB와 테이블로 바로 가고, 조사 범위로 앞 조사가 전체를 봤는지 확인하고, 빈칸으로 아직 모르는 것을 봅니다. 충돌과 실마리는 넘기지 않습니다. 어느 쪽을 믿을지, 어느 실마리를 따라갈지는 총괄이 판단할 일이기 때문입니다.

붙이는 양에는 상한이 있습니다. 선행 항목 하나에 6,000자, 전체 12,000자입니다. 실측에서 붙은 양은 1,054자와 1,382자였으니 보통은 닿지 않고, 표를 통째로 붙인 보고서 같은 예외만 막습니다. 상한에 걸리면 줄 단위로 뒤에서부터 자르므로, 네 절의 순서가 곧 남길 순서입니다. 잘린 자리에는 앞 보고서 전문을 읽는 도구를 가리키는 표시가 남습니다. 그 도구로 읽을 수 있는 것은 자기 항목의 선행 항목 보고서뿐입니다.

총괄이 직접 하는 조사는 횟수로 막는다

보고서만 받는 구조는 총괄이 혼자 조사하기 시작하면 무너집니다. 딥 리서치를 켰는데 총괄이 데이터·웹 도구를 직접 불러 원문을 받으면, 처음에 피하려던 그 컨텍스트가 그대로 생깁니다. 실운영 환경에서 자체 호스팅 모델 하나는 계획도 조사원도 없이 데이터·웹 도구를 13~24번 직접 부른 뒤 곧바로 보고서를 썼습니다. 프롬프트에 금지를 적어 두었는데도 그랬습니다.

그래서 총괄의 도구 호출을 실행하기 전에 확인합니다. 계획이 확정되기 전에는 어느 DB나 문서 모음에 주제가 있는지 보는 범위 파악 호출(테이블 검색, 문서 검색)만 기본 4번까지 받습니다. 쿼리 실행, 웹 검색, 커넥터 호출, 조사원 띄우기, 최종 답변은 거절하고 계획을 내라는 사유를 돌려줍니다. 계획은 사용자가 계획 카드에서 조사 시작을 눌러야 확정됩니다.

모든 항목에 조사원이 붙은 뒤에도 총괄의 직접 조사는 기본 3번까지입니다. 시험 환경에서 조사원 셋이 예산을 다 쓰고 끝나자, 총괄이 읽기 전용 SQL을 직접 열 번 불러 빈 곳을 메운 일이 있었습니다. 상한을 넘는 호출은 "빈칸은 보강 조사원에게 맡기라"는 사유로 거절합니다. 두 횟수는 설정 파일의 agentLoop.researchLeadScopingCalls·agentLoop.researchLeadOpenPhaseCalls 로 바꿀 수 있습니다.

거절이 이어지면 다음 라운드에 계획 도구나 조사원 띄우기를 쓰도록 지정합니다. 그래도 모델이 따르지 않으면 그 턴의 제한을 풉니다. 답을 막아 턴이 끝나지 못하는 것이 계획 없는 답보다 나쁘기 때문입니다.

보고서를 쓰기 전에 빈칸을 보고, 핵심 주장을 다른 출처로 확인한다

총괄이 받는 것은 보고서뿐이므로, 보고서에 틀린 발견이 있으면 원문으로 거를 수 없습니다. 그래서 계획 항목의 조사원이 모두 끝나면 서버가 보고서를 쓰기 전에 두 가지를 지시합니다.

첫째는 후속 검토입니다. 서버는 끝난 조사원마다 조사 범위, 빈칸, 실마리 절을 모아(조사원 하나에 1,500자까지) 총괄에게 보여 주고, 보강 조사원을 보낼지 판단하게 합니다. 실패하거나 멈춘 조사원은 그 몫이 비었다는 한 줄로 나옵니다. 검토는 조사원을 더 띄울 시간이 남았을 때 새 보고서가 들어올 때마다 서고, 한 턴에 기본 2번까지입니다.

둘째는 검증입니다. 총괄은 보고서가 기댈 핵심 주장을 골라 검증 조사원에게 넘깁니다. 검증 조사원은 주장을 확인하지 않고 반박하려 합니다. 주장마다 그 주장이 나온 출처가 아닌 다른 출처를 찾아, 지지·반박·부분 오류·범위 밖·대조 못 함 가운데 하나로 판정합니다. 같은 출처를 다시 읽어 같은 말이 나와도 대조로 치지 않습니다. 이 규칙이 없으면 검증 조사원은 주장이 나온 각주를 다시 읽고 서지 정보의 오기까지 "확인됨"으로 통과시킵니다. 검증 지시에는 조사원 보고서가 인용했지만 이 턴에 아무도 본문을 열지 않은 링크도 실립니다. 검색 결과에만 보인 주소는 열어 보면 없는 페이지일 수 있고, 실제로 그런 페이지가 보고서 인용으로 실린 적이 있습니다.

검증은 턴당 한 번이고, 조사원이 쓸 시간이 5분(agentLoop.researchVerificationMinSeconds, 기본 300초) 넘게 남았을 때만 지시합니다. 몇 초만 남은 검증 조사원은 대부분의 주장을 "대조 못 함"으로 돌려주기 때문입니다.

지시를 보고서 전에 두는 데는 이유가 있습니다. 다 쓴 보고서를 거절해 돌려보내면 규칙을 걸 자리는 분명하지만, 시험 환경의 Claude Sonnet 5.5는 보고서를 두세 번 다시 썼습니다. 쓰기 전에 검토와 검증을 끝내게 하면 보고서는 한 번에 나옵니다.

설계에서 고른 것

총괄은 보고서만 봅니다. 그 덕에 조사원이 몇 명이든 총괄의 입력에는 갈래마다 한 쪽이 안 되는 보고서만 쌓입니다. 대가는 보고서가 놓친 것을 총괄도 모른다는 점입니다. 이 대가를 줄이려고 조사 범위를 필수 절로 두고, 보고서 전 검토와 검증을 서버가 지시하게 했습니다. 원문을 함께 넘기는 방법은 총괄이 더 정확히 판단하게 하지만, 갈래를 나눈 이유를 지웁니다.

보고서 형식은 규칙으로 읽습니다. 절 제목에 수식어나 개수가 붙는 정도는 받아들이지만, 전혀 다른 낱말로 제목을 바꾼 보고서는 진행 화면에 요약이 뜨지 않습니다. 형식이 어긋난 보고서를 모델로 다시 정리하면 호출이 늘고 매번 결과가 달라지므로, 요약을 비워 두는 쪽을 골랐습니다.

총괄이 직접 하는 조사를 횟수로 막았으므로, 총괄이 직접 하면 금방 끝날 작은 확인도 조사원을 띄워 맡겨야 합니다. 그만큼 모델 호출과 시간이 늘고, 계획 승인과 검증 단계도 더해집니다. 딥 리서치를 사용자가 켤 때만 도는 기능으로 둔 이유입니다. 갈래가 여럿이고 갈래마다 원문이 길게 쌓이는 질문이라면 딥 리서치를 켜고, 한 갈래로 끝나는 질문이라면 일반 질문이 시간과 사용량을 아낍니다.

어떤 문제를 해결하나요?

메모리와 검색의 다른 글