내 에이전트들이 서로를 잊어버려서, 이에 대한 프로토콜을 작성했습니다
요약
기존 에이전트 프레임워크들은 도구 호출 방식만 표준화했을 뿐, 에이전트 간의 '메모리' 공유 및 상호 운용성을 위한 프로토콜은 부재했습니다. 필자는 이를 해결하기 위해 개방형 HTTP 기반의 에이전트 메모리 프로토콜(AMP)을 개발했습니다. AMP는 JSON 형태의 메모 셀과 간단한 REST API를 정의하여, 다양한 프레임워크 간에 메모리를 표준화된 방식으로 주고받게 합니다.
핵심 포인트
- 에이전트 도구 호출은 MCP로 표준화되었으나, 메모리 공유는 여전히 문제다.
- AMP(Agent Memory Protocol)는 에이전트 메모를 위한 개방형 HTTP 프로토콜이다.
- 메모 셀은 내용물, 소유자, 중요도 점수 등 JSON 형태로 정의된다.
- REST API 기반으로 설계되어 특정 언어에 종속되지 않는 것이 핵심 강점이다.
저는 노트북에서 몇 개의 에이전트를 운영합니다. 하나는 저를 위해 메모를 기록하고, 다른 하나는 제 프로젝트에 대해 질문에 답하며, 또 다른 하나는 뉴스를 감시하다가 중요한 일이 생기면 알려줍니다. 각각은 그 자체로는 괜찮습니다. 하지만 함께 있을 때는 제가 이름을 붙이는 데 시간이 걸릴 만큼 잊어버리는 경향이 있습니다.
메모 에이전트는 제가 이메일을 느리게 읽고 짧은 메시지를 선호한다는 것을 알고 있습니다. 나머지 두 에이전트는 매일 저에게 어떻게 연락받고 싶은지 물어봅니다.
모델 자체가 약해서가 아닙니다. 각 에이전트에는 자체적인 메모리 레이어, 자체 저장소, 그리고 '기억'이 무엇인지에 대한 자신만의 생각이 있습니다. LangChain에는 메모리 클래스가 있고, LlamaIndex에도 자체 것이 있으며, CrewAI와 AutoGen도 각각의 것을 가지고 있습니다. LangChain 에이전트는 LlamaIndex 에이전트의 메모리를 읽을 수 없으며, 설령 읽을 수 있다 하더라도 전달할 합의된 형태가 없습니다.
Anthropic의 Model Context Protocol(MCP)은 이미 이 문제의 절반을 해결했습니다. MCP 이전에는 모든 에이전트가 도구를 호출하는 방식이 개별적이었지만, 이제는 아무도 생각할 필요 없는 표준이 생겼습니다. 하지만 메모리에는 그런 대우를 받지 못했습니다. 그래서 어느 주말에 저는 제 자체 환경을 위해 이를 고칠 수 있는 가장 작은 것을 작성하기 시작했고, 계속해서 진행하게 되었습니다.
요약: MCP는 에이전트가 도구를 호출하는 방식을 표준화했습니다. 하지만 그들이 기억하는 방식은 아무것도 표준화하지 못했습니다. 저는 에이전트 메모를 위한 개방형 HTTP 프로토콜인 AMP(Agent Memory Protocol)를 작성했습니다. 이것이 정의하는 내용과, 제가 이를 구축하면서 잘못 이해했던 다섯 가지 사항입니다.
실제로 구현한 것들
세 가지 구성 요소이며, 저는 네 번째를 추가하지 않으려고 노력했습니다.
메모 셀(memory cell). 메모에 대한 하나의 JSON 형태: 내용물, 소유자, 생성자, 출처 세션, 중요도 점수, 그리고 접근 정책.
간단한 REST API. /amp/v1 아래의 일반 HTTP를 사용합니다. 메모리를 작성하는 것은 JSON 본문으로 POST 요청을 보내는 방식입니다. SDK가 필요 없다는 점이 중요합니다. 왜냐하면 오디오로 들리는 것보다 더 중요한 것이 있기 때문입니다: 단 하나의 언어만 말할 수 있는 프로토콜은 라이브러리가 되기 때문입니다. 어차피 Python과 Node용 클라이언트는 존재하지만, 와이어 포맷(wire format)이 계약서 역할을 합니다.
수명 주기 관리. 셀(Cell)들은 시간이 지남에 따라 중요도 점수(importance score)가 감소하며, 백그라운드 작업(background job)은 이 점수가 떨어짐에 따라 메모리를 active에서 stale로, 다시 archived로 이동시킵니다. 제가 가장 신경 쓰는 부분이 바로 이 부분인데, 왜냐하면 이것이 단순한 메모리 저장소와 데이터 누수(leak)를 가르는 차이점이기 때문입니다. 더 이상 중요하지 않은 컨텍스트는 스스로 검색 결과에서 사라져야 합니다.
요약: 메모리를 위한 하나의 JSON 구조, 모든 언어가 사용할 수 있는
/amp/v1아래의 REST API, 그리고 크론 작업(cron job)을 직접 작성할 필요 없이 오래된 컨텍스트를 폐기하는 감쇠 엔진(decay engine).
공유는 제가 과소평가했던 부분
다중 에이전트 메모리는 에이전트들이 이를 공유하기 시작할 때만 흥미로워지며, 공유에는 권한(permission)이 필요합니다. 이 권한은 호출자(caller)가 아닌 셀 자체에 속해야 합니다:
{
"access_policy": {
"readable_by": ["agent_billing_*"],
...
}
와일드카드("*")도 작동하며, public의 기본값은 false이고, 셀을 읽을 수 없는 에이전트는 해당 셀이 존재하든 아니든 동일한 403 응답 코드를 받습니다. 마지막 부분이 의도적입니다. 만약 '보이지 않음'과 '삭제됨'이 다르게 응답한다면, 오류 코드 자체가 접근할 권한이 없는 데이터를 탐색하는 수단이 될 수 있기 때문입니다.
리포지토리의 데모는 실제 에이전트를 사용하여 정확히 그 시나리오를 실행합니다: 고객 서비스가 선호도를 저장하고, 청구(billing) 시스템이 이를 읽어오며, 마케팅 부서가 같은 질문을 했지만 아무것도 얻지 못하는 경우입니다.
요약: 권한은 셀에 존재하며 (
readable_by,writable_by,public: false), 읽을 수 없는 셀은 삭제된 셀과 동일하게 보여 오류 코드를 탐색하는 데 사용될 수 없습니다.
사라지는 메모리들
모든 셀은 중요도 점수(importance score)와 감쇠율(decay rate)을 가집니다. 참조 서버는 작업(job)을 실행하여, 점수가 떨어짐에 따라 셀들을 active 상태에서 stale 상태를 거쳐 archived 상태로 이동시키는데, 이때 임계값은 코드 내부에 숨기지 않고 문서화되어 있습니다 (stale은 0.3 미만, archived는 30일 경과 후). 간격을 변경하거나 작업을 중지하고 관리자 엔드포인트(admin endpoint)를 통해 직접 실행을 트리거할 수 있습니다.
또한 저는 안전장치(floor)를 마련했습니다. 삭제 작업(purge)은 30일 보존 기간 내의 셀을 삭제하는 것을 거부합니다. 왜냐하면 "저희는 귀하의 데이터를 30일 동안 보관합니다"라는 문구는 저장한 사람에게 하는 약속이기 때문입니다.
요약: 중요도는 감쇠하며, 셀들은 스스로
active에서stale를 거쳐archived로 이동하고, 삭제 작업은 문서에 명시된 보존 기간을 무시하지 않습니다.
제가 잘못한 다섯 가지 실수
이 부분은 다른 사람의 글에서 읽고 싶었던 내용이라 포함합니다.
1. 같은 규칙을 두 번 작성했습니다. 검색 기능(Search) 자체적으로 읽기 검사(read check)를 수행했고, 저장소 계층(storage layer)에서도 또 다른 검사를 했습니다. 이들은 정확히 한 종류의 에이전트 ID에 대해 의견 불일치를 보였고, 이는 양쪽 호출자 모두 동일한 답변을 제공하는지 확인하는 테스트를 통해 발견되었습니다. 이제는 하나의 함수 안에 단 하나의 규칙만 존재하며, 이를 유지하는 테스트도 있습니다. 정책을 중복으로 작성하는 것은 스타일 문제가 아니라, 두 번째 호출자를 기다리는 버그입니다.
2. 아무것도 강제하지 않는 정책을 문서화했습니다. 문서 문자열(docstring)에는 보존 기간이 서버 측에서 강제된다고 되어 있었습니다. 하지만 실제 코드는 해당 기간을 확인하는 함수가 누구에게도 호출되지 않았기 때문에, 셀이 삭제로 표시된 지 불과 1초 만에 기꺼이 삭제해버릴 수 있었습니다. 문서와 코드가 의견 충돌을 일으켰고, 문서를 따르는 쪽이 승리했습니다. 이것이야말로 그 쌍(pair)에서 최악의 버전입니다.
3. Mock이 통과했지만 실제로는 작동할 수 없는 메서드. 비동기(async) 클라이언트의 forget()은 셀을 삭제하기 전에 아카이브로 표시하지 않았기 때문에, 모든 호출에서 409 에러가 반환되었습니다. 테스트는 Mock이 DELETE를 응답하고 사전 조건(precondition)을 모델링하지 않았기 때문에 통과했습니다. Mock은 사용자의 규칙을 알지 못합니다. 저는 실제 서버와 연동되는 작은 스위트를 추가했고, 이 버그를 다시 넣어서 실패할 수 있음을 증명했습니다.
4. 도달할 수 없는 경로가 존재했다. GET /memories/query는 GET /memories/{memory_id} 뒤에 등록되었기 때문에, "query"라는 단어가 메모리 ID로 파싱되었습니다. 이 엔드포인트는 코드와 문서, 그리고 인증 테스트에 있었지만 실제로 실행된 적이 없었습니다. 이제 목록 경로(listing route)를 먼저 등록하고, 테스트가 스스로 응답하는지 확인합니다.
5. 나의 첫 벤치마크는 세 가지를 한 번에 측정했다. 각 샘플이 다른 쿼리를 사용했기 때문에, 테이블은 5000개의 셀이 1000개보다 빠다고 주장했습니다. 대신 반복되는 단일 쿼리를 측정하고, 최소 컬럼을 추가한 후, 조용한(quiet) 기계에서 다시 실행했습니다. 실제 수치는 docs/performance.md에 그들이 다루지 않은 부분 옆에 있습니다.
핵심은 이 모든 것이 테스트를 거치면서 효력을 잃은 주장들이었다는 것입니다. 그래서 저는 HTTP를 통해 서버와 통신하고, 제 구현체로부터 아무것도 가져오지 않는 규격 준수 스위트(conformance suite)를 작성했습니다. 이를 다른 사람의 서버에 연결하여 명세서(spec)와 어디가 다른지에 대한 정직한 답변을 얻을 수 있습니다.
요약: 중복된 규칙들이 불일치합니다. 문서화되었지만 아무것도 강제하지 않는 정책은 정책 자체가 없는 것보다 더 나쁩니다. Mock은 사용자의 규칙을 알지 못합니다. 라우트 등록 순서는 엔드포인트를 도달할 수 없게 만들 수 있습니다. 나의 첫 벤치마크는 잘못된 것을 측정했습니다. 구현체에서 아무것도 가져오지 않는 규격 준수 스위트를 작성한 것이 이 다섯 가지 모두를 보이게 했습니다.
아직 부족한 점들
- PyPI나 npm에 배포되지 않습니다. 오늘 레포지토리에서 직접 설치해야 합니다.
- 호스팅 서비스가 없습니다. 이 단계의 프로토콜에는 사용자가 직접 실행하는 것이 적절하다고 생각합니다.
- Python과 Node용 클라이언트만 지원합니다. Go와 Rust는 사람들이 요청하는 언어입니다.
- 저장소(Storage)는 플러그인 방식입니다. 기본적으로 인프라가 필요 없는 ChromaDB를 사용하거나,
pgvector를 사용하는 PostgreSQL을 사용할 수 있습니다. 둘 다 동일한 어댑터 계약 테스트를 통과합니다. - 인증(Auth)은 선택 사항이며 키만 사용합니다. 비활성화하면 서버는 로컬 사용에 대한 명세서가 설명하는 대로
X-AMP-Agent-ID헤더를 신뢰합니다. 활성화하면 키가 필요하지만, 아직 스코프(scope), 만료일(expiry), 또는 회전(rotation) 기능은 없으므로 인터넷에 노출되는 배포 환경에서는 여전히 무언가를 앞에 두는 것이 좋습니다. - 기본 소멸(decay) 값은 제가 설정한 것입니다. 0.3과 30일은 제가 임의로 선택한 숫자이며, 실제 워크로드에 기반하여 검증된 수치는 아닙니다.
사용해 보기 (Poking at it)
git clone https://github.com/glatinone/agent-memory-protocol.git
cd agent-memory-protocol/server && docker compose up -d
...
레포지토리: https://github.com/glatinone/agent-memory-protocol
명세 및 문서(Spec and docs): https://glatinone.github.io/agent-memory-protocol/
규격 준수 테스트 스위트(Conformance suite): 레포지토리 내 conformance/ 폴더에 있으며, 39개의 벡터로 구성되어 있고 HTTP 전용이며 참조 서버에 대한 의존성이 없습니다.
제가 알고 싶은 것들 (What I would like to know)
만약 여러 에이전트 시스템(multi-agent systems)을 운영한다면, 현재 메모리를 어떻게 처리하시나요? 일화 기억(episodic memory)과 의미론적 기억(semantic memory)을 분리하여 관리하나요, 아니면 다른 점수(scores)를 가진 하나의 것으로 취급하나요? 그리고 프레임워크 전반에 걸쳐 공유되는 스키마가 실제로 도움이 되나요, 아니면 단지 문제를 다른 곳으로 옮기는 것일 뿐인가요?
저는 마지막 질문에 대해 진심으로 확신하지 못합니다. 프로토콜은 사람들이 부여하는 동의(agreement) 가치가 전부이며, 더 많은 사람이 의존하기 전에 이 아이디어가 틀렸다고 듣는 편이 낫습니다. 이슈와 PR을 받고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기

