This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Reason given by maintainers: Renamed to truceptor — use pip install truceptor
ACP — AI Control Plane
Deterministic governance and execution control plane for enterprise AI agents and autonomous systems.
Note: “ACP” means many things in other industries (medical, political, nonprofit, and more). In this project it always means ACP — AI Control Plane, not a generic acronym.
Add governance, approvals, policy enforcement, and execution visibility to AI agents in minutes.
Works with CrewAI, LangGraph, Strands, Google ADK, MCP tools, and custom Python workflows.
Requires: Docker Desktop (Compose v2).
Quick start
Make sure Docker Desktop is already running before you start ACP.
pip install acp-ai
acp init # creates starter policies in ~/.acp/policies
acp up
acp dashboard # open governance UI
| Step | Command |
|---|---|
| Install | pip install acp-ai |
| Initialize policies | acp init |
| Start stack | acp up |
| Open UI | acp dashboard → http://localhost:3090/dashboard/ |
| Stop | acp down |
For a real local integration, the usual sequence is:
acp init- start Docker Desktop
acp upexport ACP_INTERCEPTOR_URL=http://localhost:8080export ACP_BEARER_TOKEN=...- run your governed agent
If Docker is not already running, acp up will fail with Docker daemon / compose connection errors.
Why ACP — AI Control Plane?
Most agents call tools, APIs, and other agents directly. Teams then scatter rules across Python, workflows, and frameworks:
if supplier_risk_score > threshold:
require_human_approval()
That becomes inconsistent, hard to audit, easy to bypass, and duplicated everywhere.
ACP — AI Control Plane centralizes governance outside agent code:
| Capability | What you get |
|---|---|
| Centralized governance | One place for rules, not copy-paste per team |
| Policy enforcement | OPA/Rego evaluates every governed call |
| Approvals | Escalate high-risk actions to humans |
| A2A governance | Governed agent-to-agent calls |
| A2T governance | Governed agent-to-tool calls |
| Audit & visibility | Decisions, traces, registry in one dashboard |
Architecture
Agent runtime -> ACP SDK -> Interceptor / Gateway -> OPA / Rego -> allow | deny | escalate -> governed execution
ACP sits at the execution boundary:
- agent frameworks keep reasoning and orchestration
- the interceptor validates identity, routes policy, and records audit traces
- OPA / Rego returns deterministic allow, deny, or escalate decisions
- only allowed or approved requests reach tools, APIs, MCP servers, or other agents
Request sequence
Typical governed flow:
- the agent calls a governed function through the ACP SDK
- the interceptor validates JWT identity and normalizes the request
- OPA / Rego evaluates policy for the tool, action, and claims
- ACP records the decision and exposes it in the dashboard
- the SDK executes only on
allow, waits for review onescalate, and blocks ondeny
Dashboard
The ACP — AI Control Plane dashboard is a core differentiator: live allow/deny/escalate decisions, approvals, agent registry, and policy catalog. Open http://localhost:3090/dashboard/ after acp up.
Overview & activity
Decisions & approvals
Registry & policies
Forensics
Deployment modes
| Mode | How | Best for |
|---|---|---|
| Local | acp up via pip + Docker |
Demos, dev, quickstart |
| SDK | @governed_tool in your agent code |
CrewAI, LangGraph, Strands, custom Python |
| Gateway | Single origin on :3090 (dashboard + API proxy) |
Local unified URL; pattern for prod ingress |
| Cloud / self-hosted | Docker Compose, Kubernetes, ECS/EKS on AWS/Azure/GCP | Team or enterprise rollout |
Local endpoints
| URL | Purpose |
|---|---|
| http://localhost:3090/dashboard/ | Governance dashboard |
| http://localhost:8080 | Interceptor API (/tool-call, /api/v1/*) |
Self-hosted (example)
https://acp.your-company.example
Example: governed tool
Set ACP_INTERCEPTOR_URL and ACP_BEARER_TOKEN before defining a @governed_tool.
The decorator constructs its ACP client at decoration time, so setting those env vars later inside main() is too late.
import os
from acp import governed_tool
# Set env vars before decorator evaluation.
os.environ.setdefault("ACP_INTERCEPTOR_URL", "http://localhost:8080")
os.environ.setdefault("ACP_BEARER_TOKEN", "<dev-jwt>")
@governed_tool(
agent_id="texas-weather-agent",
tool="weather_api",
action="read_weather",
)
def get_texas_weather(city: str):
return {"city": city, "status": "pending_review"}
The AI Control Plane intercepts the call, evaluates policy, then allows, denies, or escalates.
tool="weather_api" is the governed ACP tool id. It does not have to match the Python function name (get_texas_weather). ACP policy keys on tool, not the Python symbol name.
The JWT agent_id claim must match agent_id="texas-weather-agent" in @governed_tool(...).
Example: policy (Rego)
package acp.policy
allow {
input.identity.role == "supply-chain-manager"
input.action.tool == "supplier_approval"
input.risk_score < 70
}
Edit policies in ~/.acp/policies/ after acp init.
Adding a new governed tool
acp init creates starter policy files in ~/.acp/policies/, but you still need to wire new tools into policy yourself.
For a brand-new governed tool, update all of these:
- choose an ACP tool id, for example
weather_api - add tool-to-role mapping in
~/.acp/policies/rbac.rego - route the tool in
~/.acp/policies/router.rego - add or reuse a domain policy file such as
weather.rego - mint and export
ACP_BEARER_TOKEN - make sure the JWT
agent_idclaim matches@governed_tool(agent_id=...) - run the agent
Two valid patterns:
Pattern 1: reuse an ACP tool bucket
Use one ACP tool id for multiple Python functions in the same policy domain.
@governed_tool(
agent_id="texas-weather-agent",
tool="weather_api",
action="read_weather",
)
def get_texas_weather(city: str):
...
~/.acp/policies/rbac.rego
"weather_api": ["weather"],
~/.acp/policies/router.rego
decision = weather.decision {
input.tool == "weather_api"
rbac.decision.decision == "allow"
}
~/.acp/policies/weather.rego
package acp.weather
default decision = {
"decision": "allow",
"reason": "weather_action_allowed",
"policy": "acp/weather",
}
decision = {
"decision": "deny",
"reason": "weather_action_not_permitted",
"policy": "acp/weather",
} {
not input.action == "read_weather"
not input.action == "read_weather_batch"
}
Pattern 2: add a brand-new ACP tool id
If you want policy to key directly on a new id such as get_texas_weather, add that id to both rbac.rego and router.rego, then route it to the right domain policy file.
If your starter router.rego or rbac.rego references a tool id, make sure the corresponding domain policy file also exists.
Local JWT dev example
Local governed /tool-call requests require a bearer token when JWT auth is enabled. ACP_INTERCEPTOR_URL alone is not enough.
Set:
ACP_INTERCEPTOR_URL=http://localhost:8080ACP_BEARER_TOKEN=<signed-jwt>
If ACP_BEARER_TOKEN is missing, governed calls may fail with 401 Unauthorized / missing bearer token.
One dev-friendly way to mint a token is:
python -m pip install pyjwt cryptography
export ACP_BEARER_TOKEN="$(
python - <<'PY'
from pathlib import Path
import time
import jwt
private_key = (Path.home() / ".acp" / "jwt" / "private.pem").read_text()
token = jwt.encode(
{
"sub": "agent:texas-weather-agent",
"agent_id": "texas-weather-agent",
"roles": ["weather"],
"iss": "acp-dev",
"aud": "acp-interceptor",
"exp": int(time.time()) + 3600,
},
private_key,
algorithm="RS256",
)
print(token)
PY
)"
Use these claims for local development:
sub=agent:texas-weather-agentagent_id=texas-weather-agentroles=["weather"]iss=acp-devaud=acp-interceptor
agent_id in the JWT must match the agent_id passed to @governed_tool(...).
Example: governance flow
Supply Chain Agent
→ ACP — AI Control Plane validates identity (JWT)
→ OPA evaluates policy
→ Decision: ESCALATE
→ Human approves in dashboard
→ Execution resumes
What the AI Control Plane provides
- Policy enforcement — OPA/Rego (Cedar on roadmap)
- Identity — JWT from Okta, Auth0, Keycloak, or your IdP
- Approvals — human-in-the-loop for risky actions
- Observability — dashboard for decisions, traces, agents, tools
- Agent registry — lightweight catalog of agents and capabilities
- Framework-friendly — keep CrewAI / LangGraph / Strands for reasoning; govern execution here
Philosophy
Orchestration frameworks handle reasoning, planning, and workflows.
ACP — AI Control Plane handles governance, trust, approvals, policy, and auditability.
Reasoning stays autonomous. Execution stays governed.
Roadmap
- Gateway / proxy execution mode (production hardening)
- MCP-native governance
- Policy studio and replay
- Enterprise topology views
- Multi-cloud deployment templates
License
MIT License
Release files for acp-ai 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| acp_ai-0.3.0.tar.gz | 79.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| acp_ai-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 185.0 kB
Release files / acp_ai-0.3.0.tar.gz
| Download URL | acp_ai-0.3.0.tar.gz |
|---|---|
| Size | 79.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
967081089af7d080b31847cfe868a7ec9c7ca2868e64df68d344793be27621d6
|
|
BLAKE2b-256 checksum How to use checksums |
e798716a463e08271ce3564ec93bcebbb9cef811714aea8abcfd7aa114d22011
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.6
|
Release files / acp_ai-0.3.0-py3-none-any.whl
| Download URL | acp_ai-0.3.0-py3-none-any.whl |
|---|---|
| Size | 105.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87638e97eab5a1aab328718cbb2ee1c530c553906e11ccbf61c8087807e7acc0
|
|
BLAKE2b-256 checksum How to use checksums |
080260280fad638a1b6a5f7b32b28a41329a4c006efd4195d75c1c11e79cbbda
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.6
|