Python으로 AI 에이전트의 영구 메모리 구축하기
요약
본 튜토리얼은 Python을 사용하여 AI 에이전트가 대화 세션 종료 후에도 정보를 기억할 수 있는 영구 메모리(persistent memory) 구축 방법을 안내합니다. 지원 대화를 API에 제출하고, 사실 추출을 기다린 뒤 자연어 쿼리로 관련 정보를 불러오는 3단계 워크플로우를 구현하는 것이 핵심입니다.
핵심 포인트
- 대화 내용을 프로필에 제출하여 사실(fact)을 추출할 수 있습니다.
- 영구 메모리 패턴은 에이전트의 연속성을 유지하며 프롬프트 과부하를 방지합니다.
- Namespace, Profile, Source 등 명확한 개념 모델을 사용하여 정보를 구조화해야 합니다.
- Ingest, Poll, Recall의 3단계 API 호출 흐름을 따릅니다.
AI 에이전트는 눈앞에서 진행되는 대화에 응답하는 데 능숙합니다. 더 어려운 문제는 그 대화가 끝난 후에도 무언가를 기억하는 것입니다.
사용자가 지원 에이전트에게 다음과 같은 정보를 말할 수 있습니다:
- 선호하는 연락 방법
- 계정 식별자
- 제품 구성
- 이전에 보고했던 문제
영구 메모리(persistent memory)가 없다면, 다음 세션은 '0'부터 시작하며 에이전트는 동일한 정보를 다시 요청합니다.
본 튜토리얼에서는 대화를 Telnyx Agent Memory로 전송하고, 사실(fact)을 추출하기를 기다린 다음, 자연어 쿼리로 해당 사실들을 불러오는 작은 Python CLI를 구축할 것입니다.
전체 예제는 여기에서 확인할 수 있습니다:
github.com/team-telnyx/telnyx-code-examples/tree/main/persistent-ai-agent-memory
구축할 내용
이 예제는 간단한 3단계 워크플로우를 따릅니다:
Conversation transcript
|
v
...
CLI의 기능은 다음과 같습니다:
- 지원 대화를 프로필에 제출합니다.
- 비동기 작업 ID(asynchronous operation ID)를 받습니다.
- 사실 추출이 완료될 때까지 폴링(Polls)합니다.
- 사용자에게 선호하는 연락 방법을 묻습니다.
- 관련성 순서대로 일치하는 메모리를 출력합니다.
이 패턴은 모든 이전 대화를 프롬프트에 포함시키지 않으면서 에이전트의 연속성을 제공합니다.
에이전트 메모리 모델 (The Agent Memory model)
에이전트 메모리는 몇 가지 핵심 개념을 사용하여 정보를 구성합니다:
- Namespace: 애플리케이션 또는 환경에 대한 격리 경계(isolation boundary)입니다.
- Profile: 메모리가 설명하는 사람 또는 개체입니다.
- Source: API에 제출된 원본 세션 또는 사실입니다.
- Memory: 소스에서 추출된 개별 사실(individual fact)입니다.
- Operation: 완료까지 추적할 수 있는 비동기 쓰기 작업(asynchronous write job)입니다.
예제는 default 네임스페이스와 user_123이라는 이름의 프로필을 사용합니다.
실제 애플리케이션에서는 기존 고객, 계정 또는 발신자 식별자를 프로필 ID로 사용할 수 있습니다.
세 가지 API 호출
모든 엔드포인트는 다음을 기준으로 합니다:
예제에서는 이 호출들을 사용합니다:
POST /namespaces/{namespace}/profiles/{profile_id}/ingest
GET /namespaces/{namespace}/operations/{operation_id}
POST /namespaces/{namespace}/profiles/{profile_id}/recall
각각을 살펴보겠습니다.
1. 대화 내용 수집 (Ingest a conversation)
먼저, API 키를 로드하고 인증 헤더를 준비합니다:
import os
import requests
from dotenv import load_dotenv
...
지원 스크립트의 요약된 버전은 다음과 같습니다:
transcript = [
{
"role": "user",
...
메시지들을 프로필에 제출합니다:
namespace = "default"
profile_id = "user_123"
session_id = "demo-session-001"
...
API는 완료된 메모리가 아닌 202 Accepted를 반환합니다.
일반적인 응답은 다음과 같습니다:
{
"data": {
"operation_id": "op_abc123",
...
사실 추출(Fact extraction)은 비동기적으로 발생합니다. operation_id는 이를 추적하는 데 사용하는 핸들입니다.
2. 쓰기가 완료될 때까지 폴링 (Poll until the write finishes)
메모리는 쓰기 작업이 완료되기 전까지 검색(recall)할 수 없습니다.
샘플은 2초마다 작업을 확인하고, 최종 상태에 도달하면 중단합니다:
import time
terminal_statuses = {"completed", "failed", "cancelled"}
...
정상적인 진행 과정은 다음과 같습니다:
pending -> processing -> completed
운영(Production) 코드는 타임아웃을 강제해야 합니다. 전체 예제는 60초 후에 폴링을 중단하고 무한정 기다리는 대신 오류를 발생시킵니다.
이 명시적인 작업 수명 주기(operation lifecycle)는 애플리케이션이 다음 사항들을 구별할 수 있기 때문에 유용합니다:
- 아직 처리 중인 쓰기
- 완료된 쓰기
- 실패한 쓰기
- 취소된 쓰기
클라이언트가 폴링 중에 재시작하더라도 전체 대화를 다시 제출하는 대신 동일한 작업을 계속 확인할 수 있습니다.
3. 관련 사실 검색 (Recall relevant facts)
수집이 완료되면, 자연어로 프로필을 조회합니다:
결과는 관련성 순으로 순위가 매겨집니다:
for fact in facts:
print(f"[score={fact['score']}] {fact['text']}")
결과는 다음과 같을 수 있습니다:
{
"id": "mem_abc123",
"text": "사용자가 선호하는 연락 방법은 [email protected]의 이메일입니다.",
...
이 응답에는 애플리케이션이 원본 스크립트를 직접 검색할 필요 없이 추출된 사실(fact)이 포함됩니다.
따라서 해당 사실을 새로운 대화가 시작될 때 에이전트의 컨텍스트에 추가할 수 있습니다.
전체 예제 실행하기
저장소 클론하기:
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/persistent-ai-agent-memory
.env 파일 생성하기:
echo "TELNYX_API_KEY=your_telnyx_api_key_here" > .env
의존성 설치하기:
pip install -r requirements.txt
CLI 실행하기:
python app.py
이 예제는 Telnyx API 키만 필요합니다. 전화번호, 메시징 프로필 또는 별도의 데이터베이스가 필요하지 않습니다.
운영 환경에서 처리할 가치가 있는 세부 사항
샘플에는 놓치기 쉬운 몇 가지 유용한 안전장치(safeguards)가 포함되어 있습니다.
경로 식별자 인코딩하기 (Encode path identifiers)
네임스페이스(Namespace), 프로필(profile), 작업(operation) 식별자는 URL에 삽입되기 전에 인코딩되어야 합니다:
from urllib.parse import quote
profile_id = quote(profile_id, safe="")
이렇게 하면 기존 고객 식별자에 포함된 예약 문자가 요청 경로를 변경하는 것을 방지할 수 있습니다.
전송 전에 입력값 유효성 검사하기 (Validate inputs before sending them)
이 예제는 여러 API 제약 조건을 강제합니다:
if len(session_id) > 128:
raise ValueError("session_id must be <= 128 characters")
...
로컬에서 실패하는 것이 유효하지 않은 요청을 보내고 나중에 디버깅하는 것보다 개발자에게 더 명확한 오류를 제공합니다.
수집 직후 리콜(recall) 하지 않기 (Do not recall immediately after ingesting)
수락된 쓰기 작업(write)이 아직 리콜 가능한 메모리(memory)는 아닙니다.
만약 recall이 데이터를 수집(ingestion)한 직후 빈 리스트를 반환한다면, 먼저 해당 작업이 completed 상태에 도달했는지 확인해야 합니다.
격리 경계(isolation boundaries)를 의도적으로 선택하세요
프로파일은 서로 격리되어 있으며, 네임스페이스는 애플리케이션 또는 환경 간의 추가적인 경계를 제공합니다.
예시:
namespace: production-support
profile: customer_1024
개발(development)과 운영(production)을 위해 별도의 네임스페이스를 사용할 수 있으며, 각 고객 또는 호출자에게는 해당 네임스페이스 내에 고유한 프로파일이 할당됩니다.
사용하려면 사용자 지정 네임스페이스를 미리 생성해야 합니다. default 네임스페이스는 별도의 프로비저닝 단계 없이 사용 가능합니다.
메모리 삭제 계획을 세우세요
영구 메모리는 삭제 전략과 함께 제공되어야 합니다.
Agent Memory API에는 개별 소스를 삭제하거나 전체 프로파일을 삭제하는 엔드포인트가 포함되어 있습니다. 이를 통해 애플리케이션은 필요한 경우 가져온(imported) 세션 하나를 제거하거나, 프로파일과 관련된 모든 것을 지울 수 있습니다.
이 패턴이 적용되는 곳
동일한 데이터 수집(ingest), 폴링(poll), 그리고 검색(recall) 워크플로우는 다음을 지원할 수 있습니다:
- 고객 지원 에이전트: 이전 문제 및 선호도를 기억함
- 영업 보조원: 대화 전반에 걸쳐 계정 컨텍스트를 유지함
- 스케줄링 에이전트: 이용 가능 여부 또는 통신 선호도를 검색함
- 음성 에이전트: 재방문하는 호출자를 인식함
- 내부 코파일럿(copilots): 사용자별 작업 컨텍스트를 유지함
메모리 모델은 동일하게 유지되더라도 통신 채널은 변경될 수 있습니다. SMS, 음성, 이메일, 브라우저 채팅 모두 동일한 프로파일 식별자로 해결될 수 있습니다.
최종 생각
더 긴 프롬프트가 장기 메모리와 같은 것은 아닙니다.
프롬프트 컨텍스트는 일시적입니다. 영구 메모리는 에이전트가 학습한 것을 저장하고 다음 상호작용에 관련 있는 사실만을 검색할 수 있는 지속적인 공간을 제공합니다.
여기서 구현은 의도적으로 작게 유지됩니다:
ingest -> poll -> recall
이는 에이전트를 격리된 세션에서 실제 연속성(continuity)으로 이동시키기에 충분합니다.
자료 (Resources)
다음은 관련 자료 링크입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기