连接 Buda ACP
按步骤把 Zed、JetBrains 或你自己的程序连接到托管在 Buda 云端的智能体。
通过 Agent Client Protocol(ACP),你可以在 Zed、JetBrains 或自己的程序里,直接与一个托管在 Buda 云端的智能体对话。回复、思考过程和工具调用会通过标准 ACP 事件流式返回,不需要在本机运行智能体或模型。
完成接入后,你将得到这条链路:
Zed / JetBrains / 你的程序
│ ACP
▼
wss://buda.im/api/acp?agentId=...
│
▼
Buda 智能体 → 云端沙箱 → 已连接的知识库与集成Buda 智能体运行在云端沙箱中,不会自动读取你编辑器当前打开的本地目录。要让它处理代码仓库,请先为该智能体连接 GitHub,或把所需内容放进它能访问的知识库与集成中。
选择接入方式
| 你的场景 | 推荐方式 | 是否需要桥接 |
|---|---|---|
| 在 Zed 中使用 | acpremote + Zed 自定义智能体 | 需要 |
| 在 JetBrains AI Chat 中使用 | acpremote + ~/.jetbrains/acp.json | 需要 |
| Node.js、脚本或 CI | @agentclientprotocol/sdk 直连 WebSocket | 不需要 |
| 其他支持远程 WebSocket 和自定义请求头的 ACP 客户端 | 直接连接 Buda 端点 | 不需要 |
| 浏览器前端 | 不建议直接连接 | 浏览器 WebSocket 不能发送 Authorization 请求头 |
Zed 和 JetBrains 的自定义 ACP 配置会启动一个本地 command,而 Buda 提供的是远程 WebSocket 端点。因此编辑器场景需要一个很小的 stdio ↔ WebSocket 桥接程序。本文使用第三方开源工具 acpremote;它只转发 ACP 消息,不在本机运行 Buda 智能体。
开始之前
准备以下内容:
- 一个你有权访问的 Buda 智能体;
- 该智能体的
agentId; - 一个以
sk_开头的 Buda API 密钥; - 如果使用编辑器:本机已安装 Python,并能运行
acpremote。
当前 ACP 连接会自动批准智能体发起的工具调用,不会弹出逐次权限确认。请只连接你信任的仓库、知识库和外部系统,并为测试与生产使用不同的 API 密钥。
第 1 步:获取智能体 ID
打开要连接的智能体。浏览器地址通常形如:
https://buda.im/agents/your_agent_id/agents/ 后面的值就是 agentId。如果你通过 API 创建智能体,也可以直接使用创建接口响应中的 id。
例如:
export BUDA_AGENT_ID="your_agent_id"一条 ACP 连接只绑定一个智能体。要连接另一个智能体,请使用另一个 agentId 建立新连接。
第 2 步:创建 API 密钥
打开「设置 → API 密钥」
在 Buda 控制台中进入 设置 → API 密钥,选择 新建密钥。
为用途命名并设置有效期
例如命名为 zed-acp、jetbrains-acp 或 ci-acp。测试时优先选择较短有效期。
立即复制完整密钥
完整的 sk_... 只显示一次。把它保存到密码管理器或密钥存储中。
先用 REST API 验证密钥是否有效:
export BUDA_API_KEY="sk_your_api_key"
curl https://buda.im/api/v1/users/me \
-H "Authorization: Bearer $BUDA_API_KEY"返回当前用户信息后,再继续配置 ACP。若返回 401 Unauthorized,请先重新创建或更换密钥。
第 3 步:组成 ACP 端点
Buda ACP 的连接参数如下:
| 配置项 | 值 |
|---|---|
| WebSocket 端点 | wss://buda.im/api/acp?agentId=<agentId> |
| 认证请求头 | Authorization: Bearer sk_... |
| 传输方式 | WebSocket |
| 一个连接可驱动的智能体 | 1 个 |
组成你的完整 URL:
export BUDA_ACP_URL="wss://buda.im/api/acp?agentId=$BUDA_AGENT_ID"API 密钥必须属于一个有权访问该智能体的 Buda 用户。密钥无效、agentId 不存在,或密钥所有者无权访问该智能体时,initialize 会失败,连接随后关闭。
第 4 步:连接编辑器
安装桥接程序
推荐把 acpremote 安装成独立命令:
uv tool install acpremote没有 uv 时也可以使用 Python:
python -m pip install --user acpremote确认编辑器能够找到该命令:
command -v acpremote
acpremote --help记下 command -v acpremote 输出的绝对路径。图形界面启动的编辑器可能没有与你的终端相同的 PATH,使用绝对路径最可靠。
Zed
在 Zed 中打开 Agent Settings → External Agents → Add Agent → Add Custom Agent,然后填写 settings.json:
{
"agent_servers": {
"Buda": {
"type": "custom",
"command": "/absolute/path/to/acpremote",
"args": [
"mirror",
"wss://buda.im/api/acp?agentId=your_agent_id",
"--token-env",
"BUDA_API_KEY"
],
"env": {
"BUDA_API_KEY": "sk_your_api_key"
}
}
}
}保存后,在 Agent Panel 中新建一个 Buda 会话,并发送:
只回复:Buda ACP connected看到流式回复即表示连接成功。若没有出现 Buda 智能体,重启 Zed,并检查 command 是否为真实存在的绝对路径。
JetBrains
在 AI Chat 中选择 Add Custom Agent。JetBrains 会创建并打开 ~/.jetbrains/acp.json:
{
"default_mcp_settings": {},
"agent_servers": {
"Buda": {
"command": "/absolute/path/to/acpremote",
"args": [
"mirror",
"wss://buda.im/api/acp?agentId=your_agent_id",
"--token-env",
"BUDA_API_KEY"
],
"env": {
"BUDA_API_KEY": "sk_your_api_key"
}
}
}
}保存文件后,在 AI Chat 的智能体选择器中选择 Buda,新建会话并发送一条测试消息。
上面的最短配置会把 API 密钥保存在编辑器的本地配置文件中。不要把该文件同步到公开仓库;限制文件读取权限,并在不再使用时删除或轮换密钥。团队环境建议为每位成员、每个环境分别创建密钥。
其他编辑器
如果编辑器的自定义 ACP 配置同样接受 command 和 args,使用相同模式:让编辑器启动下面这条本地命令。
BUDA_API_KEY="sk_your_api_key" acpremote mirror \
"wss://buda.im/api/acp?agentId=your_agent_id" \
--token-env BUDA_API_KEY如果客户端原生支持远程 ACP WebSocket,并且能在握手时发送自定义 Authorization 请求头,则可跳过 acpremote,直接连接 Buda。
第 5 步:从 Node.js 或 CI 直连
程序化客户端不需要 stdio 桥接。安装 ACP SDK 与 Node WebSocket 实现:
npm install @agentclientprotocol/sdk ws创建 buda-acp.mjs:
import * as acp from "@agentclientprotocol/sdk";
import { createWebSocketStream } from "@agentclientprotocol/sdk/experimental/ws-client";
import WebSocket from "ws";
const apiKey = process.env.BUDA_API_KEY;
const agentId = process.env.BUDA_AGENT_ID;
if (!apiKey || !agentId) {
throw new Error("Set BUDA_API_KEY and BUDA_AGENT_ID first.");
}
const stream = createWebSocketStream(
`wss://buda.im/api/acp?agentId=${encodeURIComponent(agentId)}`,
{
WebSocket,
headers: {
Authorization: `Bearer ${apiKey}`,
},
},
);
const client = acp
.client({ name: "buda-acp-quickstart" })
.onNotification(acp.methods.client.session.update, ({ params }) => {
const update = params.update;
if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
process.stdout.write(update.content.text);
}
});
const result = await client.connectWith(stream, async (connection) => {
const initialized = await connection.request(acp.methods.agent.initialize, {
protocolVersion: acp.PROTOCOL_VERSION,
clientCapabilities: {},
});
const session = await connection.request(acp.methods.agent.session.new, {
cwd: process.cwd(),
mcpServers: [],
});
const response = await connection.request(acp.methods.agent.session.prompt, {
sessionId: session.sessionId,
prompt: [{ type: "text", text: "只回复:Buda ACP connected" }],
});
return {
sessionId: session.sessionId,
stopReason: response.stopReason,
canLoadSession: initialized.agentCapabilities?.loadSession === true,
};
});
console.log("\n", result);运行:
BUDA_API_KEY="sk_your_api_key" \
BUDA_AGENT_ID="your_agent_id" \
node buda-acp.mjs你应该先看到流式文本,随后看到包含 sessionId、stopReason 和 canLoadSession: true 的结果。
createWebSocketStream 目前位于 SDK 的 experimental/ws-client 导出路径。升级 @agentclientprotocol/sdk 时,请检查该导出路径是否有变更。
会话如何工作
一次正常的 ACP 调用顺序是:
initialize:协商协议版本与能力;session/new:创建一个 Buda 会话并得到sessionId;session/prompt:发送消息;- 接收多个
session/update:流式展示回复、思考与工具调用; - 保存
sessionId;断线后重新initialize,再用session/load恢复会话; - 需要停止运行时发送
session/cancel。
| ACP 方法 | Buda 行为 |
|---|---|
initialize | 协商版本;声明支持 loadSession |
session/new | 为当前连接绑定的智能体创建新会话 |
session/prompt | 发送一轮消息,并通过 session/update 流式返回结果 |
session/load | 重新接入进行中的流,或回放已保存的会话历史 |
session/cancel | 停止当前会话中正在运行的一轮任务 |
目前 prompt 内容支持 text 和 resource_link。图片、音频与内嵌资源内容尚未开放。
故障排查
| 现象 | 最可能的原因 | 解决方法 |
|---|---|---|
| 编辑器里没有出现 Buda | 找不到 acpremote | 把 command 改为 command -v acpremote 返回的绝对路径,然后重启编辑器 |
initialize 后立即断开 | 密钥无效、过期,或 agentId 错误 | 先调用 /api/v1/users/me 验证密钥,再从智能体 URL 重新复制 ID |
| 返回无权访问 | API 密钥所属用户不是智能体拥有者或空间成员 | 使用有访问权限的账户创建密钥,或把用户加入对应空间 |
| 智能体看不到本地项目文件 | Buda 使用远程沙箱,不使用编辑器本地目录 | 为智能体连接 GitHub,或把文件上传到它可访问的位置 |
| 第二条消息提示已有任务运行 | 同一会话不支持并发 session/prompt | 等待当前任务结束,或先发送 session/cancel |
| 浏览器 WebSocket 无法认证 | 浏览器不能设置 WebSocket 握手的 Authorization 请求头 | 从可信后端连接,或使用 Node.js 客户端;不要把 sk_ 密钥放进前端 |
| 长任务中途断开 | VPN、代理或网络网关关闭了长时间 WebSocket | 检查 WebSocket 支持与空闲超时,然后用保存的 sessionId 执行 session/load |
| 工具调用没有确认弹窗 | 当前 Buda ACP 会自动批准工具调用 | 限制智能体可访问的数据与集成,使用最小权限密钥,并避免连接敏感系统 |
在 Zed 中,可以从命令面板运行 ACP: Open ACP Logs 查看编辑器与桥接进程之间的 ACP 消息。JetBrains 用户可从 AI Assistant 日志和 acpremote 的标准错误输出检查启动失败原因。
当前限制
- 仅支持 WebSocket。 Buda ACP 尚不提供 Streamable HTTP profile。
- 没有逐次权限确认。 当前工具调用自动批准。
- 同一会话一次只能运行一条 prompt。 并发发送会被拒绝,不会自动排队。
- 一条连接只对应一个智能体。 多个智能体需要多条连接。
- 仅接受
sk_API 密钥。 不接受浏览器会话 Cookie、OAuth 令牌或内部智能体密钥。 - 远程沙箱拥有工作目录。 客户端传入的本地
cwd与 MCP server 列表不会让 Buda 访问本地机器。
参考实现
本文的接入方式与以下资料保持一致:
- ACP 官方协议与 SDK
- Zed External Agents 配置
- JetBrains ACP 配置
acpremoteWebSocket 桥接- ACP TypeScript SDK WebSocket 示例