---
title: "Hoplite ACP endpoint"
description: "Connect ACP clients to durable Hoplite threads"
canonical_url: "https://hoplite.sh/docs/cli/acp"
markdown_url: "https://hoplite.sh/docs/cli/acp.md"
---

# Hoplite ACP endpoint
URL: /docs/cli/acp
LLM index: /llms.txt
Description: Connect ACP clients to durable Hoplite threads
Related: /docs/cli, /docs/cli/mcp-server, /docs/threads, /docs/workspace/security

# Hoplite ACP endpoint

Hoplite exposes a public [Agent Client Protocol](https://agentclientprotocol.com/protocol/v1/overview) endpoint. ACP clients can create or load a Hoplite thread, send prompts, receive streamed agent messages, and cancel the active run.

The endpoint negotiates stable ACP v1 or experimental ACP v2 over Streamable HTTP and WebSocket:

```text
https://api.hoplite.sh/acp
wss://api.hoplite.sh/acp
```

Add the project when creating a new session:

```text
https://api.hoplite.sh/acp?projectId=<project-id>
```

Streamable HTTP clients receive `Acp-Connection-Id` during initialization and must send it on later `POST`, `GET`, and `DELETE` requests. Server messages arrive through `GET` requests that accept `text/event-stream`; session streams also use `Acp-Session-Id`. WebSocket clients receive the connection ID in the `101 Switching Protocols` response and exchange JSON-RPC as text frames on the persistent socket. The official TypeScript SDK manages both transports.

Paseo remote ACP providers can use `wss://api.hoplite.sh/acp?projectId=<project-id>` with `bearerTokenEnv` and `authMethodId: "hoplite-oauth"` or `"hoplite-api-key"`. Hoplite accepts Paseo's optional WebSocket protocols and remote `cwd`; the project remains selected by the endpoint query parameter.

## Authentication

Every transport request accepts either OAuth or a Hoplite API key. The ACP `initialize` response advertises the matching native authentication method. ACP v1 clients complete protocol login with `authenticate`; ACP v2 clients use `auth/login`. Both versions require protocol login before session methods are available.

### OAuth

OAuth clients discover the resource and authorization server from:

```text
https://api.hoplite.sh/.well-known/oauth-protected-resource/acp
https://api.hoplite.sh/.well-known/oauth-authorization-server/api/auth
```

The protected resource is `https://api.hoplite.sh/acp`. Hoplite supports authorization-code and refresh-token grants, PKCE-capable clients, and dynamic client registration at `/api/auth/oauth2/register`. Request only the scopes the client needs:

| Scope | Allows |
| --- | --- |
| `project:read` | Validate the project selected for a new session |
| `thread:create` | Create a Hoplite thread on the first prompt |
| `thread:read` | Load a thread and replay its messages |
| `thread:update` | Add prompts and cancel an active run |

Send the access token on every HTTP request or the WebSocket upgrade:

```http
Authorization: Bearer <oauth-access-token>
```

After `initialize`, call the native ACP method for the negotiated version:

```json
{"jsonrpc":"2.0","id":2,"method":"authenticate","params":{"methodId":"hoplite-oauth"}}
{"jsonrpc":"2.0","id":2,"method":"auth/login","params":{"methodId":"hoplite-oauth"}}
```

### API keys

Create an organization-scoped key under **Settings → Workspace → API keys** with project read and thread create, read, update, and stop permissions. Send it in either supported form:

```http
X-Api-Key: hop_...
```

```http
Authorization: Bearer hop_...
```

After `initialize`, authenticate the ACP connection with `methodId: "hoplite-api-key"` using the version's login method. Credentials remain transport headers and never appear in JSON-RPC bodies.

## Sessions and prompts

`session/new` validates `projectId` and returns a server-generated session ID. The first `session/prompt` creates a Hoplite thread with that ID and starts its run. Later prompts append to the same durable thread. Reconnect by initializing a fresh transport and calling v1 `session/load` or v2 `session/resume` with the saved session ID. Hoplite authorizes the thread and can replay user and assistant messages through `session/update`.

Hoplite supports:

| ACP method | Version | Behavior |
| --- | --- | --- |
| `initialize` | v1, v2 | Negotiates capabilities and the active authentication method |
| `authenticate` / `logout` | v1 | Starts or clears native authentication for the transport credential |
| `auth/login` / `auth/logout` | v2 | Starts or clears native authentication for the transport credential |
| `session/new` | v1, v2 | Allocates a session for the selected Hoplite project |
| `session/load` | v1 | Loads an authorized Hoplite thread and replays messages |
| `session/list` | v2 | Lists authorized, non-archived threads for the selected project |
| `session/resume` | v2 | Resumes a thread and optionally replays its messages |
| `session/close` | v2 | Closes the connection's active session state without deleting the thread |
| `session/prompt` | v1, v2 | Creates or continues the thread and streams the final agent message |
| `session/cancel` | v1, v2 | Cancels the prompt and stops the active Hoplite run |

Both versions support text and resource-link prompt blocks. ACP v1 also supports embedded text resources. Client-provided MCP servers, images, audio, and embedded binary resources are rejected. Configure MCP servers on the Hoplite project instead.

## Minimal protocol flow

Initialize the transport with a non-null JSON-RPC request ID:

```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":1,"clientCapabilities":{},"clientInfo":{"name":"my-client","version":"1.0.0"}}}
```

Authenticate, create a session, then prompt:

```json
{"jsonrpc":"2.0","id":2,"method":"authenticate","params":{"methodId":"hoplite-oauth"}}
{"jsonrpc":"2.0","id":3,"method":"session/new","params":{"cwd":"/workspace","mcpServers":[]}}
{"jsonrpc":"2.0","id":4,"method":"session/prompt","params":{"sessionId":"<session-id>","prompt":[{"type":"text","text":"Fix the failing authentication test and open a pull request."}]}}
```

Connected HTTP `POST` requests return `202 Accepted`; read their JSON-RPC responses and `session/update` notifications from the SSE stream, then send `DELETE /acp` with `Acp-Connection-Id` when finished. WebSocket clients send and receive the same JSON-RPC messages as text frames and close the socket when finished.

For ACP v2, initialize with protocol version `2`, use `auth/login`, and use `session/resume` instead of `session/load`:

```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":2,"info":{"name":"my-client","version":"1.0.0"}}}
{"jsonrpc":"2.0","id":2,"method":"auth/login","params":{"methodId":"hoplite-oauth"}}
{"jsonrpc":"2.0","id":3,"method":"session/resume","params":{"sessionId":"<session-id>","cwd":"/workspace","replayFrom":{"type":"start"}}}
```

ACP v2 acknowledges `session/prompt` when the prompt is accepted, then reports `state_update` notifications for `running` and `idle`. The final `idle` update includes the stop reason.

## Protocol status

Hoplite supports stable ACP v1 and the current experimental ACP v2 draft on the same endpoint. The server routes each connection by the negotiated `initialize.protocolVersion`; v1 uses `authenticate` and `logout`, while v2 uses `auth/login` and `auth/logout`. ACP v2 may still change incompatibly before it becomes stable. Hoplite implements both profiles from the remote [Streamable HTTP and WebSocket transport](https://github.com/agentclientprotocol/agent-client-protocol/blob/c50e1cd2/docs/rfds/streamable-http-websocket-transport.mdx) RFD.

See the [ACP TypeScript SDK](https://github.com/agentclientprotocol/typescript-sdk) for a client transport implementation and the [v2 migration guide](https://agentclientprotocol.com/protocol/v2/migration) for the authentication-method differences.

## Sitemap

See the full [sitemap](/docs/sitemap.md) for all pages.
Well-known sitemap: [/docs/.well-known/sitemap.md](/docs/.well-known/sitemap.md).
