# Connect Buda over ACP (/docs/developers/acp)





[Agent Client Protocol](https://agentclientprotocol.com) (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:

```text
Zed / JetBrains / your program
              │ ACP
              ▼
wss://buda.im/api/acp?agentId=...
              │
              ▼
Buda agent → cloud sandbox → connected knowledge and integrations
```

<Callout type="info">
  A 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](/en/docs/developers/github-app#connect-github-to-a-specific-agent), or place the required content in knowledge sources and integrations the agent can access.
</Callout>

## Choose a connection method [#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`](https://vcoderun.github.io/acpkit/acpremote/) tool. It only forwards ACP messages; the Buda agent still runs in the cloud.

## Before you begin [#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 `acpremote` command.

<Callout type="warning">
  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.
</Callout>

## Step 1: Get the agent ID [#step-1-get-the-agent-id]

Open the agent you want to connect. Its browser URL usually looks like:

```text
https://buda.im/agents/your_agent_id
```

The 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:

```bash
export BUDA_AGENT_ID="your_agent_id"
```

<Callout type="info">
  One ACP connection binds to one agent. To drive another agent, open another connection with a different `agentId`.
</Callout>

## Step 2: Create an API key [#step-2-create-an-api-key]

<Steps>
  <Step>
    ### Open Settings → API Keys [#open-settings--api-keys]

    In the Buda console, open **Settings → API Keys**, then select **New key**.
  </Step>

  <Step>
    ### Name the key and choose an expiration [#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.
  </Step>

  <Step>
    ### Copy the complete key immediately [#copy-the-complete-key-immediately]

    The complete `sk_...` value is shown only once. Save it in a password manager or secret store.
  </Step>
</Steps>

Verify the key with the REST API before configuring ACP:

```bash
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 [#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:

```bash
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 [#step-4-connect-an-editor]

### Install the bridge [#install-the-bridge]

Install `acpremote` as a standalone command:

```bash
uv tool install acpremote
```

If you do not use `uv`, install it with Python:

```bash
python -m pip install --user acpremote
```

Confirm the editor can find the command:

```bash
command -v acpremote
acpremote --help
```

Copy 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 [#zed]

Open **Agent Settings → External Agents → Add Agent → Add Custom Agent**, then add this entry to `settings.json`:

```json title="Zed 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:

```text
Reply with only: Buda ACP connected
```

A 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 [#jetbrains]

In AI Chat, select **Add Custom Agent**. JetBrains creates and opens `~/.jetbrains/acp.json`:

```json title="~/.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.

<Callout type="warning">
  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.
</Callout>

### Other editors [#other-editors]

If another editor's custom ACP settings also accept `command` and `args`, configure it to launch this local command:

```bash
BUDA_API_KEY="sk_your_api_key" acpremote mirror \
  "wss://buda.im/api/acp?agentId=your_agent_id" \
  --token-env BUDA_API_KEY
```

If 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 [#step-5-connect-from-nodejs-or-ci]

Programmatic clients do not need the stdio bridge. Install the ACP SDK and a Node WebSocket implementation:

```bash
npm install @agentclientprotocol/sdk ws
```

Create `buda-acp.mjs`:

```js title="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:

```bash
BUDA_API_KEY="sk_your_api_key" \
BUDA_AGENT_ID="your_agent_id" \
node buda-acp.mjs
```

You should first see streamed text, followed by a result containing `sessionId`, `stopReason`, and `canLoadSession: true`.

<Callout type="info">
  `createWebSocketStream` currently lives under the SDK's `experimental/ws-client` export. Check for export-path changes when upgrading `@agentclientprotocol/sdk`.
</Callout>

## How sessions work [#how-sessions-work]

A normal ACP call follows this sequence:

1. `initialize` negotiates the protocol version and capabilities;
2. `session/new` creates a Buda session and returns its `sessionId`;
3. `session/prompt` sends a message;
4. Multiple `session/update` notifications stream replies, reasoning, and tool calls;
5. Save the `sessionId`. After reconnecting, call `initialize` again and then use `session/load` to restore the session;
6. Send `session/cancel` when 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 [#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 [#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 `cwd` or MCP server list does not give Buda access to the local machine.

## Reference implementations [#reference-implementations]

This setup follows the behavior documented by:

* [The ACP specification and SDKs](https://agentclientprotocol.com)
* [Zed External Agents](https://zed.dev/docs/ai/external-agents)
* [JetBrains ACP configuration](https://www.jetbrains.com/help/ai-assistant/acp.html)
* [`acpremote` WebSocket bridging](https://vcoderun.github.io/acpkit/acpremote/)
* [The ACP TypeScript SDK WebSocket example](https://github.com/agentclientprotocol/typescript-sdk/blob/main/src/examples/ws-client.ts)

## Related content [#related-content]

<Cards>
  <Card title="Authentication" href="/en/docs/developers/authentication" description="Create, verify, and rotate the sk_ API key used by ACP." />

  <Card title="GitHub App" href="/en/docs/developers/github-app#connect-github-to-a-specific-agent" description="Give the cloud agent access to repositories you authorize." />

  <Card title="API Claw" href="/en/docs/developers/api-claws" description="Create agents through the REST API and obtain an agentId." />
</Cards>
