Connect Buda over ACP
Connect Zed, JetBrains, or your own program to a Buda-hosted agent, step by step.
Agent Client Protocol (ACP) lets you talk to a Buda-hosted agent from Zed, JetBrains, or your own program. Replies, reasoning, and tool calls stream back as standard ACP events, without running the agent or model on your machine.
After setup, your connection looks like this:
Zed / JetBrains / your program
│ ACP
▼
wss://buda.im/api/acp?agentId=...
│
▼
Buda agent → cloud sandbox → connected knowledge and integrationsA Buda agent runs in a cloud sandbox. It does not automatically read the local folder open in your editor. To work with a code repository, first connect GitHub to that agent, or place the required content in knowledge sources and integrations the agent can access.
Choose a connection method
| Your environment | Recommended method | Bridge required? |
|---|---|---|
| Zed | acpremote + a Zed custom agent | Yes |
| JetBrains AI Chat | acpremote + ~/.jetbrains/acp.json | Yes |
| Node.js, scripts, or CI | Connect directly with @agentclientprotocol/sdk | No |
| Another ACP client that supports remote WebSocket and custom headers | Connect directly to Buda | No |
| Browser frontend | Do not connect directly | Browser WebSocket cannot send an Authorization header |
Zed and JetBrains custom ACP configurations launch a local command, while Buda exposes a remote WebSocket endpoint. Editor integrations therefore need a small stdio ↔ WebSocket bridge. This guide uses the third-party open-source acpremote tool. It only forwards ACP messages; the Buda agent still runs in the cloud.
Before you begin
Prepare the following:
- A Buda agent you can access;
- The agent's
agentId; - A Buda API key beginning with
sk_; - For editor setup: Python installed locally and a working
acpremotecommand.
Buda ACP currently auto-approves tool calls instead of showing a permission prompt for each action. Connect only repositories, knowledge sources, and external systems you trust, and use separate API keys for test and production environments.
Step 1: Get the agent ID
Open the agent you want to connect. Its browser URL usually looks like:
https://buda.im/agents/your_agent_idThe value after /agents/ can be used as the agentId. If you created the agent through the REST API, you can also use the id returned by the create-agent endpoint.
For example:
export BUDA_AGENT_ID="your_agent_id"One ACP connection binds to one agent. To drive another agent, open another connection with a different agentId.
Step 2: Create an API key
Open Settings → API Keys
In the Buda console, open Settings → API Keys, then select New key.
Name the key and choose an expiration
Use a recognizable name such as zed-acp, jetbrains-acp, or ci-acp. Prefer a short expiration period while testing.
Copy the complete key immediately
The complete sk_... value is shown only once. Save it in a password manager or secret store.
Verify the key with the REST API before configuring ACP:
export BUDA_API_KEY="sk_your_api_key"
curl https://buda.im/api/v1/users/me \
-H "Authorization: Bearer $BUDA_API_KEY"Continue after the endpoint returns your current user. If it returns 401 Unauthorized, replace or recreate the key first.
Step 3: Build the ACP endpoint
Buda ACP uses these connection values:
| Setting | Value |
|---|---|
| WebSocket endpoint | wss://buda.im/api/acp?agentId=<agentId> |
| Authentication header | Authorization: Bearer sk_... |
| Transport | WebSocket |
| Agents per connection | 1 |
Build your full URL:
export BUDA_ACP_URL="wss://buda.im/api/acp?agentId=$BUDA_AGENT_ID"The API key must belong to a Buda user who can access the requested agent. An invalid key, an unknown agentId, or insufficient access causes initialize to fail and the connection to close.
Step 4: Connect an editor
Install the bridge
Install acpremote as a standalone command:
uv tool install acpremoteIf you do not use uv, install it with Python:
python -m pip install --user acpremoteConfirm the editor can find the command:
command -v acpremote
acpremote --helpCopy the absolute path returned by command -v acpremote. An editor launched from the desktop may not inherit the same PATH as your terminal, so an absolute path is the most reliable configuration.
Zed
Open Agent Settings → External Agents → Add Agent → Add Custom Agent, then add this entry to 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"
}
}
}
}Save the settings, start a new Buda thread in the Agent Panel, and send:
Reply with only: Buda ACP connectedA streamed reply confirms the connection works. If Buda does not appear in the agent selector, restart Zed and verify that command points to an existing executable.
JetBrains
In AI Chat, select Add Custom Agent. JetBrains creates and opens ~/.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"
}
}
}
}Save the file, select Buda from the AI Chat agent picker, start a thread, and send a test message.
These minimal configurations store the API key in a local editor configuration file. Do not sync that file into a public repository. Restrict its file permissions, delete or rotate the key when it is no longer needed, and issue separate keys for each team member and environment.
Other editors
If another editor's custom ACP settings also accept command and args, configure it to launch this local command:
BUDA_API_KEY="sk_your_api_key" acpremote mirror \
"wss://buda.im/api/acp?agentId=your_agent_id" \
--token-env BUDA_API_KEYIf the client natively supports remote ACP over WebSocket and can send a custom Authorization header during the handshake, skip acpremote and connect directly to Buda.
Step 5: Connect from Node.js or CI
Programmatic clients do not need the stdio bridge. Install the ACP SDK and a Node WebSocket implementation:
npm install @agentclientprotocol/sdk wsCreate 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: "Reply with only: Buda ACP connected" }],
});
return {
sessionId: session.sessionId,
stopReason: response.stopReason,
canLoadSession: initialized.agentCapabilities?.loadSession === true,
};
});
console.log("\n", result);Run it:
BUDA_API_KEY="sk_your_api_key" \
BUDA_AGENT_ID="your_agent_id" \
node buda-acp.mjsYou should first see streamed text, followed by a result containing sessionId, stopReason, and canLoadSession: true.
createWebSocketStream currently lives under the SDK's experimental/ws-client export. Check for export-path changes when upgrading @agentclientprotocol/sdk.
How sessions work
A normal ACP call follows this sequence:
initializenegotiates the protocol version and capabilities;session/newcreates a Buda session and returns itssessionId;session/promptsends a message;- Multiple
session/updatenotifications stream replies, reasoning, and tool calls; - Save the
sessionId. After reconnecting, callinitializeagain and then usesession/loadto restore the session; - Send
session/cancelwhen you need to stop an active run.
| ACP method | Buda behavior |
|---|---|
initialize | Negotiates the version and advertises loadSession support |
session/new | Creates a session for the agent bound to this connection |
session/prompt | Sends one turn and streams the result through session/update |
session/load | Reattaches to an active stream or replays saved session history |
session/cancel | Stops the active run in the requested session |
Prompt content currently supports text and resource_link. Image, audio, and embedded-resource content are not yet available.
Troubleshooting
| Symptom | Most likely cause | Fix |
|---|---|---|
| Buda does not appear in the editor | The editor cannot find acpremote | Set command to the absolute path returned by command -v acpremote, then restart the editor |
The connection closes after initialize | The key is invalid or expired, or the agentId is wrong | Verify the key with /api/v1/users/me, then copy the ID again from the agent URL |
| The server reports insufficient access | The API-key owner does not own the agent and is not a member of its Space | Create the key with an authorized account or add the user to the Space |
| The agent cannot see local project files | Buda uses a remote sandbox, not the editor's local folder | Connect GitHub to the agent or upload the files somewhere it can access |
| A second message reports that a run is already in progress | Concurrent session/prompt calls are not supported in one session | Wait for the active run to finish or send session/cancel first |
| Browser WebSocket authentication fails | Browsers cannot set the WebSocket handshake Authorization header | Connect from a trusted backend or Node.js client; never expose an sk_ key in frontend code |
| A long run disconnects | A VPN, proxy, or gateway closed the long-lived WebSocket | Check WebSocket support and idle timeouts, then restore the saved sessionId with session/load |
| Tool calls run without a confirmation dialog | Buda ACP currently auto-approves tools | Limit accessible data and integrations, use least-privilege keys, and avoid sensitive systems |
In Zed, run ACP: Open ACP Logs from the command palette to inspect messages between Zed and the bridge process. In JetBrains, inspect AI Assistant logs and acpremote standard-error output for startup failures.
Current limitations
- WebSocket only. Buda ACP does not currently expose the Streamable HTTP profile.
- No per-action permission prompt. Tool calls are currently auto-approved.
- One prompt at a time per session. Concurrent prompts are rejected instead of queued.
- One agent per connection. Connecting multiple agents requires multiple connections.
sk_API keys only. Browser session cookies, OAuth tokens, and internal agent keys are not accepted.- The remote sandbox owns the workspace. A client-provided local
cwdor MCP server list does not give Buda access to the local machine.
Reference implementations
This setup follows the behavior documented by:
- The ACP specification and SDKs
- Zed External Agents
- JetBrains ACP configuration
acpremoteWebSocket bridging- The ACP TypeScript SDK WebSocket example