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 schemaletta/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— 工具规则编排 DSLletta/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_agent → LettaAgentV3;开启 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/Block(schemas/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_search(function_sets/base.py:87)做 hybrid(文本 + 语义)检索。系统提示元数据行会告知 “N previous messages stored in recall memory”(prompt_generator.py:74)。 - Archival memory(长期归档,向量库):
archival_memory_insert/archival_memory_search(base.py:164/:194,带 tags + tag_match_mode any/all + 时间过滤 + top_k)。底层passage_manager.py:get_openai_embedding_async(:35)生成 embedding 写 pgvector(pad 到MAX_EMBEDDING_DIM,:148-159),亦支持 Turbopuffer/Pinecone。系统提示元数据行告知归档条数 + 可用 tags(prompt_generator.py:78-85)。
上下文压缩/驱逐在 services/summarizer/summarizer.py。Summarizer(:36)两种模式:partial_evict(默认,_partial_evict_buffer_summarization,:136,保留最近 1 - partial_evict_summarizer_percentage(默认 0.30)的消息,其余总结)与 trim 静态缓冲(message_buffer_limit=10、message_buffer_min=3,超限驱逐到只留 min,:257-288)。驱逐的旧消息交给后台 summarizer 生成总结。触发阈值在 thresholds.py:get_compaction_trigger_threshold。压缩产出 CompactionStats/SummaryMessage(letta_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.py(GitEnabledBlockManager,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.py、files.py、multi_agent.py、voice.py。注意很多 base 工具体是raise NotImplementedError(如memory/archival_*,:68/:191)——真正执行在 executor 层。 - 执行器路由:
ToolExecutorFactory._executor_map(tool_execution_manager.py:35-43)按ToolType分发:LETTA_CORE/LETTA_MEMORY_CORE/LETTA_SLEEPTIME_CORE→LettaCoreToolExecutor;LETTA_BUILTIN→LettaBuiltinToolExecutor;LETTA_FILES_CORE→LettaFileToolExecutor;EXTERNAL_MCP→ExternalMCPToolExecutor;LETTA_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.py的PROMPT(<base_instructions>,含<memory>/<file_system>说明;开头自称 “helpful self-improving agent”,结尾明确 loop 协议,源码已核对)。仓库另有多套骨架:memgpt_chat/memgpt_v2_chat/react/voice_chat/sleeptime_v2/workflow。 - 动态组装:
prompt_generator.py。compile_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.py、supervisor_multi_agent.py、dynamic_multi_agent.py、sleeptime_multi_agent_v{1..4}.py,对应ManagerType(round_robin / supervisor / dynamic / sleeptime)。 - 工具级编排 = Tool Rules(
helpers/tool_rule_solver.py+schemas/tool_rule.py):一套声明式 DSL 约束工具调用图——ToolRuleType含constrain_child_tools(父→子)、parent_last_tool、conditional(按返回值路由)、run_first(init)、exit_loop(终止工具)、continue_loop、required_before_exit、max_count_per_step、requires_approval。ToolRulesSolver(:24)在每步算 valid tools、should_force_tool_call、is_terminal_tool、get_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_skills(schemas/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:请求可携带
ClientSkillSchema(letta_agent_v3.py:136的self.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:前台 agentstep()正常回复后,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_memory(base.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(FeedbackType,add_feedback_async给每个 step 打 positive/negative,:269);docs 有 Letta Evals 体系。系统提示自称 “self-improving agent”(letta_v1.py)。RL 见「轨迹利用」。
可观测性(日志 / trace 格式)
- OpenTelemetry:
letta/otel/tracing.py(OTLP gRPC span exporter,@trace_method装饰器遍布 agent/executor;FastAPI 路由级 span,:44-61)。另有otel/metrics.py、metric_registry.py、db_pool_monitoring.py、sqlalchemy_instrumentation.py。 - LLM/provider trace:
services/llm_trace_writer.py(LLMTraceWriter,把每次 LLM 请求/响应写 ClickHouse,:57/:117,to_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:181、record_step_metrics_async:562、错误类型:383),支持按 feedback 过滤。schema 为StepMetrics/StepProgression。
安全与权限(审批门、密钥管理)
- 审批门(human-in-the-loop):
requires_approvaltool rule(schemas/tool_rule.py:353RequiresApprovalToolRule)。_handle_ai_response(letta_agent_v3.py:1682-1709):若某 tool callis_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.py(SandboxCredentialsService,从STEP_ORCHESTRATOR_ENDPOINTwebhook 拉沙箱凭证,BearerSTEP_COMPLETE_KEY,:16-57);sandbox_config_manager.py管沙箱 env vars(base.py:_gather_env_vars:476)。沙箱内 agent_id 只通过LETTA_AGENT_IDenv 暴露(tool_sandbox/base.py:75),不直传对象。仓库根有AI_POLICY.md/SECURITY.md/PRIVACY.md。
沙箱与执行隔离
- 自定义/用户工具默认走
SandboxToolExecutor(见「工具体系」路由)。沙箱后端(services/tool_sandbox/)三选一:LocalSandbox(本地子进程/venv)、E2B(e2b_sandbox.py,云沙箱)、Modal(modal_sandbox.py/modal_sandbox_v2.py+modal_deployment_manager.py+modal_version_manager.py,serverless 容器)。 AsyncToolSandboxBase(base.py:24):generate_execution_script(:126)把工具代码渲染成隔离执行脚本,支持 Python 与 TypeScript 工具(is_typescript_tool:119、_generate_typescript_execution_script:390、typescript_generator.py);_gather_env_vars(:476)注入 env;pydantic 结果包装 + markers 解析 stdout(_render_sandbox_code:177)。safe_pickle.py做安全反序列化。- 每 agent 可配
SandboxConfig(sandbox_config_manager.py):pip 依赖、env、force_recreate 等。
与模型的协同设计
- 模型无关(README:fully model-agnostic)。
llm_api/(各 provider client)+services/llm_router/(get_llm_routing_client,letta_agent_v3.py:70)+model_specs/+model_aliases.py+provider_manager.py(含AUTO_MODE_HANDLES自动选型)。 - 多套 adapter 抽象 LLM 交互:
SimpleLLMRequestAdapter/SimpleLLMStreamAdapter(阻塞/流式)、LettaLLMRequestAdapter、SGLangNativeAdapter(按 handle 选择,letta_agent_v3.py:299-325)。 - 本地/开源模型:
letta/local_llm/(含INNER_THOUGHTS_KWARG等本地模型适配常量);仓库带docker-compose-vllm.yaml。 - 推理协议协同:
SGLangNativeAdapter(adapters/sglang_native_adapter.py)为多轮 RL 直接用模型 chat template 拿 token ids + per-token logprob(_messages_to_input_ids走apply_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/docsguides/evals);step feedback 是评测/纠错信号来源。 - 结论:轨迹既反哺训练(多轮 RL,token-id 级)也反哺评测(step feedback + evals),是本次调研中少见地把 harness 与 RL 训练闭环打通的样本。
与同类 harness 的关键差异(1-3 条)
- 记忆是一等公民,且分层 + 可自编辑 + git 版本化:core block 常驻 in-context、archival 向量库、recall 会话检索三层齐备,配 sleeptime 后台 agent 主动整理记忆(“dreaming”)——大多数 coding harness 只有会话历史 + 文件系统,没有这套主动学习型记忆。
- 用 Tool Rules 声明式状态机替代 heartbeat/ReAct 硬编码:V3 明确弃用 heartbeat,靠 tool-rule solver(9 种规则含 conditional/terminal/required_before_exit)在每步动态算 valid tools 与停/续,把编排逻辑从 prompt 挪到可验证的 DSL。
- 原生打通多轮 RL:
SGLangNativeAdapter直接吐 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.pyletta/agents/letta_agent_v3.py(主 loop,2134 行)letta/agents/letta_agent_v2.pyletta/functions/function_sets/base.py(记忆工具集)letta/functions/schema_generator.pyletta/prompts/system_prompts/letta_v1.pyletta/prompts/prompt_generator.pyletta/schemas/memory.pyletta/schemas/tool_rule.pyletta/helpers/tool_rule_solver.pyletta/services/summarizer/summarizer.py(+compact.py/thresholds.py)letta/groups/sleeptime_multi_agent_v4.pyletta/services/tool_executor/tool_execution_manager.pyletta/services/tool_sandbox/{base,local_sandbox,e2b_sandbox,modal_sandbox}.pyletta/services/sandbox_credentials_service.pyletta/adapters/sglang_native_adapter.pyletta/services/{passage_manager,message_manager,archive_manager,block_manager_git}.pyletta/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.pyletta_agent_v3.pyfunction_sets_base.pyschemas_memory.pyschemas_tool_rule.pytool_rule_solver.pyprompt_generator.pysystem_prompt_letta_v1.pysummarizer.pysleeptime_multi_agent_v4.pytool_execution_manager.pytool_sandbox_base.pysglang_native_adapter.py