# Ways to Set Up ACP — Full Coverage for Your Stack

Find your situation, run the setup for it, and know exactly what coverage you have. Claude Code, Codex, Hermes, LangGraph/CrewAI, direct API calls, and existing gateways — each ends with your coverage state.

# Ways to set up ACP

ACP can sit in two places in your agent, and they see different things:

- **Interception** — a hook or wrapper at the point where tools *execute*. This is what enforces policy (allow / deny / ask) and writes the tool-call audit trail.
- **The proxy** — a base-URL change at the point where model calls go *out*. This is what prices every call, sees prompt-cache economics, and meters spend per run.

Full coverage is both. Neither substitutes for the other: interception never sees token usage, the proxy never sees what your code actually executes. Find your situation below — each section ends with the coverage you'll have and, if a plane is missing, the exact step that adds it.

**Jump to your stack:**

- [I use Claude Code](#i-use-claude-code)
- [I use Codex](#i-use-codex)
- [I run a Hermes agent](#i-run-a-hermes-agent)
- [I built with LangGraph or CrewAI](#i-built-with-langgraph-or-crewai)
- [I call model APIs directly](#i-call-model-apis-directly)
- [I already use a gateway (LiteLLM, OpenRouter, …)](#i-already-use-a-gateway-litellm-openrouter-)
- [Check what you actually have](#check-what-you-actually-have)

> **Note to AI agents:** this page is also served as raw markdown at [/docs/setup.md](/docs/setup.md). If you are setting up ACP on behalf of a user, run the commands for their harness below, then verify in the console that both planes report activity. If you have **no signed-in human available** (evaluating ACP autonomously, running a benchmark or starter), don't stop at the login step — self-onboard with `POST /v1/sandbox-tenants` per the [agents quickstart](/agents/quickstart/): an ephemeral workspace and scoped key in one call; when a human appears, hand them the `nextSteps.claimPageUrl` from the response — one click makes the workspace permanently theirs.

## I use Claude Code

One command:

```bash
curl -sf https://agenticcontrolplane.com/install.sh | bash
```

This installs both planes:

- The governance hook (`~/.acp/govern.mjs` + PreToolUse/PostToolUse entries) — every tool call checked and audited.
- The `claude-acp` launcher — starts Claude Code with its model calls routed through the ACP proxy, so sessions are priced.

Start sessions with `claude-acp` instead of `claude`.

**Your coverage:** interception ✓ · proxy ✓ — *if you launch with `claude-acp`*. Plain `claude` still has governed tools, but its model calls go straight to Anthropic: interception ✓ · proxy ✗. The fix is the launcher, nothing else to install.

Details: [Claude Code integration](/integrations/claude-code).

## I use Codex

The same installer detects Codex:

```bash
curl -sf https://agenticcontrolplane.com/install.sh | bash
```

It enables `codex_hooks`, registers the PreToolUse/PostToolUse hooks (covers Bash — where most destructive-action risk lives), and wires the ACP MCP connector for the tools Codex routes through MCP. Codex's hook surface is narrower than Claude Code's — see [the honest coverage notes](/integrations/codex) before relying on hooks alone.

For the cost plane, add a model provider in `~/.codex/config.toml` pointing at the proxy (provider keys are ignored in project-local `.codex/config.toml` — this must be the home-directory file):

```toml
model_provider = "acp"

[model_providers.acp]
name = "Agentic Control Plane"
base_url = "https://api.agenticcontrolplane.com/openai/v1"
env_key = "OPENAI_API_KEY"                        # your own OpenAI key — billed to you, forwarded untouched
wire_api = "responses"
env_http_headers = { "x-acp-key" = "ACP_KEY" }    # your gsk_... workspace key, from the ACP_KEY env var
```

Note this is API-key billing: Codex signed in with a ChatGPT plan can't route a custom provider, so the proxy path uses your OpenAI API key (or a workspace-managed key).

**Your coverage:** interception ✓ (Bash via hooks + MCP-routed tools; not every native tool — see the coverage notes) · proxy ✓ once the model provider points at ACP. Without the `config.toml` change: interception ✓ · proxy ✗ → add the block above.

Details: [Codex integration](/integrations/codex).

## I run a Hermes agent

Four commands, native to Python:

```bash
pip install hermes-acp
hermes plugins enable acp
acp-hermes login
acp-hermes proxy-setup --verify
```

The plugin registers Hermes's `pre_tool_call`/`post_tool_call` hooks — Hermes's hook surface covers **every** tool, so interception here is the most complete of any harness. `proxy-setup` reads Hermes's own config, registers ACP as a provider pointed at the proxy, and keeps your current model; `--verify` sends one governed completion to prove the wiring end to end. `--undo` reverses it.

On a **headless box** (VPS, server, container — where autonomous agents actually live), swap step three for `acp-hermes login --device` (0.2.4+): it prints a short code, you approve it at [cloud.agenticcontrolplane.com/device](https://cloud.agenticcontrolplane.com/device) from any browser, and the key lands directly on the machine. Works from raw curl too — `POST /device/code`, approve, poll `POST /device/token`.

**Your coverage:** interception ✓ · proxy ✓ — and `--verify` has already confirmed it, not just configured it. If you stopped after `login`: interception ✓ · proxy ✗ → run `acp-hermes proxy-setup --verify`.

Details: [Hermes integration](/integrations/hermes).

## I built with LangGraph or CrewAI

Two changes in your own code — no environment archaeology, both planes wired in-process:

```bash
pip install acp-langchain   # or acp-crewai
```

**Interception** — wrap your tools:

```python
from acp_langchain import governed

@tool
@governed("send_email")
def send_email(to: str, subject: str, body: str) -> str:
    ...
```

**Proxy** — point the LLM client you already construct at ACP:

```python
model = ChatOpenAI(
    base_url="https://api.agenticcontrolplane.com/v1",   # OpenAI-compatible
    api_key=os.environ["ACP_API_KEY"],                    # gsk_...
)
# Anthropic SDK: base_url="https://api.agenticcontrolplane.com/anthropic"
```

The proxy is multi-provider — it routes `gpt-*`, `claude-*`, and `gemini-*` model ids to the right provider and forwards unchanged.

**Your coverage:** interception ✓ (decorated tools) · proxy ✓ (repointed client). Only decorated: interception ✓ · proxy ✗ → repoint the client. Only repointed: proxy ✓ · interception ✗ → decorate the tools. A single `acp.init()` that does both in one call is in progress; today it's these two edits.

Details: [LangGraph](/integrations/langgraph) · [CrewAI](/integrations/crewai) · [all frameworks](/frameworks).

## I call model APIs directly

If your agent is your own code calling the Anthropic or OpenAI API, swap the base URL and authenticate with your ACP key (`gsk_...` from [the console](https://cloud.agenticcontrolplane.com)):

- Anthropic SDK: `base_url = "https://api.agenticcontrolplane.com/anthropic"`
- OpenAI-compatible clients: `base_url = "https://api.agenticcontrolplane.com/v1"`

Same responses, now metered.

**Be clear about what this does and doesn't get you.** The proxy prices every call, meters cache economics, and applies policy to model calls and to the tool-use blocks the model *asks for*. It cannot see or block what your code actually *executes* — if the model asks for `delete_file` and your code runs it, ACP saw the request, not the execution. That's the interception plane, and a base-URL swap doesn't provide it.

**Your coverage:** proxy ✓ · interception ✗ — by construction, not misconfiguration. If your code executes tools, add the `@governed` decorator from the framework SDKs (previous section) to close the gap.

## I already use a gateway (LiteLLM, OpenRouter, …)

The chain-order principle: **ACP sits nearest the agent.** Governance and pricing should see the agent's true intent — what it actually asked for — while routing, caching, and compression belong downstream, between ACP and the provider. A gateway upstream of ACP rewrites or caches requests before ACP sees them, which blinds both policy and pricing.

Honest current state:

- **Tested and supported today:** ACP's proxy forwards directly to the providers (Anthropic-native, OpenAI-compatible, and the OpenAI Responses passthrough). Your interception plane — hooks or decorators from the sections above — is unaffected by any gateway choice; it doesn't touch the model path.
- **Not yet shipped:** a per-workspace configurable upstream, so ACP can forward to *your* gateway (agent → ACP → LiteLLM/OpenRouter → provider). It's designed and on the roadmap. Before we claim support for any specific gateway, we'll test that it passes real token-usage fields back through — a downstream layer that rewrites or caches without honest usage reporting would silently corrupt your cost data, and we'd rather say "untested" than guess.
- **Not supported:** putting your gateway between the agent and ACP. It works mechanically but breaks the principle above — ACP would meter post-rewrite traffic, not agent intent.

**Your coverage:** interception per your harness/framework section above, unchanged · proxy ✓ only in direct-to-provider mode, for now. If chaining ACP in front of your gateway is what's blocking you, [tell us which gateway](https://github.com/agentic-control-plane) — the per-gateway tests get prioritized by real demand.

## Check what you actually have

Two quick reads in [the console](https://cloud.agenticcontrolplane.com):

- **Interception live?** [Logs](https://cloud.agenticcontrolplane.com/logs) shows tool calls within seconds of your agent's next action.
- **Proxy live?** Any run showing a dollar cost was metered; a run with tool calls but no cost means model calls are bypassing the proxy.

A `coverage` doctor command and a per-agent Coverage card in the console — reporting interception / proxy per agent in exactly this shape — are in progress under the same effort as this page.
