工作原理

了解 Letta Code 的构建方式和自定义方法

本页面面向希望了解内部原理、为 Letta Code 做出贡献或使用 Letta SDK 构建自己的代理工具的开发者。

Letta Code 是一个围绕 Letta TypeScript SDK 构建的轻量级 CLI 工具

它让 Letta 代理(运行在服务器上,本地或远程)能够与您的本地开发环境交互。

架构概述

┌─────────────────────────────────────────────────────────────┐
│                        您的终端                              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    Letta Code                        │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────────────┐   │   │
│  │  │ CLI UI / │  │  工具    │  │   权限管理器     │   │   │
│  │  │ Headless │  │  执行器  │  │                  │   │   │
│  │  └────┬─────┘  └────┬─────┘  └────────┬─────────┘   │   │
│  │       │             │                 │             │   │
│  │       └─────────────┴─────────────────┘             │   │
│  │                      │                              │   │
│  │               ┌──────┴──────┐                       │   │
│  │               │ Letta TS SDK│                       │   │
│  │               └──────┬──────┘                       │   │
│  └──────────────────────┼──────────────────────────────┘   │
└─────────────────────────┼──────────────────────────────────┘
                          │
                          │ Letta API
                          │
                    ┌─────┴─────┐
                    │  Letta    │
                    │  服务器   │
                    └───────────┘

Letta Code 的主要工作是:

  1. 管理消息生命周期 - 在用户和代理之间发送消息
  2. 本地执行工具 - 在您的机器上运行 Bash、Read、Write、Edit 等
  3. 处理权限 - 在工具执行前提示用户批准
  4. 提供终端 UI - 渲染代理状态、流式响应和工具调用

客户端工具执行

让 Letta Code 工作的核心机制是客户端工具执行。您的 Letta 代理运行在外部服务器上,但它调用的工具——如 BashReadWrite——在您的机器上本地执行。

这是通过 Letta API 的 客户端工具 功能实现的:

  1. 代理请求工具 - 代理决定调用 Bash(ls -la)
  2. 服务器暂停代理执行等待批准 - 请求发送到您的终端
  3. Letta Code 本地执行 - 命令在您的机器上运行
  4. 结果返回 - 输出返回给代理继续
// 简化版:Letta Code 如何处理工具执行
const response = await client.agents.messages.create(agentId, {
  messages: [{ role: "user", content: userInput }],
});

for (const msg of response.messages) {
  if (msg.message_type === "approval_request_message") {
    // 本地执行工具
    const result = await executeToolLocally(msg.tool_call);

    // 将结果发送回代理
    await client.agents.messages.create(agentId, {
      messages: [{
        type: "approval",
        approvals: [{
          type: "tool",
          tool_call_id: msg.tool_call.tool_call_id,
          tool_return: result,
          status: "success",
        }],
      }],
    });
  }
}

流式传输

Letta Code 使用 SDK 的 流式 API 实时显示推理、消息和工具调用。

const stream = await client.agents.messages.stream(agentId, {
  messages: [{ role: "user", content: userInput }],
  stream_tokens: true,
});

for await (const chunk of stream) {
  if (chunk.message_type === "reasoning_message") {
    process.stdout.write(chunk.reasoning);
  } else if (chunk.message_type === "assistant_message") {
    process.stdout.write(chunk.content);
  }
}

后台模式流式传输

由于编程代理通常是长时间运行的,Letta Code 使用 后台模式流式传输

这将代理执行与客户端连接解耦,允许:

  • 可恢复的流 - 如果您的连接断开,您可以重新连接并从断开的地方继续
  • 崩溃恢复 - 即使您的终端关闭,代理也会在服务器上继续处理
  • 长时间操作 - 耗时 10+ 分钟的任务不会超时
// 后台模式在服务器端持久化流
const stream = await client.agents.messages.stream(agentId, {
  messages: [{ role: "user", content: userInput }],
  stream_tokens: true,
  background: true,  // 启用后台模式
});

// 每个块包含 run_id 和 seq_id 用于恢复
let runId, lastSeqId;
for await (const chunk of stream) {
  if (chunk.run_id && chunk.seq_id) {
    runId = chunk.run_id;
    lastSeqId = chunk.seq_id;
  }
  // 处理块...
}

// 如果断开连接,从最后位置恢复
for await (const chunk of client.runs.stream(runId, {
  starting_after: lastSeqId,
})) {
  // 继续处理...
}

对话

Letta Code 将消息线程组织为对话。单个代理可以同时运行多个对话——所有对话共享相同的记忆块和可搜索的消息历史。

这让您可以同时运行多个编程会话(一个重构您的 API,另一个编写测试),具有独立的上下文窗口但共享知识。来自所有对话的消息汇集在一起并可搜索,因此您的代理可以回忆任何过去会话的上下文。

默认情况下,启动 letta 会恢复与您上次使用的代理的"默认"对话。使用 --new 为并行会话开始新对话,--continue 完全恢复您上次的会话,--resume 交互式浏览过去的对话,或在会话期间使用 /resume 在对话之间切换。

您的 Letta Code 代理是通用 Letta 代理

重要的一点:Letta Code 创建的代理是通用 Letta 代理

这意味着它们可以通过以下方式完全访问:

  • Letta API - 使用 PythonTypeScript SDK 或任何 REST 端点来修改/访问/消息它们
  • ADE - 在 app.letta.com 查看和交互
  • 其他客户端 - 在 Letta API 之上构建自己的界面(例如使用 Vercel AI SDK

Letta Code 只是将一组专注于编程的工具和提示附加到您的代理,并提供终端界面与它们交互。

代理本身,包括它们的记忆和对话历史,存在于 Letta 服务器上。

这意味着您可以:

  • 在 Letta Code 中开始会话,然后在 ADE 中继续
  • 使用 API 以编程方式与您的编程代理交互
  • 构建自定义 UI(例如仪表板)来查看您的 Letta Code 代理,即使您不在终端前

下一步