Letta (原 MemGPT)

一句话定位

Letta 是 MemGPT 记忆架构的生产级服务端实现(Python + FastAPI 有状态 agent server),把”记忆作为一等公民”贯彻到底:三层记忆(core in-context block / recall 会话 / archival 向量库)+ 自编辑记忆工具 + sleeptime 后台记忆整理(自进化)+ MemFS git 版本化记忆 + conversation 隔离;agent loop 用 tool-rule 状态机替代 heartbeat 做编排与停机;工具默认沙箱隔离(Local/E2B/Modal)、审批门 human-in-the-loop;并原生打通多轮 RL(SGLang token-id 轨迹)与 ClickHouse/OTel 可观测。

需要说明的定位:本仓库是 legacy Letta 服务端(Letta V1 API + SDK 背后的有状态服务),也正是 MemGPT 论文分层记忆的工程化落地。README 注明活跃开发已迁到独立的 letta-code(TypeScript CLI),但记忆机制的一手实现仍在这个 Python 仓库里,因此它是”记忆维度”最该读的样本。

核心架构总览(目录结构关键路径 + 引用的 commit)

分析基于 commit b76da9092518cbaa2d09042e52fdcbde69243e18(2026-07-03,docs: update README to Letta Agent SDK…)。仓库 536 个 .py 文件,FastAPI 服务端 + SQLAlchemy ORM/Postgres/pgvector。关键路径:

  • letta/agents/agent_loop.py — agent 类型 → 执行 loop 的工厂分发
  • letta/agents/letta_agent_v3.py(2134 行)— 当前主 agent loop(V3,继承 V2)
  • letta/agents/letta_agent_v2.py(1487 行)— V2 loop(含已弃用的 heartbeat 机制)
  • letta/functions/function_sets/base.py — 核心记忆编辑工具集(core/archival/conversation_search + memory_* patch 工具)
  • letta/functions/schema_generator.py — 从 Google 风格 docstring 生成 tool JSON schema
  • letta/prompts/system_prompts/letta_v1.py — V1 系统提示骨架
  • letta/prompts/prompt_generator.py — 系统提示动态组装
  • letta/schemas/memory.py — Memory/Block 及 <memory_blocks>/<directories>/<available_skills> 渲染
  • letta/services/summarizer/summarizer.py(+ compact.py/thresholds.py)— 上下文压缩/驱逐
  • letta/groups/sleeptime_multi_agent_v4.py — 睡眠时后台记忆 agent(自进化核心)
  • letta/services/tool_executor/tool_execution_manager.py — 工具执行器工厂/路由
  • letta/services/tool_sandbox/{base,local_sandbox,e2b_sandbox,modal_sandbox}.py — 沙箱执行
  • letta/helpers/tool_rule_solver.py + letta/schemas/tool_rule.py — 工具规则编排 DSL
  • letta/adapters/sglang_native_adapter.py — 多轮 RL 训练 token-id/logprob 适配器
  • letta/services/{passage_manager,message_manager,archive_manager,block_manager_git}.py — 记忆存储
  • letta/services/memory_repo/git_operations.py/block_markdown.py)— MemFS git-backed 记忆
  • letta/services/llm_trace_writer.py + letta/otel/tracing.py + letta/services/step_manager.py — 可观测性
  • letta/server/rest_api/routers/v1/agents.py 等 — FastAPI agent server

Agent Loop(主循环 / 何时继续何时停)

入口是工厂 AgentLoop.load()agent_loop.py:15),按 agent_type + enable_sleeptime 分发:letta_v1_agent/sleeptime_agentLettaAgentV3;开启 sleeptime 且有 group → SleeptimeMultiAgentV4/V3;否则回落 LettaAgentV2(源码确认在 agent_loop.py 里有 enable_sleeptime 但 group 为 None 时的 warning 回落分支)。

主循环在 letta_agent_v3.py:阻塞式 step():222)与流式 stream():444)都是 for i in range(max_steps):328/:569),上限 DEFAULT_MAX_STEPS。每轮调 _step():895),执行完检查 self.should_continue,为 False 即 break(:386);最后一轮仍未设 stop → StopReasonType.max_steps:394)。

V3 的停止哲学与 MemGPT 原版不同。类 docstring(:100-110)明确 “No heartbeats(loops happen on tool calls)“——系统提示末尾也写着 “To continue: call another tool. To yield control: end your response without calling a tool.”(见 letta_v1.py PROMPT 结尾,源码已核对)。停/续由 _handle_ai_response():1595)+ _decide_continuation():1971)决定:

  • 无 tool call 且无 content → end_turn;除非有 required-before-exit 工具未调,则注入 heartbeat 系统消息强制续(:1626-1642)。
  • 无 tool call 但有 content(纯文本回复)→ 走 _decide_continuation,默认 end_turn;finish_reason=="length"max_tokens_exceeded:2000)。
  • 有 tool call → 默认 continue;is_terminal_tool → stop(tool_rule);is_final_step 硬停 max_steps;required-before-exit 未调齐则继续(:2003-2034)。

停止原因是完整枚举 StopReasonType:end_turn / max_steps / tool_rule / requires_approval / cancelled / insufficient_credits / context_window_overflow_in_system_prompt / invalid_tool_call / invalid_llm_response / llm_api_error / max_tokens_exceeded。每轮末尾并行触发 _check_credits():390),做余额闸门(云计费)。

记忆与上下文管理(压缩、长期记忆、会话持久化)

这是 Letta 的核心。三层记忆是经典 MemGPT 结构,代码里逐一对应:

  • Core memory(核心记忆,常驻 in-context)Memory/Blockschemas/memory.py)。Memory.compile():688)把每个 Block 渲染成 <memory_blocks>:149/:177),块有 label / description / value / size limit / read_only:162)。Block 是一等公民——嵌在系统提示里恒常可见。
  • Recall memory(会话历史/召回):即消息历史,message_manager.list_messages_for_agent(...),工具 conversation_searchfunction_sets/base.py:87)做 hybrid(文本 + 语义)检索。系统提示元数据行会告知 “N previous messages stored in recall memory”(prompt_generator.py:74)。
  • Archival memory(长期归档,向量库)archival_memory_insert/archival_memory_searchbase.py:164/:194,带 tags + tag_match_mode any/all + 时间过滤 + top_k)。底层 passage_manager.pyget_openai_embedding_async:35)生成 embedding 写 pgvector(pad 到 MAX_EMBEDDING_DIM:148-159),亦支持 Turbopuffer/Pinecone。系统提示元数据行告知归档条数 + 可用 tags(prompt_generator.py:78-85)。

上下文压缩/驱逐services/summarizer/summarizer.pySummarizer:36)两种模式:partial_evict(默认,_partial_evict_buffer_summarization:136,保留最近 1 - partial_evict_summarizer_percentage(默认 0.30)的消息,其余总结)与 trim 静态缓冲(message_buffer_limit=10message_buffer_min=3,超限驱逐到只留 min,:257-288)。驱逐的旧消息交给后台 summarizer 生成总结。触发阈值在 thresholds.py:get_compaction_trigger_threshold。压缩产出 CompactionStats/SummaryMessageletta_agent_v3.py:818/:848)。单条 tool return 也有动态截断上限 _compute_tool_return_truncation_chars:143,约 20% 上下文窗 × 4 字符,下限 5k)。

会话持久化/隔离:支持一个 agent 多个并行 conversation(conversation_id),ConversationManager.apply_isolated_blocks_to_agent_state:264)做 per-conversation 的 block override。

MemFS(git-backed 记忆)services/memory_repo/git_operations.py/block_markdown.py)+ block_manager_git.pyGitEnabledBlockManager,tag git-memory-enabled:26-36:写 git 优先作 source of truth,再同步 Postgres,保留完整版本历史)。官方 docs 称之为 MemFS / context repository:记忆块投影成带 YAML frontmatter 的 markdown 文件、git 版本化,system/ 目录内容每轮必进系统提示,目录外仅按需加载。

工具体系(定义/调用协议/注册/权限)

  • 定义:Python 函数 + Google 风格 docstring,schema_generator.py:validate_google_style_docstring:15)校验后自动生成 OpenAI tool JSON schema——docstring 就是契约源。
  • 内置工具集 function_sets/base.py(记忆工具 + send_message + conversation_search)、builtin.pyfiles.pymulti_agent.pyvoice.py。注意很多 base 工具体是 raise NotImplementedError(如 memory/archival_*:68/:191)——真正执行在 executor 层。
  • 执行器路由ToolExecutorFactory._executor_maptool_execution_manager.py:35-43)按 ToolType 分发:LETTA_CORE/LETTA_MEMORY_CORE/LETTA_SLEEPTIME_CORELettaCoreToolExecutorLETTA_BUILTINLettaBuiltinToolExecutorLETTA_FILES_CORELettaFileToolExecutorEXTERNAL_MCPExternalMCPToolExecutorLETTA_MULTI_AGENT_CORE 及默认(自定义/用户工具)→ SandboxToolExecutor:57)。默认走沙箱是安全设计的关键。
  • 调用协议:标准 OpenAI tool_call;V3 剥离了 heartbeat/inner_thoughts kwargs(执行前 args.pop(REQUEST_HEARTBEAT_PARAM)/pop(INNER_THOUGHTS_KWARG):1776)。支持并行 tool call(_run_one + 按并行能力分组,:1822/:1842)。
  • 权限/门控:见「安全与权限」(tool rules + requires_approval + client-side tools)。
  • MCP:见「Skill / 插件体系」。

Prompt 设计(系统提示结构、动态组装)

  • 静态骨架system_prompts/letta_v1.pyPROMPT<base_instructions>,含 <memory>/<file_system> 说明;开头自称 “helpful self-improving agent”,结尾明确 loop 协议,源码已核对)。仓库另有多套骨架:memgpt_chat/memgpt_v2_chat/react/voice_chat/sleeptime_v2/workflow
  • 动态组装prompt_generator.pycompile_system_message_async:181)= 系统提示模板 + in_context_memory.compile()(渲染 memory blocks/directories/skills)+ compile_memory_metadata_block:26,注入”系统提示上次重编译时间 / recall 消息数 / 归档条数 / 可用 tags”)+ tool_rules_solver 的 compile_tool_rule_prompts():200,把工具约束写进提示)。用 safe_format:92,容错 KeyError 的 __missing__)做变量替换。
  • 记忆块渲染成 <memory_blocks>、文件系统渲染成 <directories>、skills 渲染成 <available_skills>(均在 schemas/memory.py)。

Router / 编排(任务分解、多 agent、子 agent)

  • 多 agent groups letta/groups/round_robin_multi_agent.pysupervisor_multi_agent.pydynamic_multi_agent.pysleeptime_multi_agent_v{1..4}.py,对应 ManagerType(round_robin / supervisor / dynamic / sleeptime)。
  • 工具级编排 = Tool Ruleshelpers/tool_rule_solver.py + schemas/tool_rule.py):一套声明式 DSL 约束工具调用图——ToolRuleTypeconstrain_child_tools(父→子)、parent_last_toolconditional(按返回值路由)、run_first(init)、exit_loop(终止工具)、continue_looprequired_before_exitmax_count_per_steprequires_approvalToolRulesSolver:24)在每步算 valid tools、should_force_tool_callis_terminal_toolget_uncalled_required_tools。这是 Letta 的核心编排/状态机手段,比多 agent 更常用。
  • 子 agent:sleeptime 子 agent(见「自进化能力」)。docs 侧新 Letta Agent 有 subagents/goal-mode,但那属于 letta-code 仓库;本仓库以 groups + tool rules 为主。

Skill / 插件体系

  • Skills = 存进记忆的 memFS 块Memory.compile_available_skillsschemas/memory.py:483)扫描 label 以 skills/ 开头的 block(如 skills/<name>skills/<name>/SKILL),渲染成 <available_skills> 目录树,location = ${MEMORY_DIR}/skills/<name>/SKILL.md。docs 证实 “skills 随 agent 走、与记忆仓库一起 git 版本化”。这与其他 harness 把 skill 当磁盘文件不同——Letta 的 skill 就是记忆的一部分。
  • Client-side skills:请求可携带 ClientSkillSchemaletta_agent_v3.py:136self.client_skills),合并进系统提示(与 agent-scoped skills 去重)。
  • Plugin 系统letta/plugins/plugins.py/defaults.py/README)——可插拔组件(如自定义 provider/行为),较轻量。
  • 工具即插件:MCP server(services/mcp/ + functions/mcp_client/,支持 stdio/SSE/streamable-http/fastmcp + OAuth)、Composio 集成(functions/async_composio_toolset.py)。

自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)

这是 Letta 记忆维度的亮点。

  • **Sleeptime / “dreaming”(睡眠时计算)**是核心自进化机制。groups/sleeptime_multi_agent_v4.py:前台 agent step() 正常回复后,run_sleeptime_agents():132)在后台异步(safe_create_task/_issue_background_task:171)派发一个或多个 sleeptime 子 agent(group.agent_ids),把前台最新 response 喂给它们,让它们编辑记忆块(整理/去重/提炼 lessons)。频率门控 sleeptime_agent_frequency(每 N 轮触发一次,:143-146),bump_turns_counter_async 计数,get_last_processed_message_id 断点续处理(:151)。
  • 记忆自编辑工具(sleeptime/主 agent 共用):rethink_memorybase.py:283,重写整块)、memory_replace/memory_insert/memory_apply_patch/memory_rethink/memory_finish_edits:311-520,行号感知的 patch 式编辑,参考 Anthropic computer-use edit tool)。
  • 记忆去碎片化 / doctor(docs):可让 agent 重组记忆,subagent 用 git worktree 并发写记忆不阻塞主 agent。
  • eval 驱动纠错services/step_manager.py 有 feedback(FeedbackTypeadd_feedback_async 给每个 step 打 positive/negative,:269);docs 有 Letta Evals 体系。系统提示自称 “self-improving agent”(letta_v1.py)。RL 见「轨迹利用」。

可观测性(日志 / trace 格式)

  • OpenTelemetryletta/otel/tracing.py(OTLP gRPC span exporter,@trace_method 装饰器遍布 agent/executor;FastAPI 路由级 span,:44-61)。另有 otel/metrics.pymetric_registry.pydb_pool_monitoring.pysqlalchemy_instrumentation.py
  • LLM/provider traceservices/llm_trace_writer.pyLLMTraceWriter,把每次 LLM 请求/响应写 ClickHouse,:57/:117to_clickhouse_row)+ llm_trace_reader.py + clickhouse_otel_traces.py/clickhouse_provider_traces.py。启用条件 clickhouse_endpoint && clickhouse_password
  • Step 级指标step_manager.py 记录每步(log_step_async :181record_step_metrics_async :562、错误类型 :383),支持按 feedback 过滤。schema 为 StepMetrics/StepProgression

安全与权限(审批门、密钥管理)

  • 审批门(human-in-the-loop)requires_approval tool rule(schemas/tool_rule.py:353 RequiresApprovalToolRule)。_handle_ai_responseletta_agent_v3.py:1682-1709):若某 tool call is_requires_approval_tool 或是 client-side 工具 → 生成 approval request 消息、停机并返回 StopReasonType.requires_approval,等外部批准;被拒则 create_tool_returns_for_denials:1756)把拒绝理由作为 tool return 回灌。
  • 工具规则闸门:valid_tools 白名单,越界即 _build_rule_violation_result:1826),max_count_per_step 限频。
  • 密钥/凭证services/sandbox_credentials_service.pySandboxCredentialsService,从 STEP_ORCHESTRATOR_ENDPOINT webhook 拉沙箱凭证,Bearer STEP_COMPLETE_KEY:16-57);sandbox_config_manager.py 管沙箱 env vars(base.py:_gather_env_vars :476)。沙箱内 agent_id 只通过 LETTA_AGENT_ID env 暴露(tool_sandbox/base.py:75),不直传对象。仓库根有 AI_POLICY.md/SECURITY.md/PRIVACY.md

沙箱与执行隔离

  • 自定义/用户工具默认走 SandboxToolExecutor(见「工具体系」路由)。沙箱后端(services/tool_sandbox/)三选一:LocalSandbox(本地子进程/venv)、E2Be2b_sandbox.py,云沙箱)、Modalmodal_sandbox.py/modal_sandbox_v2.py + modal_deployment_manager.py + modal_version_manager.py,serverless 容器)。
  • AsyncToolSandboxBasebase.py:24):generate_execution_script:126)把工具代码渲染成隔离执行脚本,支持 Python 与 TypeScript 工具(is_typescript_tool :119_generate_typescript_execution_script :390typescript_generator.py);_gather_env_vars:476)注入 env;pydantic 结果包装 + markers 解析 stdout(_render_sandbox_code :177)。safe_pickle.py 做安全反序列化。
  • 每 agent 可配 SandboxConfigsandbox_config_manager.py):pip 依赖、env、force_recreate 等。

与模型的协同设计

  • 模型无关(README:fully model-agnostic)。llm_api/(各 provider client)+ services/llm_router/get_llm_routing_clientletta_agent_v3.py:70)+ model_specs/ + model_aliases.py + provider_manager.py(含 AUTO_MODE_HANDLES 自动选型)。
  • 多套 adapter 抽象 LLM 交互:SimpleLLMRequestAdapter/SimpleLLMStreamAdapter(阻塞/流式)、LettaLLMRequestAdapterSGLangNativeAdapter(按 handle 选择,letta_agent_v3.py:299-325)。
  • 本地/开源模型letta/local_llm/(含 INNER_THOUGHTS_KWARG 等本地模型适配常量);仓库带 docker-compose-vllm.yaml
  • 推理协议协同SGLangNativeAdapteradapters/sglang_native_adapter.py)为多轮 RL 直接用模型 chat template 拿 token ids + per-token logprob(_messages_to_input_idsapply_chat_template:72;含 GLM4.7 tool-call 解析 _parse_glm47_tool_calls :181),说明训练/推理栈是协同设计的。V3 类 docstring 注明 “No inner thoughts in kwargs” 正是为对齐现代 native tool-calling 模型。

轨迹利用(session/trajectory 是否反哺训练/评测)

  • 明确支持 RL 训练letta_agent_v3.py 状态里 self.logprobs(注释 “for RL training”,:138)、self.turns: list[TurnTokenData](“Multi-turn token tracking for RL training, accumulated across all LLM calls”,:140)、self.return_token_ids:141)。当 llm_config.return_token_ids 且 handle 以 sglang/ 开头或 provider 含 sglang(含训练用 slime-sglang)时切到 SGLangNativeAdapter:289-313),产出 token 级轨迹供 loss masking。
  • step/trajectory 持久化:每 step 落库(step_manager.py),带 feedback 标注,可用于离线评测/偏好数据。
  • Evals(docs):Letta Evals 体系(fern/docs guides/evals);step feedback 是评测/纠错信号来源。
  • 结论:轨迹既反哺训练(多轮 RL,token-id 级)也反哺评测(step feedback + evals),是本次调研中少见地把 harness 与 RL 训练闭环打通的样本。

与同类 harness 的关键差异(1-3 条)

  1. 记忆是一等公民,且分层 + 可自编辑 + git 版本化:core block 常驻 in-context、archival 向量库、recall 会话检索三层齐备,配 sleeptime 后台 agent 主动整理记忆(“dreaming”)——大多数 coding harness 只有会话历史 + 文件系统,没有这套主动学习型记忆。
  2. 用 Tool Rules 声明式状态机替代 heartbeat/ReAct 硬编码:V3 明确弃用 heartbeat,靠 tool-rule solver(9 种规则含 conditional/terminal/required_before_exit)在每步动态算 valid tools 与停/续,把编排逻辑从 prompt 挪到可验证的 DSL。
  3. 原生打通多轮 RLSGLangNativeAdapter 直接吐 token-id + per-token logprob + turns 轨迹供 loss masking,同时 step feedback 反哺 evals——同类 harness 里少见把训练与评测闭环都做进服务端的。

原始源码定位

  • repo: https://github.com/letta-ai/letta
  • commit/version analyzed: b76da9092518cbaa2d09042e52fdcbde69243e18(2026-07-03,克隆日期 2026-07-11)
  • 关键文件列表(相对仓库根):
    • letta/agents/agent_loop.py
    • letta/agents/letta_agent_v3.py(主 loop,2134 行)
    • letta/agents/letta_agent_v2.py
    • letta/functions/function_sets/base.py(记忆工具集)
    • letta/functions/schema_generator.py
    • letta/prompts/system_prompts/letta_v1.py
    • letta/prompts/prompt_generator.py
    • letta/schemas/memory.py
    • letta/schemas/tool_rule.py
    • letta/helpers/tool_rule_solver.py
    • letta/services/summarizer/summarizer.py(+ compact.py/thresholds.py
    • letta/groups/sleeptime_multi_agent_v4.py
    • letta/services/tool_executor/tool_execution_manager.py
    • letta/services/tool_sandbox/{base,local_sandbox,e2b_sandbox,modal_sandbox}.py
    • letta/services/sandbox_credentials_service.py
    • letta/adapters/sglang_native_adapter.py
    • letta/services/{passage_manager,message_manager,archive_manager,block_manager_git}.py
    • letta/services/memory_repo/git_operations.py/block_markdown.py
    • letta/services/{llm_trace_writer,step_manager}.py + letta/otel/tracing.py

一手源存档(sources/)

存放于 /Users/zhao/projects/self-wiki/ai-research/sources/harness/letta/

  • NOTES.md — 第一阶段 12 维度全笔记(带行号,dossier 唯一输入)
  • src/(13 个核心源文件留档,约 336K):
    • agent_loop.py
    • letta_agent_v3.py
    • function_sets_base.py
    • schemas_memory.py
    • schemas_tool_rule.py
    • tool_rule_solver.py
    • prompt_generator.py
    • system_prompt_letta_v1.py
    • summarizer.py
    • sleeptime_multi_agent_v4.py
    • tool_execution_manager.py
    • tool_sandbox_base.py
    • sglang_native_adapter.py