Chain of Recall이란? Stable ID로 AI 에이전트에 기억력을 부여하는 방법
Chain of Recall이란? Stable ID로 AI 에이전트에 기억력을 부여하는 방법 Chain of Recall은 컨텍스트 창(Context Window)에 모든 정보를 억지로 밀어 넣지 않고도 장기 실행(Long-running) AI 에이전트에 메모리를 부여하는 방식입니다. 모든 트리거(Trigger), 스레드(Thread), 워커(Worker)는 고유한 불변 ID를 부여받
Chain of Recall이란? Stable ID로 AI 에이전트에 기억력을 부여하는 방법
Chain of Recall은 컨텍스트 창(Context Window)에 모든 정보를 억지로 밀어 넣지 않고도 장기 실행(Long-running) AI 에이전트에 메모리를 부여하는 방식입니다. 모든 트리거(Trigger), 스레드(Thread), 워커(Worker)는 고유한 불변 ID를 부여받습니다. 컨텍스트에는 ID, 짧은 요약, 인접한 메시지만 유지하며, 에이전트는 ID 간의 연결 링크를 따라가며 몇 번의 홉(hop)만으로 이전 사실을 가져옵니다.
이 용어는 2026년 11월 1일에 게시된 DeepSeek Harness의 설계 에세이 “Exploring Super-agent Design”에서 비롯되었습니다. 본격적으로 살펴보기 전에 한 가지 유의할 점이 있습니다. 이 에세이에서 설명하는 내용은 정식 출시된 기능이 아니라 아키텍처라는 점입니다. 일부는 저자들이 “DeepSeek의 공식 제품이 아니다”라고 밝힌 프로토타입 플러그인 dsh-superagent-prototype에 구현되어 있습니다. 즉, 버튼 하나로 켤 수 있는 Chain of Recall 스위치 같은 것은 없으며, 직접 구현해야 하는 설계 패턴입니다.
장기 실행 에이전트에서 발생하는 컨텍스트 창의 한계
장기 실행 에이전트는 작업이 끊임없이 유입되기 때문에 필연적으로 컨텍스트 한계에 부딪힙니다. 채팅, GitHub, CI를 모니터링하는 슈퍼 에이전트는 하루에도 수백 건의 이벤트를 마주하며, 어제의 작업 내역이 담긴 창에 오늘의 작업까지 함께 담아낼 수는 없습니다.
이에 대처하는 일반적인 방식들에는 저마다의 대가가 따릅니다.
- 모든 내용 유지: 컨텍스트 창이 금방 차오르고 턴이 지날수록 비용이 급증합니다.
- 이전 턴 요약: 요약 과정에서 나중에 꼭 필요해질 정확한 오류 메시지나 PR 번호 같은 세부 정보가 누락됩니다.
- 유사도 기반 검색: 필요한 정보가 검색 쿼리와 유사하지 않은 형태라면 찾아내지 못합니다.
Anthropic의 AI 에이전트를 위한 컨텍스트 엔지니어링 가이드에서는 컨텍스트를 신중하게 큐레이션해야 하는 유한한 자원으로 정의합니다. Chain of Recall은 이러한 큐레이션을 수행하는 구체적인 방법 중 하나이며, 더 폭넓은 선택지는 AI 에이전트 메모리의 작동 원리 글에서 확인하실 수 있습니다.
인라인 vs 스필: 캐시로서의 컨텍스트
해당 에세이에서는 컨텍스트 창을 두 가지 동작을 수행하는 캐시처럼 다룹니다.
- 인라인(Inline): 에이전트가 지금 당장 필요로 할 가능성이 높은 정보(ID, 짧은 요약, 인접 메시지)를 컨텍스트 안에 유지합니다.
- 스필(Spill): 그 밖의 모든 정보는 잘라내어 외부로 넘기고, 에이전트가 나중에 찾아갈 수 있는 포인터만 남겨둡니다.
스필된 항목은 삭제되는 것이 아니며, 프롬프트에는 해당 항목을 가리키는 포인터만 남습니다.
라우터(Router)에 CI 실패 이벤트가 전달되었을 때의 데이터 구조 예시는 다음과 같습니다. 이는 설명을 돕기 위한 예시이며 실제 DeepSeek의 코드는 아닙니다.
{
"trigger_id": "trg_8f21",
"source": "github.check_run",
"thread_id": "thr_pr_412",
"summary": "CI failed on PR #412: 3 of 118 tests red in payments/",
"neighbours": ["trg_8f1c: review comment asking for retry logic"],
"spilled": {
"full_log": "GET /triggers/trg_8f21/payload (41 KB, truncated)"
}
}
한 줄짜리 요약만으로 충분하다면, 에이전트는 41KB에 달하는 전체 로그 비용을 치를 필요가 없습니다. 요약만으로 부족한 경우에만 ID를 통해 로그를 가져옵니다.
불변 ID와 참조 그래프
Chain of Recall이 효과적으로 작동하는 이유는 ID가 절대 바뀌지 않기 때문입니다. 해당 에세이의 설계에서는 다음 세 가지 유형의 객체가 ID를 가집니다.
| 객체 | 설명 | ID 예시 |
|---|---|---|
| Trigger | 단일 수신 이벤트: 채팅 메시지, 웹훅, CI 콜백 등 | trg_8f21 |
| Thread | 하나의 PR, 메신저 토픽, 이메일 스레드 등에서 연속적으로 일어나는 관련 이벤트들 | thr_pr_412 |
| Worker | 하나의 작업을 처리하는 독립된 단일 에이전트 세션 | wkr_77a0 |
트리거(Trigger)는 스레드(Thread)에 속하고, 스레드는 하나 이상의 워커(Worker)에 귀속되며, 워커의 보고서는 자신이 처리한 트리거를 참조합니다. 이러한 연결 고리들이 모여 참조 그래프를 형성하며, 이 참조 그래프가 곧 에이전트의 메모리가 됩니다.
정보의 회상(Recall)은 전체 히스토리를 불러오거나 유사한 텍스트를 검색하는 대신, 링크를 한 홉씩 차례로 따라가는 방식으로 이루어집니다. 전체 라우터 및 워커 설계에서 트리거, 스레드, 워커가 차지하는 위치에 대한 자세한 내용은 관련 가이드인 슈퍼 에이전트 구축 방법을 참조하세요.
멀티 홉 회상 과정 살펴보기
금요일에 한 팀원이 라우터에 다음과 같이 질문했다고 가정해 보겠습니다. “결제 클라이언트에 재시도 로직을 왜 추가했죠?” 원래의 논의는 화요일에 이루어졌고 이미 오래전에 스필 처리되었습니다. 이때 회상이 일어나는 단계는 다음과 같습니다.
-
1단계(Hop 1): 스레드 찾기. 라우터의 컨텍스트에는 여전히 한 줄짜리 인덱스 항목인
thr_pr_412: payments retry PR, merged Wed가 남아 있습니다. 이를 바탕으로GET /threads/thr_pr_412를 호출합니다. -
2단계(Hop 2): 워커 찾기. 해당 스레드 레코드에는
owner_workers: ["wkr_77a0"]이 명시되어 있습니다. 라우터는GET /workers/wkr_77a0을 호출하여 최종 보고서를 확인합니다. -
3단계(Hop 3): 원인 파악하기. 보고서에는 CI 실패 이벤트인
trg_8f21이 참조되어 있습니다. 라우터는 해당 트리거의 페이로드를 가져와 로그에 기록된 타임아웃 오류를 확인합니다. - 답변 생성. “화요일에 PR #412의 CI에서 3건의 결제 타임아웃이 발생했습니다. 이에 따라 워커 wkr_77a0이 백오프(backoff)를 포함한 재시도 로직을 추가했고, 해당 PR은 수요일에 병합되었습니다.”
작고 정확한 세 번의 API 호출만으로 해결되었습니다. 어떤 것도 임의로 추측하지 않았으며, 3일 동안 프롬프트에 불필요하게 머물러 있던 데이터도 없었습니다.
Chain of Recall vs 벡터 메모리 및 요약 방식 비교
Chain of Recall은 다른 메모리 기법을 완전히 대체하는 것이 아닙니다. 해결하고자 하는 질문의 성격이 다릅니다. 검색 증강 생성(RAG) 논문으로 널리 알려진 벡터 검색이 “이것과 유사한 것은 무엇인가?”를 묻는다면, Chain of Recall은 “이것과 연결된 것은 무엇인가?”를 묻습니다.
| Chain of Recall | 벡터 메모리 (RAG) | 롤링 요약 (Rolling summaries) | 메모리 MCP 서버 | |
|---|---|---|---|---|
| 회상 방식 | 불변 ID 링크를 추적 | 임베딩 기반 유사도 검색 | 압축된 히스토리 확인 | 서버가 제공하는 메모리 툴 호출 |
| 정확도 | ID를 통한 정확한 단일 레코드 조회 | 유사도 점수 기반의 근사치 랭킹 | 설계상 정보 손실 발생 | 서버의 저장소 구성에 따라 다름 |
| 적합한 대상 | 이벤트 히스토리: PR, 티켓, CI 실행 기록 등 | 대규모 문서 집합, 모호한 질문 | 짧은 세션, 대화의 연속성 유지 | 여러 도구 및 세션 간에 공유되는 정보 |
| 필요 사항 | 변경되지 않는 ID, ID 기반 조회 API | 임베딩 모델 및 인덱스 | 요약 처리 단계 | 실행 중인 MCP 서버 |
| 한계점 | 연결 링크가 없는 정보는 탐색 불가 | 표현 방식이 다르면 사실을 놓칠 수 있음 | 세부 정보 누락 | 추가적인 서비스 운영 및 보안 관리 부담 |
실제 환경에서는 이 방식들을 함께 조합하여 사용하는 경우가 많습니다. 예를 들어 벡터 인덱스로 시작점이 될 스레드 ID를 찾은 다음, Chain of Recall을 통해 정확한 세부 정보를 추적해 나가는 식입니다. MemGPT 논문에서 제안한 운영체제 스타일의 메모리 계층 구조도 이와 매우 유사한 개념입니다. 기성 저장소를 바로 활용하고 싶다면 MCP를 활용해 AI 에이전트에 영구 메모리 추가하기 가이드를 확인해 보세요.
다만 두 가지 한계가 있습니다. 해당 에세이에서는 장기 기억을 여전히 해결해야 할 과제로 분류하고 있으며, Chain of Recall이 이를 완전히 해결했다고 주장하지는 않습니다. 또한 에세이의 실험에서 스레드 패스스루(Thread pass-through)를 제거하자 1회 실행당 캐시 읽기 토큰이 23.2M에서 31.8M으로 약 37% 증가했는데, 이는 기능 부재로 인한 비용 증가일 뿐 Chain of Recall 자체로 절감된 수치를 의미하는 것은 아닙니다.
하위 API가 반드시 보장해야 하는 요구 조건
앞서 살펴본 과정에서 각 홉은 모두 API 호출로 이루어집니다. 만약 단 하나의 호출이라도 잘못된 레코드를 반환하거나 응답하지 못하면 체인이 끊어지며, 에이전트는 동작을 멈추거나 부정확한 추측으로 답변하게 됩니다. 따라서 Chain of Recall을 뒷받침하는 API는 다음 네 가지 계약을 충족해야 합니다.
- ID의 불변성 보장: 오늘 반환된 ID는 다음 달에도 동일한 객체로 조회되어야 합니다. 삭제 후 ID 재사용이나 데이터 마이그레이션 후 번호 재부여는 절대 금지됩니다.
-
저비용의 정확한 ID 기반 조회:
GET /threads/{id}는 해당 단일 레코드만 정확히 반환해야 합니다. 별도의 검색을 수행하거나 “가장 유사한 일치 항목”을 반환해서는 안 됩니다. -
알 수 없는 ID에 대한 명확한 실패 처리: 존재하지 않는 ID는 RFC 9110에 명시된 대로 명확한 오류 본문과 함께
404 Not Found를 반환해야 합니다. 빈 객체와 함께200을 반환하면 에이전트는 존재하지 않는 메모리가 있는 것으로 잘못 인식하게 됩니다. -
누락 없는 커서 기반 페이징:
GET /threads/{id}/events?cursor=는 긴 스레드를 순서대로 탐색할 수 있어야 합니다. 모든 이벤트는 한 번씩만 나타나야 하고 누락이 없어야 하며, 새로운 이벤트가 유입되는 동안에도 커서의 유효성이 유지되어야 합니다.
이러한 계약 조건들은 코드 리팩터링 과정에서 알아채지 못하게 깨지기 쉬우므로 자동화 테스트로 철저히 검증해야 합니다. 또한 에이전트 툴 응답과 컨텍스트 창 가이드에서 자세히 다루었듯이, 툴 응답 크기를 작게 유지하는 것 역시 매우 중요합니다.
Apidog CLI로 코딩 에이전트를 활용해 회상 API 테스트하기
Chain of Recall의 신뢰성은 ID 기반 조회 엔드포인트의 안정성에 정비례하며, 코딩 에이전트를 활용하면 이러한 검증 테스트를 작성하고 주기적으로 실행할 수 있습니다. Apidog CLI를 사용하면 에이전트가 터미널에서 엔드포인트를 정의하고, 테스트 케이스를 생성하며, 이를 직접 실행할 수 있는 명령어 집합을 제공합니다.
초기 설정은 한 번만 진행하면 됩니다.
npm install -g apidog-cli@latest
apidog auth login --with-token <YOUR_TOKEN>
npx -y skills add https://apidog.com # pick your agent when prompted
그런 다음 Claude Code, Codex 등 사용하는 에이전트에 다음과 같은 프롬프트를 전달합니다.
In Apidog project <projectId>, define three endpoints for our agent memory
service: GET /threads/{id}, GET /threads/{id}/events?cursor=, and
GET /workers/{id}. Then create test cases that check:
1. A thread_id returned by GET /threads/{id} resolves to the same record
on a second call, and each owner worker ID resolves via GET /workers/{id}.
2. An unknown thread ID and an unknown worker ID both return 404.
3. Paging GET /threads/{id}/events with the cursor returns every event
once, in order, with no gaps.
Run them against the staging environment and summarize any failures.
에이전트는 각 페이로드 스키마를 확인하고, 작성 전 JSON의 유효성을 검증한 뒤 테스트 케이스를 생성하고 실행합니다.
apidog cli-schema get endpoint-create
apidog cli-schema validate endpoint-create --file thread-get.json
apidog endpoint create --project <projectId> --file thread-get.json
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file id-resolves.json
apidog test-case create --project <projectId> --file id-resolves.json
apidog run --test-case <caseId> --project <projectId> -e <envId> -r cli,json
cli 리포터는 터미널에 어설션별 성공 및 실패 여부를 출력하며, json 리포트는 어떤 홉에서 문제가 발생했는지 에이전트가 읽고 분석할 수 있는 파일을 제공합니다. 만약 마이그레이션 이후 특정 ID 조회가 실패하더라도, 에이전트가 끊어진 체인을 바탕으로 잘못된 답변을 내놓기 전에 리포트를 통해 먼저 발견할 수 있습니다. 매 머지마다 동일한 검사를 실행하려면 리포터를 -r junit으로 변경하면 되며, 전체적인 에이전트 루프는 Claude Code에서의 Apidog CLI 활용법에서 자세히 살펴볼 수 있습니다.
Chain of Recall이 적합한 활용처
Chain of Recall은 에이전트의 메모리가 PR, 티켓, CI 실행, 지원 스레드, 배포 기록처럼 개별적이고 서로 연결 가능한 이벤트 히스토리일 때 가장 적합합니다. 이러한 데이터는 이미 자연스럽게 고유 ID를 가지고 있으며, 사람들이 이에 대해 던지는 질문(“이 작업을 왜 했는가?”, “그 후에 무슨 일이 일어났는가?”) 역시 결국 연결 관계에 대한 질문이기 때문입니다.
비정형 문서나 모호한 질문에는 벡터 검색을 활용하고, 세부 정보가 누락되어도 괜찮은 짧은 세션에는 요약 방식을 사용하는 것이 좋습니다.
Chain of Recall은 하나의 에세이와 프로토타입에서 출발한 개념으로, 완제품이 아니라 명확하고 검증 가능한 아이디어에 가깝습니다. 이 에세이의 기반이 된 도구에 대해 더 알고 싶다면 DeepSeek Harness란 무엇인가를 먼저 읽어보시기 바랍니다.
자주 묻는 질문 (FAQ)
Chain of Recall은 바로 활성화할 수 있는 DeepSeek의 기능인가요? 아닙니다. 이는 DeepSeek Harness의 슈퍼 에이전트 에세이에서 소개된 개념이며, 일부 구현체는 공식 DeepSeek 제품이 아니라고 명시된 프로토타입 플러그인에 들어 있습니다. 이 패턴은 개발자가 직접 구현해야 합니다.
인라인(Inline)과 스필(Spill)의 차이점은 무엇인가요? 인라인은 ID, 짧은 요약, 인접 메시지를 프롬프트 내에 유지하는 방식입니다. 스필은 그 외의 내용을 잘라내고 필요할 때 에이전트가 ID를 통해 가져올 수 있도록 포인터만 남겨두는 방식입니다.
Chain of Recall이 RAG를 대체하나요? 아닙니다. RAG는 유사한 콘텐츠를 찾는 데 쓰이고, Chain of Recall은 정확한 ID 링크를 추적하는 데 쓰입니다. 실제로 많은 에이전트가 두 방식을 함께 사용합니다.
Chain of Recall을 사용하면 토큰을 37% 절감할 수 있나요? 아닙니다. 37%라는 수치는 스레드 패스스루에 관한 것입니다. 에세이의 실험에서 이를 제거했을 때 1회 실행당 캐시 읽기 토큰이 23.2M에서 31.8M으로 증가했습니다. 해당 에세이에서는 Chain of Recall 자체로 인한 토큰 절감 수치를 별도로 보고하지 않았습니다.
존재하지 않는 ID에 대해 ID 기반 조회 API는 무엇을 반환해야 하나요? 명확한 오류 본문과 함께 404 Not Found를 반환해야 합니다. 빈 객체와 함께 200을 반환하면 에이전트는 레코드가 존재하는 것으로 인식하여 회상 체인이 조용히 깨지는 원인이 됩니다.
에이전트의 메모리 API가 안정적으로 유지되는지 어떻게 테스트하나요? 한 호출에서 반환된 ID가 다음 호출에서도 동일하게 조회되는지, 존재하지 않는 ID에 대해 404를 반환하는지, 커서 페이징에서 누락이 없는지 검증하는 테스트 케이스를 작성하세요. 코딩 에이전트와 Apidog CLI를 활용하면 매 머지 시마다 이러한 테스트를 자동으로 생성하고 실행할 수 있습니다.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.

