메모리 영속화와 암호화
LLaMON의 PostgreSQL 메모리는 Agent checkpoint와 Orchestrator state·durable execution을 재개하기 위한 저장소입니다. Langfuse trace는 관측용이며 재개의 원본으로 사용하지 않습니다. memory를 끄거나 backend="in_memory"를 명시하면 DB·키링·migration 경로에 들어가지 않습니다.
새 프로젝트에서 backend 전환
섹션 제목: “새 프로젝트에서 backend 전환”메모리를 지원하는 모든 CLI 템플릿은 처음 선택한 모드와 관계없이 같은 env 기반 코드를 생성합니다. 예를 들어 --memory in-memory로 시작해도 Python을 고치지 않고 .env의 한 값만 바꿀 수 있습니다.
MEMORY_BACKEND=in_memory # off | in_memory | postgres | sqliteLLAMON_MEMORY_KEYRING=.llamon/secrets/memory-keyring.jsonPOSTGRES_MEMORY_DSN=postgresql://runtime-role@pgbouncer/agent_memoryPOSTGRES_MIGRATION_DSN=postgresql://migration-role@postgres/agent_memoryCLI는 scripts/migrate_memory.py와 owner-only 권한(0600)의 로컬 개발 키링을 함께 만들며 키링은 Git에서 제외합니다. PostgreSQL로 바꿀 때는 다음 순서만 따르면 됩니다.
# .env에서 MEMORY_BACKEND=postgres로 변경한 뒤uv run python scripts/migrate_memory.pyuv run python main.py처음부터 --memory postgres를 선택한 Docker Compose 프로젝트는 PostgreSQL, migration, non-root runtime이 읽을 수 있는 keyring init volume까지 자동 구성합니다. 처음 in-memory를 선택한 프로젝트에서 나중에 전환하는 경우 .env의 두 DSN이 가리키는 PostgreSQL/PgBouncer를 준비한 뒤 같은 migration 명령을 실행합니다.
prepare-offline이 만드는 배포 tar에는 .llamon/secrets/memory-keyring.json이 0600 권한 그대로 포함됩니다. keyring이 있는 프로젝트에는 deploy/memory-keyring-deployment.md도 생성해 Kubernetes/Docker Secret mount와, 배포 설정을 제어할 수 없는 환경의 .dockerignore·Dockerfile 수동 fallback을 함께 안내합니다. 이 문서는 같은 prepare-offline 실행에서 생성되는 tar에도 포함됩니다. 키 값은 .env로 복사하지 마세요. .env에는 LLAMON_MEMORY_KEYRING 경로만 두며, 키가 포함된 tar 자체를 secret 반입물로 취급해 접근 권한과 전달 경로를 통제해야 합니다. 운영 keyring을 Vault/KMS/HSM 등 외부 secret provider로 주입하는 환경에서는 배포 tar에 개발 keyring을 싣지 말고 배포 단계에서 운영 secret을 해당 경로에 mount합니다.
Orchestrator는 코드를 바꾸는 대신 아래 값을 사용합니다. 이 env가 설정되면 orchestrator.toml의 state_backend를 덮어씁니다.
ORCHESTRATOR_STATE_BACKEND=in_memory # in_memory | postgresPOSTGRES_ORCH_DSN=postgresql://runtime-role@pgbouncer/orchestrator_statePOSTGRES_MIGRATION_DSN=postgresql://migration-role@postgres/orchestrator_stateoutcome-evaluator처럼 memory가 의미상 금지된 off-only 템플릿은 PostgreSQL 전환값을 노출하지 않습니다.
먼저 migration 실행
섹션 제목: “먼저 migration 실행”runtime은 DDL 권한을 사용하지 않습니다. PgBouncer가 아닌 PostgreSQL direct DSN을 migration 전용 환경 변수에 넣고 별도 role로 실행하세요.
export POSTGRES_MIGRATION_DSN='postgresql://migration-role@postgres/llamon'just memory-migrate llamon_runtime llamon_observability생성되는 고정 schema는 llamon_checkpoint_v2와 llamon_runtime_v2입니다. runtime은 schema version이 정확히 2가 아니면 시작을 거부합니다. 기존 plaintext PostgreSQL schema는 읽거나 복사하지 않으므로 승인된 reset 또는 별도 마이그레이션 절차가 필요합니다.
키링 준비
섹션 제목: “키링 준비”폐쇄망 기본 KeyProvider는 read-only JSON 파일입니다. 파일은 symlink가 아니어야 하고 owner 외에는 어떤 읽기·쓰기·실행 권한도 없어야 합니다.
{ "version": 1, "active_kid": "prod-2026-08", "keys": { "prod-2026-08": "BASE64_ENCODED_EXACTLY_32_BYTES" }}chmod 600 /run/secrets/llamon-memory-keyring.jsonexport LLAMON_MEMORY_KEYRING=/run/secrets/llamon-memory-keyring.jsonexport LLAMON_MEMORY_TENANT_ID=defaultexport LLAMON_MEMORY_PRINCIPAL_ID=serviceroot key는 store에 전달되지 않습니다. KeyProvider가 tenant·agent·purpose별 HKDF data key를 만들고 AES-256-GCM이 매 record에 새 12-byte nonce를 사용합니다. 따라서 같은 운영 root keyring을 여러 Agent replica가 공유해도 실제 data key는 agent_id별로 다릅니다. 로컬 scaffold는 프로젝트마다 새 root keyring을 생성하지만, 운영에서는 replica마다 새 키를 만들면 기존 데이터를 재개할 수 없으므로 같은 Agent replica끼리 동일한 환경 keyring을 공유해야 합니다. principal, conversation, record ID와 codec version은 AAD에 묶입니다. 명시적 PostgreSQL backend에서 키링 오류는 fail-closed이며 in-memory로 폴백하지 않습니다.
PgBouncer profile
섹션 제목: “PgBouncer profile”# 다중 replica 권장값export MEMORY_PG_POOL_MODE=transaction지원 값은 direct, session, transaction입니다. transaction pooling은 asyncpg statement cache를 항상 0으로 강제합니다. 프로세스·event loop·DSN·role·profile이 같으면 Agent checkpoint/KV와 Orchestrator state/execution이 하나의 pool을 공유합니다. 기본은 min_size=0, max_size=5입니다.
Orchestrator turn은 DB connection을 잡은 채 LLM·tool·A2A를 실행하지 않습니다. 짧은 lease와 fencing token을 얻고 connection을 반환한 뒤, heartbeat와 revision CAS 저장만 각각 짧은 transaction으로 실행합니다.
strict 운영 모드
섹션 제목: “strict 운영 모드”export MEMORY_STRICT_MODE=trueexport MEMORY_RETENTION_DAYS=30strict 모드는 PostgreSQL backend, 키링 경로와 양의 retention 값을 모두 명시하도록 요구합니다. 환경별 keyring은 분리하고 모든 replica가 같은 환경·agent용 keyring을 읽게 하세요.
retention worker나 승인된 운영 job에서 같은 trusted scope 환경 변수를 바인딩한 뒤 다음 명령을 실행합니다. 후보를 찾은 뒤 catalog row를 다시 잠그고 만료 여부를 확인하므로, 그 사이 갱신된 대화는 삭제하지 않습니다.
just memory-retention 30단일 Agent WorkMemory
섹션 제목: “단일 Agent WorkMemory”WorkMemory는 기본으로 꺼져 있으며 기존 MemoryConfig 직렬화 shape를 바꾸지 않습니다.
from llamon_agent import Agent, AgentWorkMemoryConfig
agent = Agent(model="gpt-4o-mini").with_work_memory( AgentWorkMemoryConfig(enabled=True, max_items=3, max_characters=2000))활성화하면 출력 가드레일을 통과하고 정상 완료된 응답만 checkpoint의 기존 summary 슬롯에 bounded envelope로 commit합니다. 먼저 ResponseContract의 text/data를 projection하고, 파일·artifact metadata만 있는 성공 응답은 inline bytes를 제거한 뒤 내부 summary LLM을 사용합니다. summary가 실패하거나 비어 있으면 저장을 생략합니다. input_required, unavailable, failed 또는 차단된 응답은 저장하지 않습니다. 비활성 상태에서는 추가 graph state, LLM 호출, DataPart, trace field가 없습니다.
삭제와 key rotation
섹션 제목: “삭제와 key rotation”삭제는 trusted scope 안에서 tombstone을 먼저 기록하고 checkpoint, blob, pending write, KV, session catalog, WorkflowState, lease, execution과 artifact를 한 번에 지웁니다. 같은 scope의 tombstoned conversation ID는 다시 생성할 수 없습니다.
키링은 old kid와 active kid를 함께 두면 mixed-key read를 지원합니다. EncryptedStateCodec.reencrypt()로 batch 재암호화가 끝난 뒤에만 old kid를 제거하세요. agent ID는 파생 키와 scope hash의 일부이므로 runtime 관리 API에서 즉석 변경하지 않습니다. 현재 secure backend의 agent-ID 변경 요청은 전용 offline 재암호화 도구가 도입될 때까지 명시적으로 실패합니다.
의도적인 비호환
섹션 제목: “의도적인 비호환”- 기존 plaintext PostgreSQL 데이터는 v2에서 읽지 않습니다.
- 명시적 PostgreSQL backend에는 keyring이 필수입니다.
- 메모리 설정 관리 API는 raw PostgreSQL DSN을 반환하지 않습니다.
- persistence v2 schema는 구버전 SDK가 읽을 수 없습니다.
- 장기기억은 평가용
LongTermMemoryPort와 disabled no-op만 제공하며 runtime에는 연결하지 않습니다.
로컬 계약은 just memory-persistence-check로 검사합니다. direct/session/transaction 실제 DB matrix, crash/restart, RLS connection 재사용, plaintext sentinel scan과 rotation은 배포 canary에서 별도로 실행하세요.