Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bright-apes-serve-acp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eve": patch
---

Launch local or deployed eve applications as stable ACP v1 agents with `eve acp [url]`, including streamed messages, tool activity, human input, cancellation, and concurrent sessions.
88 changes: 88 additions & 0 deletions docs/guides/acp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: "Use eve through ACP"
description: "Launch a local eve agent from Zed and other Agent Client Protocol clients."
---

Agent Client Protocol (ACP) clients can launch an authored eve application as a local subprocess. eve serves stable ACP v1 over stdio while its normal development server remains the execution runtime.

```sh
eve acp
```

Without a URL, the client starts one process from the eve application root. It supervises a local development server, and closing the ACP connection stops that owned server. To bridge ACP to a deployed eve agent, pass its URL:

```sh
eve acp https://agent.example.com
```

## Configure Zed

Open the eve application root as the Zed workspace. In **Agent Settings → External Agents**, add a custom agent:

```json
{
"agent_servers": {
"eve-local": {
"type": "custom",
"command": "pnpm",
"args": ["exec", "eve", "acp"],
"env": {}
}
}
}
```

Use an absolute command path if Zed cannot find `pnpm` in its environment. The workspace must be the same directory as the eve application root; eve rejects a different `session/new.cwd` instead of running the wrong application.

Disable Zed project MCP servers for this agent. The initial eve adapter does not accept client-provided MCP servers.

## Supported behavior

ACP clients receive:

- streamed assistant text and reasoning;
- tool-call requests and results;
- one-time tool approval and denial requests;
- fixed-choice and freeform questions when the client supports ACP form elicitation;
- cooperative turn cancellation;
- independent concurrent ACP sessions;
- session closure and process cleanup.

Development rebuilds retain normal eve semantics. In-flight work stays pinned to its generation, and the next turn uses the newest successful generation.

## Security and capability limits

ACP mode does not give the agent access to the editor's host filesystem or terminal. `session/new.cwd` identifies the eve application being launched; it is not mounted into the agent sandbox.

The initial adapter does not support:

- a deployed ACP HTTP or WebSocket endpoint;\n- ACP authentication (remote bridges use the deployed eve agent's existing HTTP authentication);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- a deployed ACP HTTP or WebSocket endpoint;\n- ACP authentication (remote bridges use the deployed eve agent's existing HTTP authentication);
- a deployed ACP HTTP or WebSocket endpoint;
- ACP authentication (remote bridges use the deployed eve agent's existing HTTP authentication);

A literal \n escape sequence in the markdown source merges two bullet list items into one broken bullet

Fix on Vercel

- ACP v2;
- client filesystem or terminal methods;
- client-provided MCP servers;
- images, audio, files, or embedded resources in prompts;
- session loading, listing, resumption, or durable ACP IDs across process restarts;
- ACP model or mode configuration.

The agent continues to use the connections, tools, credentials, and sandbox policy authored in the eve application. Prompt text and ACP metadata never establish an authenticated end-user principal.

## Diagnose a connection

ACP reserves stdout for newline-delimited JSON-RPC. eve sends compilation output, server logs, and diagnostics to stderr so they cannot corrupt the protocol stream.

For a quick headless smoke test, run an ACP client such as `acpx` from the application root. `acpx` launches the ACP process itself; do not start `eve acp` separately.

```sh
npx acpx@latest \
--agent 'pnpm exec eve acp' \
exec 'Reply with exactly: ACP works'
```

When testing from the eve source checkout, use an authored fixture rather than the monorepo root, which does not provide an `eve` executable:

```sh
cd apps/fixtures/weather-agent
npx acpx@latest --agent 'pnpm exec eve acp' exec 'Reply with exactly: ACP works'
```

If startup fails, inspect the ACP client's logs together with eve's stderr. A non-empty client MCP configuration, a mismatched working directory, and unsupported prompt content produce explicit protocol errors before model work begins.
1 change: 1 addition & 0 deletions docs/guides/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dynamic-workflows",
"remote-agents",
"dev-tui",
"acp",
"frontend",
"client"
]
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The `eve` binary (`bin: eve`) runs from your app root, and every command first l
| `eve start` | Serve the built `.output/` app; prints the listening URL |
| `eve dev` | Start the local dev server and open the terminal UI |
| `eve dev <url>` | Connect the UI to an existing server URL (e.g. a remote deployment) instead of booting a local server |
| `eve acp [url]` | Serve the local application or an existing eve server URL as a stable ACP v1 agent over stdio |
| `eve logs [logid]` | Print an `eve dev` diagnostic log (the most recent when `logid` is omitted) |
| `eve logs ls` | List `eve dev` diagnostic logs, most recent first |
| `eve trace ls` | List locally captured agent traces, most recent first |
Expand Down Expand Up @@ -181,6 +182,8 @@ Pass a bare URL and the UI connects to that server instead of booting a local on
| `--context-size <tokens>` | number | none | Model context window size, shown as a usage percentage |
| `--logs <mode>` | enum | `stderr` | Server/agent logs to show: `all` \| `stderr` \| `sandbox` \| `none` |

`eve acp` reserves stdin and stdout for newline-delimited JSON-RPC and sends diagnostics to stderr. Without a URL, it supervises an isolated local development server. With a URL, it bridges ACP to that server's existing eve HTTP API and accepts the same URL credentials and request headers as `eve dev <url>`. See [Use eve through ACP](../guides/acp) for client configuration and capability limits.

A fresh `eve init` passes `--input /model`. That bare local input starts onboarding: the TUI installs the Vercel CLI if needed, asks you to log in if needed, then opens `/model`. Other input stays editable in the prompt.

For a URL target protected by HTTP Basic auth, put the credentials in the URL. eve sends them as a Basic `Authorization` header and strips them from the server URL before connecting:
Expand Down
1 change: 1 addition & 0 deletions packages/eve/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@
"undici": "8.9.0"
},
"devDependencies": {
"@agentclientprotocol/sdk": "1.3.0",
"@ai-sdk/anthropic": "catalog:",
"@ai-sdk/google": "catalog:",
"@ai-sdk/mcp": "catalog:",
Expand Down
26 changes: 26 additions & 0 deletions packages/eve/scripts/vendor-compiled/@agentclientprotocol/sdk.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";

const DECLARATIONS = [
["acp.d.ts", "index.d.ts"],
["jsonrpc.d.ts", "jsonrpc.d.ts"],
["stream.d.ts", "stream.d.ts"],
["schema/guards.gen.d.ts", "schema/guards.gen.d.ts"],
["schema/index.d.ts", "schema/index.d.ts"],
["schema/types.gen.d.ts", "schema/types.gen.d.ts"],
];

/** Vendor the stable ACP v1 SDK without adding it to eve's runtime dependencies. */
export default {
packageName: "@agentclientprotocol/sdk",
compiledPath: "@agentclientprotocol/sdk",
bundling: "standalone",
copyDeclarations: async ({ destinationRoot, packageInfo }) => {
const sourceRoot = join(packageInfo.packageRoot, "dist");
for (const [sourceFile, destinationFile] of DECLARATIONS) {
const destinationPath = join(destinationRoot, destinationFile);
await mkdir(dirname(destinationPath), { recursive: true });
await writeFile(destinationPath, await readFile(join(sourceRoot, sourceFile)), "utf8");
}
},
};
2 changes: 2 additions & 0 deletions packages/eve/scripts/vendor-compiled/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* the orchestrator passes to `runVendor`. Adding a new vendored package
* means writing a new per-package file and importing it here.
*/
import acpSdk from "./@agentclientprotocol/sdk.mjs";
import anthropic from "./@ai-sdk/anthropic.mjs";
import google from "./@ai-sdk/google.mjs";
import mcp from "./@ai-sdk/mcp.mjs";
Expand Down Expand Up @@ -48,6 +49,7 @@ import zod from "./zod.mjs";
import zodValidationError from "./zod-validation-error.mjs";

export const MODULES = [
acpSdk,
anthropic,
chat,
chatAdapterSlack,
Expand Down
Loading
Loading