Skip to main content

ACP — AI Control Plane: deterministic governance and execution control for enterprise AI agents.

Project description

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:

  1. acp init
  2. start Docker Desktop
  3. acp up
  4. export ACP_INTERCEPTOR_URL=http://localhost:8080
  5. export ACP_BEARER_TOKEN=...
  6. 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

ACP — AI Control Plane 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

ACP — AI Control Plane governed request sequence

Typical governed flow:

  1. the agent calls a governed function through the ACP SDK
  2. the interceptor validates JWT identity and normalizes the request
  3. OPA / Rego evaluates policy for the tool, action, and claims
  4. ACP records the decision and exposes it in the dashboard
  5. the SDK executes only on allow, waits for review on escalate, and blocks on deny

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

Overview — governance posture and live activity

Live activity — real-time enforcement stream

Decisions & approvals

Governance decisions — allow / deny / escalate analytics

Approvals — human-in-the-loop escalation queue

Registry & policies

Agent registry — identity catalog for policy enforcement

Policies — Rego catalog from the interceptor

Policy detail — mortgage underwriting rules

Forensics

Traces — governance trace investigation


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:

  1. choose an ACP tool id, for example weather_api
  2. add tool-to-role mapping in ~/.acp/policies/rbac.rego
  3. route the tool in ~/.acp/policies/router.rego
  4. add or reuse a domain policy file such as weather.rego
  5. mint and export ACP_BEARER_TOKEN
  6. make sure the JWT agent_id claim matches @governed_tool(agent_id=...)
  7. 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:8080
  • ACP_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-agent
  • agent_id=texas-weather-agent
  • roles=["weather"]
  • iss=acp-dev
  • aud=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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

acp_ai-0.2.8.tar.gz (79.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

acp_ai-0.2.8-py3-none-any.whl (106.0 kB view details)

Uploaded Python 3

File details

Details for the file acp_ai-0.2.8.tar.gz.

File metadata

  • Download URL: acp_ai-0.2.8.tar.gz
  • Upload date:
  • Size: 79.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.6

File hashes

Hashes for acp_ai-0.2.8.tar.gz
Algorithm Hash digest
SHA256 1b524c2bd615755aa6be13dacf723ebd56193f89c4d4ddbe11c28f072bba5070
MD5 e5e57e4aa40eecd7db8ce4d393b4c4d3
BLAKE2b-256 1dbee7587822f4d638b1a6402fdda4306c439826187a34b89077bcedab7de2ae

See more details on using hashes here.

File details

Details for the file acp_ai-0.2.8-py3-none-any.whl.

File metadata

  • Download URL: acp_ai-0.2.8-py3-none-any.whl
  • Upload date:
  • Size: 106.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.6

File hashes

Hashes for acp_ai-0.2.8-py3-none-any.whl
Algorithm Hash digest
SHA256 6478408fabf37989d24b6e90d80bef71ebc31abd2441053f5e75f46aab1e53e7
MD5 d655d9ec7aead259c26a855c513df180
BLAKE2b-256 6b25325136a04228d6f18dd072ccfb487fe2194373cd13520f9395fe9447b9d1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page