# Agentic Control Plane (ACP) — Complete Documentation Generated: 2026-09-04 > See, price, and control every tool call your AI agents make. ACP checks each call against your policy before it runs (allow / flag / deny / ask), prices every model call — including subscription traffic at API rates — and audits every action. It also solves the Three-Party Problem — where user identity is lost between the LLM and your backend — with verified identity on every call. Available as open-source npm modules (GatewayStack, MIT licensed) and as a managed cloud service (ACP Cloud). --- ## What Is an Agentic Control Plane? An Agentic Control Plane (ACP) — also called an agent control plane — is the identity and governance layer for AI agents. It sits between the agents and the systems they interact with — your backend services, third-party APIs, LLM providers, and other agents. It ensures that every agent action is: - **Identified** — bound to a real, verified user or agent with a cryptographic identity - **Authorized** — checked against your policies - **Safe** — sensitive data is detected and redacted before reaching the model - **Constrained** — rate limits and budget caps are enforced per user - **Routed** — sent to the right backend with the user's identity intact - **Auditable** — logged with full context: identity, policy decisions, and cost This applies whether the action is a user asking ChatGPT to query your CRM, a LangChain agent calling your API, or one agent delegating to another agent. The ACP governs the trust boundary — not the model layer, not the app layer, but the identity and governance layer in between. ### The Three-Party Problem Traditional web apps have two parties: a user and a backend. The user logs in, the backend verifies their identity, and every subsequent request carries that identity context. Authentication is solved. AI apps break this model. They introduce a third party: the LLM runtime. Here's what actually happens: 1. The user authenticates with the LLM (signs into ChatGPT, opens Claude, launches Cursor) 2. The user sends a prompt 3. The LLM decides it needs to call a tool — your API, your database, your internal service 4. The LLM calls your backend with... a shared API key Your backend receives the request. But it has no idea *who* made it. The identity link between user and backend is severed. The LLM sits in the middle, holding one credential on each side, bridging neither. This is the Three-Party Problem. And it's the root cause of nearly every governance failure in production AI systems. ### The Parrot at the Bank Imagine you have a really smart parrot. You send it to the bank to withdraw money from your account. The parrot flies in and says: "I'd like to withdraw $200 from David's account." But you can't just trust a parrot. It could be lying. Confused. Intercepted on the way. The bank has no way to verify that this parrot is actually acting on your behalf. The parrot is the LLM. Your backend is the bank. And right now, most AI systems are trusting the parrot. The fix isn't smarter parrots. It's a security checkpoint at the front door of the bank — one that verifies a sealed, tamper-proof letter from a trusted authority before the parrot gets anywhere near a teller. The checkpoint verifies the seal, checks the rules, counts how many trips the parrot has already made today, stamps the request with the verified identity, and writes the whole transaction in an immutable ledger. That checkpoint is the Agentic Control Plane. ### Why This Matters Now Three platform shifts are happening simultaneously: **Protocol standardization.** OpenAI's Apps SDK lets ChatGPT call any HTTP endpoint on behalf of a user. Anthropic's Model Context Protocol (MCP) gives LLMs a standard way to discover and invoke tools. The infrastructure for agents to take real actions now exists as an open standard — but MCP has no built-in governance. **Enterprise agent rollouts.** Every large company is deploying internal copilots and agent workflows. These aren't experiments anymore — they're production systems that query patient records, create Jira tickets, process refunds, pull credit reports, and modify infrastructure. Real actions. Real consequences. **Regulatory pressure.** HIPAA, SOC 2, GDPR, and PCI DSS all have direct implications for AI-mediated access to protected data. Regulators aren't going to accept "we don't know which user triggered that model call" as an answer. ### What Goes Wrong Without One **Shadow AI.** Teams integrate AI tools without security review. Shared API keys get passed around. Nobody knows which users are making which requests. When something goes wrong, there's no way to trace it back to a person or a policy gap. **Data Leakage.** Without content filtering at the gateway, sensitive data flows into LLM prompts unchecked. Patient names, social security numbers, credit card numbers — all sent to third-party models with no detection, no redaction, and no record. **No Audit Trail.** A compliance officer asks: "Who accessed patient data through the AI assistant last Tuesday?" Without identity binding and structured logging, the honest answer is: "We don't know." **Runaway Costs.** An agent loop fires 10,000 API calls in a minute. A single user burns through the team's monthly LLM budget overnight. Without per-user rate limits and budget caps, there's no guardrail until the invoice arrives. ### How an ACP Fits in Your Stack An ACP occupies a distinct layer. It complements — not replaces — your existing infrastructure. **It's not an LLM routing gateway.** Tools like Portkey, LiteLLM, and OpenRouter focus on model selection and load balancing. An ACP doesn't choose which model to use. It governs who can use it and what they're allowed to do. **It's not an agent framework.** LangChain, CrewAI, and AutoGen help you *build* agents. An ACP doesn't build agents. It governs them. The agent framework decides *what* to do. The ACP decides *whether it's allowed*. **It's not a traditional API gateway.** Kong, Apigee, and AWS API Gateway handle HTTP traffic management. They don't understand the Three-Party Problem. They can verify a token, but they can't bind LLM-forwarded requests to the originating user. Use all of them. Your API gateway handles TLS and global routing. Your LLM gateway handles model selection and fallback. Your agent framework builds the workflows. Your Agentic Control Plane governs the trust boundary between the AI and your backend. --- ## Architecture: The Six Governance Layers An Agentic Control Plane implements six governance concerns. Each is composable. Each addresses one piece of the trust problem. Together, they form a pipeline that every AI-initiated request passes through before reaching your backend. ### 1. Identity — Who Is Calling? Every request must be bound to a verified user. This means validating OAuth tokens (RS256 JWTs) against your identity provider's JWKS endpoint and extracting the user's identity — their `sub` claim, scopes, roles, and tenant context. This is the foundation. Without verified identity, nothing else works. You can't enforce policies if you don't know who's asking. You can't attribute costs if you don't know who spent them. You can't audit actions if you don't know who took them. ### 2. Content Safety — Is the Data Clean? Before a request reaches the model or your backend, the control plane inspects it for sensitive content. PII detection catches social security numbers, email addresses, credit card numbers, phone numbers, and other regulated data patterns. Depending on your policy, the control plane can redact, mask, flag, or block the request entirely. ### 3. Policy Enforcement — Is This Allowed? A deny-by-default policy engine checks whether the authenticated user has permission to perform the requested action. Can this user call this tool? Access this model? Query this data source? Policies are defined by role, scope, or custom claims. ### 4. Usage Governance — Within Budget? Per-user rate limits prevent runaway loops. Budget caps track cumulative spend and reject requests that would exceed the user's allocation. Agent guard detects anomalous patterns — 500 identical tool calls in 30 seconds is almost certainly a loop, not a legitimate user request. ### 5. Secure Routing — Where Does It Go? The control plane routes the validated request to the appropriate backend with the user's verified identity injected. Your backend receives `x-user-uid` — the verified `sub` claim — on every request. It never sees a shared API key. It always knows exactly which user the LLM is acting for. Routing also includes SSRF protection, auth mode selection (forwarding user tokens vs. injecting service credentials), and scope enforcement per outbound destination. ### 6. Audit Trail — What Happened? Every action is logged with structured metadata: who made the request, what tool was called, what policy decision was made, whether PII was detected, what it cost, whether it was approved or denied. This isn't generic HTTP logging. It's a purpose-built audit trail for AI agents — identity-attributed, policy-aware, and compliance-ready. --- ## GatewayStack: Open-Source Reference Implementation GatewayStack is the open-source (MIT licensed) reference implementation of the Agentic Control Plane pattern. It's built as six composable npm modules — each handles one governance concern, and they compose into a full pipeline. ### Module Breakdown Modules ship as an Express middleware package plus, for most, a `-core` package (framework-agnostic, pure functions). | Module | npm Package | What it does | |--------|-------------|-------------| | **identifiabl** | @gatewaystack/identifiabl | RS256 JWT verification and identity normalization. Validates tokens from any OIDC provider and maps them to a consistent user object on `req.user`. | | **transformabl** | @gatewaystack/transformabl | PII detection, redaction, and content safety classification. Catches SSNs, emails, credit cards in prompts before they reach the model. | | **validatabl** | @gatewaystack/validatabl | Deny-by-default policy engine. Define who can use which tools and models based on roles, scopes, or custom claims. | | **limitabl** | @gatewaystack/limitabl | Per-user rate limits, budget tracking, and agent runaway detection. Pre-flight checks reject requests that would exceed spend limits. | | **proxyabl** | @gatewaystack/proxyabl | Identity-aware routing to tool backends and LLM providers. SSRF protection, auth injection, and scope enforcement per outbound call. | | **explicabl** | @gatewaystack/explicabl | Structured audit logging of every tool call, policy decision, and cost attribution. Health endpoints for monitoring. | Supporting packages: | Package | Purpose | |---------|---------| | **request-context** | AsyncLocalStorage-based request context propagation across the pipeline | ### Architecture Pattern Each `-core` package exports pure functions with no framework dependency: ```ts // identifiabl-core: verify a token import { verifyToken } from "@gatewaystack/identifiabl-core"; const user = await verifyToken(token, { issuer, audience }); // validatabl-core: check a policy import { checkPolicy } from "@gatewaystack/validatabl-core"; const allowed = checkPolicy(user, "tool:crm:read"); // limitabl-core: pre-flight budget check import { checkBudget } from "@gatewaystack/limitabl-core"; const ok = await checkBudget(user.sub, { maxSpend: 500 }); ``` ### Repository Layout | Path | Description | |------|-------------| | `packages/` | Six `-core` packages + six Express middleware wrappers + `request-context` | | `apps/gateway-server` | Express reference server wiring all six layers | | `apps/admin-ui` | Vite/React dashboard that polls `/health` | | `demos/` | MCP issuer + ChatGPT Apps SDK connectors | | `tools/` | Echo server, mock tool backend, Cloud Run deploy helper | | `tests/` | Vitest smoke tests (135 tests across 17 files) | | `docs/` | Auth0 walkthroughs, conformance output, endpoint references | --- ## Getting Started with GatewayStack (Self-Hosted) GatewayStack implements the Agentic Control Plane as composable npm modules. Start with identity — it's the foundation — then add layers as your governance needs grow. ### Prerequisites - Node.js **20+** - npm **10+** - An OIDC provider issuing RS256 access tokens (Auth0, Okta, Entra ID, Keycloak, etc.) ### Step 1: Install identifiabl ```bash npm install @gatewaystack/identifiabl express ``` ### Step 2: Add identity verification ```ts import express from "express"; import { identifiabl } from "@gatewaystack/identifiabl"; const app = express(); app.use(identifiabl({ issuer: process.env.OAUTH_ISSUER!, audience: process.env.OAUTH_AUDIENCE!, })); app.get("/api/me", (req, res) => { res.json({ user: req.user.sub, scopes: req.user.scope }); }); app.listen(8080); ``` Every request now requires a valid RS256 JWT. `req.user` contains the verified identity — sub, email, scopes, and any custom claims from your identity provider. ### Step 3: Add content safety ```bash npm install @gatewaystack/transformabl ``` ```ts import { transformabl } from "@gatewaystack/transformabl"; // After identifiabl app.use("/tools", transformabl({ blockThreshold: 80 })); ``` Prompts are now scanned for PII (SSNs, emails, credit cards) before reaching the model. ### Step 4: Add policy enforcement ```bash npm install @gatewaystack/validatabl ``` ```ts import { validatabl } from "@gatewaystack/validatabl"; app.use("/tools", validatabl({ requiredPermissions: ["tool:read"], })); ``` Requests are now checked against the user's scopes and roles. ### Step 5: Add rate limiting and budgets ```bash npm install @gatewaystack/limitabl ``` ```ts import { limitabl } from "@gatewaystack/limitabl"; app.use("/tools", limitabl({ rateLimit: { windowMs: 60_000, maxRequests: 100 }, budget: { maxSpend: 500, periodMs: 86_400_000 }, })); ``` Each user is now rate-limited to 100 requests per minute and $500/day in spend. ### Step 6: Add audit logging ```bash npm install @gatewaystack/explicabl ``` ```ts import { createConsoleLogger, explicablLoggingMiddleware } from "@gatewaystack/explicabl"; app.use(explicablLoggingMiddleware(createConsoleLogger())); ``` Every tool call is now logged with the user's identity, the policy decision, and cost attribution. ### Full Pipeline Wire all six layers together: ```bash npm install @gatewaystack/identifiabl @gatewaystack/transformabl \ @gatewaystack/validatabl @gatewaystack/limitabl \ @gatewaystack/proxyabl @gatewaystack/explicabl \ @gatewaystack/request-context express ``` ```ts import express from "express"; import { runWithGatewayContext } from "@gatewaystack/request-context"; import { identifiabl } from "@gatewaystack/identifiabl"; import { transformabl } from "@gatewaystack/transformabl"; import { validatabl } from "@gatewaystack/validatabl"; import { limitabl } from "@gatewaystack/limitabl"; import { createProxyablRouter, configFromEnv } from "@gatewaystack/proxyabl"; import { createConsoleLogger, explicablLoggingMiddleware } from "@gatewaystack/explicabl"; const app = express(); app.use(express.json()); // 1. Request context for downstream layers app.use((req, _res, next) => { runWithGatewayContext( { request: { method: req.method, path: req.path } }, () => next() ); }); // 2. Audit logging app.use(explicablLoggingMiddleware(createConsoleLogger())); // 3. Identity verification app.use(identifiabl({ issuer: process.env.OAUTH_ISSUER!, audience: process.env.OAUTH_AUDIENCE!, })); // 4. Content safety app.use("/tools", transformabl({ blockThreshold: 80 })); // 5. Policy enforcement app.use("/tools", validatabl({ requiredPermissions: ["tool:read"] })); // 6. Rate limits and budgets app.use("/tools", limitabl({ rateLimit: { windowMs: 60_000, maxRequests: 100 }, budget: { maxSpend: 500, periodMs: 86_400_000 }, })); // 7. Route to backends app.use("/tools", createProxyablRouter(configFromEnv(process.env))); app.listen(8080, () => console.log("GatewayStack running on :8080")); ``` ### Health Checks ```ts app.get("/health", (_req, res) => { res.json({ status: "ok", version: process.env.npm_package_version }); }); app.get("/health/auth", async (_req, res) => { try { const issuer = process.env.OAUTH_ISSUER!; const disco = await fetch(`${issuer}.well-known/openid-configuration`); const { jwks_uri } = await disco.json(); const jwks = await fetch(jwks_uri); const { keys } = await jwks.json(); res.json({ status: "ok", issuer, jwks_uri, keys_available: keys.length, }); } catch (err) { res.status(503).json({ status: "error", message: String(err) }); } }); ``` ### Environment Variables ```bash OAUTH_ISSUER=https://your-tenant.us.auth0.com/ OAUTH_AUDIENCE=https://your-api-audience ``` --- ## Getting Started with ACP Cloud (Managed) ### Step 1: Sign up and see your dashboard Go to [cloud.agenticcontrolplane.com](https://cloud.agenticcontrolplane.com/login) and sign in with Google or email. You'll land on your home dashboard — a quick-launch pad with suggested prompts, your agents, and recent conversations. ### Step 2: Connect your data and tools Click **Data** in the top nav to give your agents context: - **Upload files** — drag in CSV, Excel, PDF, TXT, or JSON files (up to 10MB each) - **Add web sources** — paste any public URL and we'll extract the content - **Connect services** — link GitHub, Jira, Linear, Salesforce, and more with one click via OAuth ### Step 3: Create an agent Click **Agents** in the top nav, then **+ Create Agent**. Give it a name, describe what it should do, pick a model, and choose a schedule. For example: "Monitor Hacker News for posts about agentic AI and email me a summary every hour." ### Step 4: Chat with everything you've connected Click **Chat** to talk to your data. Your AI assistant has access to all your connected tools — ask questions across files, services, and agents in one conversation. Every tool call shows what was accessed, is scoped to your identity, and is logged automatically. ### Step 5: Trigger agents from external systems Every agent gets an HTTP trigger endpoint: ```bash export ACP_KEY="your-api-key-here" curl -X POST https://api.agenticcontrolplane.com//agents//run \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACP_KEY" \ -d '{"input": "Summarize open support tickets tagged urgent"}' ``` Create an API key from **Settings > API Keys**, then wire the endpoint into your automation. --- ## Agent HTTP Triggers API Reference Trigger any agent in your workspace with a single HTTP request. Connect your agents to n8n, Zapier, Make, or any system that can send a POST. ### Endpoint ``` POST https://api.agenticcontrolplane.com//agents//run ``` ### Authentication ``` Authorization: Bearer $ACP_KEY ``` Create API keys from **Settings > API Keys** in your dashboard. All authentication methods supported by ACP work here: API keys (`gsk_*`), Firebase tokens, and external JWTs. ### Request Body ```json { "input": "Find all cold leads from last week and draft follow-up emails", "context": { "region": "EMEA", "quarter": "Q1", "maxLeads": "20" }, "stream": false } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `input` | string | Yes | The goal or instruction for the agent | | `context` | object | No | Key-value pairs injected into the agent's system prompt | | `stream` | boolean | No | `true` returns SSE events. Default: `false` | ### Response (non-streaming) ```json { "id": "run_abc123", "status": "completed", "output": "I found 12 cold leads from last week...", "conversationId": "conv_xyz", "usage": { "promptTokens": 1500, "completionTokens": 800, "toolCallCount": 3, "estimatedCostCents": 2.45, "model": "gpt-4o", "durationMs": 4200 }, "stopReason": "goal_complete" } ``` ### Response (streaming) Set `"stream": true` to receive Server-Sent Events: ``` data: {"type":"text","text":"Searching for cold leads..."} data: {"type":"tool_calls","toolCalls":[{"id":"tc_1","name":"salesforce.search","arguments":"{...}"}]} data: {"type":"governance","tool":"salesforce.search","decision":"allowed","layers":{"identity":"verified","policy":"allowed","rate_limit":"under_limit"}} data: {"type":"tool_result","toolCallId":"tc_1","name":"salesforce.search","result":"{...}"} data: {"type":"text","text":"Found 12 cold leads. Drafting follow-up emails..."} data: {"type":"done","conversationId":"conv_xyz","usage":{"promptTokens":1500,"completionTokens":800}} ``` ### Governance Every agent trigger runs through the same governance pipeline as dashboard chat: - **Identity** — the API key identifies the caller - **Tool governance** — each tool call goes through policy enforcement, PII detection, rate limiting, and scope checking - **Audit logging** — the trigger plus every tool call is logged with full identity context - **Billing** — the trigger counts as one tool call for plan billing ### curl Example ```bash export ACP_KEY="your-api-key-here" curl -X POST https://api.agenticcontrolplane.com/acme/agents/PROFILE_ID/run \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACP_KEY" \ -d '{ "input": "Summarize open support tickets from this week", "context": { "team": "engineering" } }' ``` ### Python Example ```python import requests response = requests.post( "https://api.agenticcontrolplane.com/acme/agents/PROFILE_ID/run", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "input": "Check inventory levels and alert if any item is below threshold", "context": {"warehouse": "east-coast"}, }, ) result = response.json() print(result["output"]) print(f"Cost: {result['usage']['estimatedCostCents']}c in {result['usage']['durationMs']}ms") ``` ### Error Responses | Status | Cause | |--------|-------| | `400` | Missing `input`, invalid `context`, unconfigured model | | `401` | Missing or invalid API key | | `404` | Invalid `profileId` | | `429` | Per-user daily LLM cost cap hit | --- ## Integration Guide: Auth0 Auth0 is the most common identity provider for ACP deployments. ### Step 1: Create an Auth0 API In the Auth0 Dashboard, go to **Applications > APIs > Create API**. | Field | Value | |-------|-------| | Name | `ACP Gateway` | | Identifier (Audience) | `https://api.agenticcontrolplane.com/your-slug` | | Signing Algorithm | **RS256** (required — ACP rejects HS256) | ### Step 2: Configure permissions Under your API's **Permissions** tab, add scopes: ``` salesforce:read salesforce:write github:read github:write slack:read slack:write ``` Enable RBAC: go to Settings tab, enable "Enable RBAC" and "Add Permissions in the Access Token." ### Step 3: Set up roles | Role | Permissions | |------|-------------| | Sales (Read Only) | `salesforce:read` | | Sales (Full Access) | `salesforce:read`, `salesforce:write` | | Developer | `github:read`, `github:write`, `slack:read` | | Admin | All permissions | ### Step 4: Configure ACP In ACP dashboard, go to **Settings > Identity Providers**: | Field | Value | |-------|-------| | Issuer | `https://your-tenant.auth0.com/` | | Audience | `https://api.agenticcontrolplane.com/your-slug` | | JWKS URI | Leave blank (auto-discovered) | | Scope Claim | `scope` | | Role Claim | `permissions` | | Tenant Claim | `org_id` | ### Auth0 Claim Mapping | Auth0 Claim | ACP Field | Example | |-------------|-----------|---------| | `sub` | `identity.sub` | `auth0\|8f3a2b1c9d4e5f6a` | | `iss` | `identity.issuer` | `https://your-tenant.auth0.com/` | | `scope` | `identity.scopes` | `["openid", "profile", "email"]` | | `permissions` | `identity.roles` | `["salesforce:read", "github:write"]` | | `org_id` | `identity.tenantId` | `org_acme_corp` | | `email` | `identity.email` | `alice@acme.com` | ### Step 5: Configure tool scopes In **Policies > Tool Scopes**, map permissions to tools: ```json { "salesforce.query": ["salesforce:read"], "salesforce.createRecord": ["salesforce:write"], "github.listRepos": ["github:read"], "github.createIssue": ["github:write"] } ``` --- ## Integration Guide: LangChain Add governance to your LangChain agent without changing frameworks. ### Option 1: MCP Client SDK (Recommended) ```python from langchain_mcp import MCPToolkit # Connect to your ACP workspace toolkit = MCPToolkit( server_url="https://api.agenticcontrolplane.com/your-slug", transport="streamable-http", headers={ "Authorization": f"Bearer {user_jwt}" } ) # Get all tools available to this user tools = toolkit.get_tools() # Use with any LangChain agent from langchain.agents import create_tool_calling_agent agent = create_tool_calling_agent(llm, tools, prompt) ``` ACP returns only the tools the authenticated user has access to. ### Option 2: OpenAI-Compatible Proxy ```python from langchain_openai import ChatOpenAI llm = ChatOpenAI( model="gpt-4o", openai_api_base="https://api.agenticcontrolplane.com/your-slug/v1", default_headers={ "Authorization": f"Bearer {user_jwt}" } ) ``` ### Option 3: Wrap Individual Tools ```python import httpx from langchain.tools import tool ACP_URL = "https://api.agenticcontrolplane.com/your-slug" @tool def salesforce_query(query: str, user_token: str) -> str: """Query Salesforce records using SOQL.""" response = httpx.post( f"{ACP_URL}/tools/salesforce.query", json={"query": query}, headers={"Authorization": f"Bearer {user_token}"} ) if response.status_code == 403: return "Access denied: insufficient permissions" return response.json() ``` ### What Happens on Every Tool Call 1. **Identity verification** — ACP verifies the JWT (RS256, JWKS-cached) 2. **Scope enforcement** — Token scopes checked against tool requirements 3. **Immutable rules** — SSN, credit card, SSRF pattern scanning 4. **Content scanning** — Configurable PII detection 5. **Rate limiting** — Per-user rate limits 6. **Execution** — Backend tool called with user's own credentials 7. **Audit logging** — Full identity attribution logged ### Per-User Identity in Multi-User Apps ```python async def handle_user_request(user_jwt: str, question: str): toolkit = MCPToolkit( server_url="https://api.agenticcontrolplane.com/your-slug", headers={"Authorization": f"Bearer {user_jwt}"} ) tools = toolkit.get_tools() agent = create_tool_calling_agent(llm, tools, prompt) return await agent.ainvoke({"input": question}) ``` Each user gets their own tools (scoped to permissions), rate limits, and audit trail. --- ## Integration Guide: External MCP Servers ACP can act as an MCP client — connecting to external MCP servers and consuming their tools through the governance pipeline. ### Register an MCP Server In ACP dashboard: **Connectors > MCP Servers > Add Server**. | Field | Value | |-------|-------| | Name | A descriptive name (e.g. `internal-docs`) | | Server ID | Short identifier (e.g. `docs`) | | URL | MCP server endpoint URL | | Transport | Streamable HTTP or SSE | | Auth header | (Optional) Bearer token or API key | Via the API: ```bash curl -X POST \ -H "Authorization: Bearer $ACP_KEY" \ -H "Content-Type: application/json" \ https://api.agenticcontrolplane.com/myworkspace/api/v1/mcp-servers \ -d '{ "name": "Internal Documentation", "serverId": "docs", "url": "https://docs-mcp.internal.acme.com", "transport": "streamable-http", "authHeader": "Bearer internal-token-here" }' ``` ### Tool Namespacing External tools are namespaced as `mcp.{serverId}.{toolName}`. For example, a `docs` server with tools `search` and `getPage` becomes: - `mcp.docs.search` - `mcp.docs.getPage` ### Configure Scopes ```json { "mcp.docs.search": ["docs:read"], "mcp.docs.getPage": ["docs:read"], "mcp.jira.createIssue": ["jira:write"], "mcp.jira.listIssues": ["jira:read"] } ``` ### Connect from Your AI Client ```json { "mcpServers": { "my-company": { "url": "https://api.agenticcontrolplane.com/your-slug", "transport": "streamable-http" } } } ``` ACP merges tools from all sources — built-in connectors, external MCP servers, and agent-defined tools — into a single tool list. ### Governance Pipeline for External Tools Every call to an external MCP server tool goes through: 1. **Immutable rules** — SSN, credit card, SSRF pattern scanning 2. **Delegation check** — Agent-to-agent trust chain 3. **Scope enforcement** — JWT scopes vs. tool requirements 4. **ABAC rules** — Attribute-based access control 5. **Rate limits** — Per-user rate limiting 6. **Plan limits** — Subscription tier enforcement 7. **Content scanning** — PII detection on inputs and outputs The external server never sees the user's JWT or identity. ACP handles auth with the external server using the configured auth header. ### SSRF Protection ACP blocks connections to private IP ranges: `localhost`, `127.0.0.0/8`, `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `169.254.0.0/16`, and `metadata.google.internal`. ### Plans ACP does not meter calls on any plan. Pricing is bands of INITIATING AGENTS — durable identities that start work (the root of a delegation chain). Subagents, fan-outs, and delegation chains are free on every plan. "You pay for agents that start work; everything they delegate is free." | | Free | Solo | Team | Scale | Enterprise | |-------|------|------|------|-------|-----------| | Price | $0 forever | $25 / month | $49 / month | $199 / month | Let's talk | | Initiating agents / month | 5 | 10 | 25 | 100 | Unlimited | | Governed calls | Unlimited | Unlimited | Unlimited | Unlimited | Unlimited | | Subagents & delegation chains | Free | Free | Free | Free | Free | | Audit retention | 30 days | 90 days | 1 year | 1 year | Unlimited | | On-device local mode (`--local`) | ✅ free, no account | ✅ | ✅ | ✅ | ✅ | There is no per-seat pricing, no "Pro" tier, and no call cap. Model spend always stays on the customer's own keys — ACP never marks up tokens. Over-band agents keep working but run ungoverned with a loud notice (ACP never blocks work). See [/pricing](https://agenticcontrolplane.com/pricing) for the canonical table. --- ## The Identity Flow This is the end-to-end flow when a user triggers a tool call through ChatGPT or an MCP client: 1. User authenticates with identity provider (Auth0, Okta, Entra ID) via OAuth (PKCE) 2. Identity provider returns RS256-signed JWT with `sub`, `scope`, `aud` claims 3. User sends prompt + Bearer token to LLM/MCP client 4. LLM decides to call a tool, forwards request + Bearer token to ACP 5. ACP verifies JWT against identity provider's JWKS endpoint (cached) 6. ACP checks scopes against tool requirements 7. ACP runs PII detection, policy enforcement, and rate limiting 8. ACP forwards request to your backend with `x-user-uid` header (verified `sub` claim) 9. Backend responds 10. ACP writes structured audit log entry 11. Tool result returned to LLM ### What's in the JWT ```json { "header": { "alg": "RS256", "typ": "JWT", "kid": "NjVBRjY5MDlCMUIwNzU4RTA2QzZFMD..." }, "payload": { "sub": "auth0|8f3a2b1c9d4e5f6a", "aud": "https://api.yourapp.com", "iss": "https://yourcompany.auth0.com/", "scope": "tool:crm:read tool:jira:write", "org_id": "org_acme_corp", "exp": 1739145600, "iat": 1739142000 } } ``` Critical claims: - **`sub`** — the user's unique identifier. Cryptographically verified user ID, not an API key or email. - **`aud`** — intended audience. ACP rejects tokens meant for a different service. - **`scope`** — what the user is allowed to do. `tool:crm:read` means read from CRM. No scope, no access. - **`org_id`** — tenant isolation. Users in one organization can't access another's data. - **`kid`** — key ID for JWKS verification. ### What Your Backend Receives Without a control plane: ``` POST /api/crm/contacts Authorization: Bearer sk-shared-api-key-for-everyone Content-Type: application/json {"query": "show me all contacts in the pipeline"} ``` With a control plane: ``` POST /api/crm/contacts x-user-uid: auth0|8f3a2b1c9d4e5f6a x-user-scope: tool:crm:read x-user-org: org_acme_corp x-request-id: req_7f8a9b0c Content-Type: application/json {"query": "show me all contacts in the pipeline"} ``` --- ## Agent-to-Agent Governance Production agent systems involve agents delegating to other agents. A planning agent calls a research agent, which calls a data retrieval agent, which queries your backend. An ACP solves this by propagating identity through delegation chains. Each agent in the chain receives a scoped, time-limited credential derived from the original user's identity. Trust boundaries are enforced at every hop — Agent B can only access what Agent A is authorized to delegate. The full chain is recorded in the audit trail. --- ## ADCS — Agent Delegation Chain Specification ADCS is an open specification that formalizes the data structure and runtime semantics of agent-to-agent delegation chains. v0.1.0 is a draft with a reference implementation in production (the ACP gateway). Spec text is CC BY 4.0; schema, conformance vectors, and reference code are MIT. Spec repo: https://github.com/agentic-control-plane/delegation-chain-spec Hub page: https://agenticcontrolplane.com/spec/delegation-chain ### The data structure ```json { "originSub": "auth0|alice@acme.com", "originClaims": { "email": "alice@acme.com" }, "links": [ { "agentProfileId": "strategy-orchestrator", "agentRunId": "run_orch_2026041610", "agentName": "Strategy orchestrator", "effectiveScopes": ["web.*", "internal-research.delegate"], "effectiveTools": ["web_search", "research.delegate"], "remainingBudgetCents": 350, "delegatedAt": "2026-04-16T10:00:00Z" }, { "agentProfileId": "remote-researcher", "agentRunId": "run_res_2026041611", "agentName": "Remote researcher", "effectiveScopes": ["web.*"], "effectiveTools": ["web_search", "hn_search"], "remainingBudgetCents": 100, "delegatedAt": "2026-04-16T10:01:23Z" } ], "depth": 2 } ``` ### The six normative rules 1. **Origin invariant.** `originSub` MUST NOT change at any depth. Every action in the chain traces to exactly one accountable human or service identity. 2. **Scope intersection.** `effective_child = intersect(effective_parent, profile_child)`. Permissions only narrow as you descend the chain — children can never hold scopes their parent didn't already have. 3. **Budget propagation.** `budget_child = min(remaining_parent, max_child)`. Spend caps are mathematically bounded by what the ancestor has left, preventing runaway loops in deep chains. 4. **Cycle prevention.** An agent MUST NOT delegate to a profile already present in the chain. No mutual recursion, no infinite delegation loops. 5. **Type vs runtime identity.** `agentProfileId` is the stable type of the agent (e.g. "strategy-orchestrator"); `agentRunId` is unique per execution. This lets audit queries correlate the calls of one specific run even under parallel concurrency. 6. **Audit emission.** Every governed tool call MUST emit an audit entry containing the full chain at the moment of invocation. Logs are reconstructable from the emitted entries alone; SIEM integration is a query, not a custom pipeline. ### How ADCS relates to other specs - **A2A Protocol** (Google, Linux Foundation). Transport, discovery, capability negotiation. ADCS is complementary — A2A invocations MAY carry an ADCS chain in a header or message-part. - **MCP** (Anthropic). Tool invocation between agent and tool. ADCS wraps MCP — every governed MCP `tools/call` emits an ADCS audit entry. - **RFC 8693** (OAuth 2.0 Token Exchange, nested `act` claims). ADCS chains MAY be expressed as JWTs with nested `act` for cryptographic verifiability. ADCS is a profile of these semantics, plus a data shape for governance systems. - **OIDC-A / AIP** (in-flight identity drafts). ADCS assumes one of these has bound the originating user — ADCS specifies what happens downstream of that binding. --- ## Three-Axis Governance ACP's policy engine evaluates every tool call on three independent axes and returns the most-restrictive decision. This is the core ABAC model. ### The three axes 1. **Tool axis.** Per-tool rules (e.g., "deny `delete_repo` tool"). Tools inherit from categories, so a rule on "write tools" applies to every tool tagged as write. 2. **Agent axis.** Per-agent-type and per-agent-run rules (e.g., "the Explore subagent in Claude Code may not call network tools"). Keyed by `${client}::${tier}::${name}`. 3. **User axis.** Per-user rules (e.g., "Alice can call `customer_export` but only up to 50/day; Bob cannot call it at all"). ### The four-layer policy merge At decision time, ACP composes the effective policy for a call via: 1. **Workspace defaults** — tenant-wide baseline (set by admins). 2. **Role layer** — rules by user role (owner / admin / member). 3. **Agent-type layer** — rules by detected agent identity (from the Agent axis). 4. **User layer** — rules by the end user's `sub` (most specific). Each layer can tighten but not loosen the layer above it. A workspace "allow" with a user-layer "deny" resolves to deny. A workspace "200 calls/day" with an agent-type "50 calls/day" resolves to 50 calls/day. ### What this enables - **Role separation without ticket churn.** Engineers can call production tools; contractors cannot — enforced at every tool call, not at ticket time. - **Agent-shape policies.** "The Claude Code `Explore` subagent can read, but never write" is expressible in one rule. - **Per-user drift detection.** Policy violations by user surface in the activity log, even in audit mode — so you learn what to tighten before you enforce. - **Deterministic oversight.** Every decision is the output of rules, not a model prompt. Auditable, version-controlled, idempotent. Hub page: https://agenticcontrolplane.com/three-axis-governance --- ## Frequently Asked Questions ### What is an Agentic Control Plane? An Agentic Control Plane (ACP) is the identity and governance layer for AI agents. It ensures every agent action is identified (bound to a real user or agent identity), authorized (checked against policies), and auditable (logged with identity and context) — regardless of which framework, model, or client you use. ### What is the Three-Party Problem? In traditional web apps, users authenticate directly with backends — two parties, one trust boundary. AI applications add an LLM runtime as a third party. Users prove their identity to the LLM, but when the LLM calls a backend it forwards a shared API key. The backend can't verify who initiated it. ### How is ACP different from an API gateway? API gateways handle HTTP traffic — TLS, load balancing, rate limits. They operate in a two-party model. An ACP is designed for the three-party model where the caller is an LLM acting on behalf of a user. Most teams use both. ### How is ACP different from an LLM gateway? LLM gateways (Portkey, LiteLLM, OpenRouter) sit between your app and the model provider, optimizing model selection and cost. An ACP sits on the opposite side — between the model and your backend services. ### How is ACP different from an agent framework? Agent frameworks (LangChain, CrewAI, AutoGen) provide orchestration — tool chains, memory, reasoning loops. They determine what actions an agent should take. An ACP determines whether those actions are permitted. ### What identity providers are supported? Any OIDC-compliant provider issuing RS256 access tokens: Auth0, Okta, Microsoft Entra ID, Firebase Auth, AWS Cognito, Keycloak, PingIdentity, and Google. ### What agent frameworks does it work with? Any framework. ACP provides an MCP endpoint for tool discovery and an OpenAI-compatible proxy for model routing. LangChain, CrewAI, AutoGen, Mastra, Vercel AI SDK, custom code — if it can make an HTTP call, ACP can govern it. ### Is it free? The open-source modules (GatewayStack) are MIT licensed. There are two more no-cost ways to run ACP: (1) **on-device local mode** — `curl -sf https://agenticcontrolplane.com/install.sh | bash -s -- --local` puts allow/ask/deny policy + a safety floor + an audit log in front of Claude Code, Cursor, and Codex, entirely on your machine, no account and no network; and (2) **ACP Cloud is free up to 5 initiating agents** — unlimited governed calls, subagents free, no call meter and no credit card. Flat monthly bands above: Solo $25 (10 agents), Team $49 (25), Scale $199 (100). See [/pricing](https://agenticcontrolplane.com/pricing). ### What AI models can I use? ACP supports multiple models including Gemini, GPT, and Claude. You configure which models are available in your workspace settings and bring your own API keys. ### Can I use ACP with Claude Desktop, ChatGPT, or Cursor? Yes. ACP exposes a standard MCP endpoint. Point any MCP-compatible client — Claude Desktop, Claude Code, Cursor, Windsurf, Cline, Zed — at your workspace URL. Identity and governance are enforced on every request. ### What's the latency overhead? The identity verification and policy enforcement pipeline adds 2-5ms per request. JWKS fetch is cached after first use. PII detection adds ~1ms. Rate limit checks are sub-millisecond. ### Can I deploy on-prem? Yes. GatewayStack runs anywhere Node.js runs — Cloud Run, ECS, Kubernetes, bare metal. No external dependencies beyond your OIDC provider. ### What's the license? MIT. All six modules and the monorepo are MIT licensed. Use them freely in commercial and open-source projects. ### Is it production-ready? The open-source modules are published on npm and tested (135 tests across 17 files). ACP Cloud provides a managed multi-tenant gateway with dashboard, integrations, and audit UI. ### Can agents call other agents through ACP? Yes. ACP supports agent-to-agent governance with delegation chains. Every hop is audited. Agents discover each other via standard well-known endpoints. --- ## Troubleshooting ### Token is encrypted (JWE), not signed (JWS) **Symptom:** 401 response with `access_token_is_encrypted_jwe`. Your identity provider is issuing opaque or encrypted tokens (JWE — 5 base64 segments) instead of signed JWTs (JWS — 3 segments). **Fix:** Configure your IdP to issue RS256-signed access tokens. In Auth0, go to APIs > your API > Settings > JSON Web Token Profile and select "RS256." ### Audience mismatch **Symptom:** 401 response with `jwt_verify_failed`. The `aud` claim in the token doesn't match the `OAUTH_AUDIENCE` your gateway expects. **Fix:** Ensure the `audience` parameter in your OAuth request matches the API identifier. Check for trailing slashes — `https://api.example.com` and `https://api.example.com/` are different audiences. ### Insufficient scope **Symptom:** 403 response with `insufficient_scope`. The user's token doesn't include the required scopes. The `WWW-Authenticate` header tells you which scopes are needed. **Fix:** Check that your IdP grants the required scopes. In Auth0, verify the API permissions and any Rules or Actions that modify token claims. ### Token expired **Symptom:** 401 response with `token_expired`. **Fix:** Check token lifetime settings in the IdP. Default Auth0 access tokens expire in 24 hours. Check for clock drift on your server. ### Identity claim missing **Symptom:** Request passes authentication but backend receives no user context. **Fix:** Ensure your IdP includes the `sub` claim in access tokens. Some providers only include `sub` in ID tokens by default. --- ## Harness Native Controls (reference) What each coding agent enforces on its own — approval modes, rules, sandboxing, hook coverage, audit, escape hatches, and unattended behavior — and where each ends. The hub compares them side by side; the per-harness pages go deep on one control model each. - [Which Coding Agent Has the Best Native Controls? (August 2026)](https://agenticcontrolplane.com/controls): Approval modes, policy rules, sandboxing, hook coverage, audit logs, escape hatches, and unattended behavior — compared across Claude Code, Codex CLI, Cursor, dsh, Muse Code, Grok Build, Antigravity, Goose, opencode, and more. Per-harness pages: - [Google Antigravity Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/antigravity): How Antigravity's permissions engine, terminal sandbox, hook system, and headless posture actually work — the first harness whose hooks can natively ask, why a failing hook blocks the call, and where the enterprise controls begin. - [Claude Code Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/claude-code): The six permission modes including the new auto mode, how allow/deny rules actually match, what the sandbox bounds, which hooks fire when, what bypassPermissions still enforces, and where the native model ends. Current to v2.1.233. - [Codex CLI Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/codex-cli): Codex CLI's approval policies (on-failure is gone), the Guardian auto-reviewer, permission profiles, the sandbox on each OS, the new full hooks system that's on by default, requirements.toml for enterprises, and where the model ends. Current to 0.147. - [Cursor Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/cursor): Cursor's three Run Modes and the Auto-review classifier, natural-language permission instructions, the sandbox on each OS, the hook system and its fail-open default, the three allowlist-bypass CVEs, cloud agents, and where the model ends. - [DeepSeek Harness (dsh) Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/dsh): How dsh's approval service, typed plugin interception points, headless ask-denies-itself posture, and trajectory log actually work — what each catches, what none of them record, and how to extend them. - [fx (Vercel Labs) Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/fx): How fx's ask/auto/yolo modes, wildcard permission rules, hardcoded model reviewer, repo-config lockdown, and macOS sandbox actually work — what each mechanism does, what none of them record, and where the native model ends. - [Grok Build Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/grok-build): How Grok Build's permission modes, TOML rules, sandbox profiles, and hook system actually work — what fires in always-approve, why dontAsk is not the escape hatch, and why every hook failure is a silent allow. - [Hermes Agent Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/hermes): How Nous Research's Hermes Agent controls tool execution: smart approvals (now the default), the published blocklist and its unconditional tier, the file-write guard, four hook systems, what survives yolo mode, and where the model ends. - [Muse Code Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/muse-code): How Muse Code's approval modes, LLM approval judge, staged shell review, OS-enforced sandbox, and hook system actually work — what each catches, what runs outside the sandbox, and where the beta's docs are ahead of the binary. - [OpenClaw Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/openclaw): How OpenClaw controls tool execution: the exec security/ask settings and their permissive default, allowlist mode's approval binding, per-agent and per-sender tool policy, the sandbox, plugin hooks with requireApproval, and the security audit command. - [opencode Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/opencode): How opencode's permission system actually works: allow/ask/deny rules with last-match-wins, bash pattern matching, the once/always/reject gate, the --auto flag, plugin hooks on the permission system, and where the model ends. - [pi (earendil-works) Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/pi): pi ships four tools and no permission system, on purpose. How its TypeScript extension events (tool_call, tool_result), ctx.hasUI, and containment patterns actually work — what an extension can intercept, and where the native model ends. - [Prime Agent Permissions & Control Model, Explained](https://agenticcontrolplane.com/controls/prime-agent): Prime Agent runs everything through one ipython kernel, ships no permission framework, and is built for unattended autonomy. How its extension events, hasUI signal (and its print-mode bug), daemon architecture, and autonomous limits actually work. --- ## MCP Server Native Controls (reference) What each MCP server enforces on its own — auth model, read-only modes, scoping, tool filtering, approvals, audit, and who holds the keys. The hub compares them; the per-server pages document exactly which flags enforce what. - [Which MCP Servers Have the Best Native Controls? (August 2026)](https://agenticcontrolplane.com/mcp-controls): Read-only modes, tool filtering, scoping, audit logs, and approval hooks — compared across the GitHub, Playwright, Supabase, Stripe, Notion, Slack, Atlassian, Sentry, Filesystem, Postgres, AWS, Linear, Zapier, Context7, and Chrome DevTools MCP servers. Per-server pages: - [Atlassian MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/atlassian): How the Atlassian Rovo MCP server's admin plane actually works — permission mirroring, domain and IP allowlists enforced per tool call, permission-group grants, and the only per-call audit log in this series — and what none of it decides. - [AWS API MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/aws): How the AWS API MCP server's REQUIRE_MUTATION_CONSENT elicitation prompt, READ_OPERATIONS_ONLY mode, and JSON security policy actually work — the only native human approval in this series, verified fail-closed, and already dropped from AWS's own successor server. - [Chrome DevTools MCP Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/chrome-devtools): How Chrome DevTools MCP's profile model, attach modes, category flags, and URL patterns actually work — what --browser-url and --autoConnect mean for your real Chrome, and where the native model ends. - [Context7 MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/context7): How Context7's read-only, two-tool design actually works — open library submission, the ContextCrush injection disclosure, what Upstash says it can't guarantee, and why the risk here flows into the agent, not out of it. - [Filesystem MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/filesystem): How the filesystem MCP server's allowed-directories boundary actually works — CLI args, the MCP roots protocol that silently replaces them, two patched path-check CVEs, and why read-only means a Docker mount. - [GitHub MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/github): How the GitHub MCP server's read-only mode, toolsets, per-tool selection, dynamic toolsets, and lockdown mode actually work — what each one enforces, what GitHub says they are not, and where the native model ends. - [Honeycomb MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/honeycomb): How the Honeycomb MCP server's controls actually work — the read/write scope split, team-owner-only API keys, the densest native rate limits in this series — and why telemetry itself is the untrusted input on this surface. - [Linear MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/linear): How the hosted Linear MCP server's controls actually work — the dedicated read-only endpoint at /mcp/readonly, the read OAuth scope, restricted API keys, Okta enterprise-managed auth — and what still doesn't exist below them. - [Notion MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/notion): How the hosted Notion MCP server's permission model actually works — one OAuth grant carrying the user's full workspace access, no read-only mode, no tool filtering, and the real scoping stranded on a server Notion no longer maintains. - [Playwright MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/playwright): How Playwright MCP's isolated profiles, capability gates, origin filters, and traces actually work — why the origin flags were removed and restored in one week, what Microsoft says they are not, and where the native model ends. - [Postgres MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/postgres): How the archived Anthropic Postgres MCP server and Postgres MCP Pro actually control SQL — a read-only wrapper with an unpatched injection still on npm, a restricted mode that's off by default, and the database role that outlasts both. - [Sentry MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/sentry): How the Sentry MCP server's dual-token OAuth, skills-based authorization, org/project path constraints, and fail-closed grants actually work — the best grant-time architecture in this series, and why grant time is still its ceiling. - [Slack MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/slack): How the official Slack MCP server's admin approval flow, OAuth scopes, IP allowlists, and per-call audit events actually work — and why nothing native can hold a message before it's sent. - [Stripe MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/stripe): How the Stripe MCP server's restricted API keys, OAuth sessions, and sandboxes actually work — the only vendor-side scoping in this series, and why it still can't say 'never refund more than $50'. - [Supabase MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/supabase): How the Supabase MCP server's read-only mode, project scoping, and feature groups actually work — read-only enforced at the Postgres role, scoping as blast-radius control, and where the native model ends. - [Zapier MCP Server Permissions & Controls, Explained](https://agenticcontrolplane.com/mcp-controls/zapier): How Zapier MCP's two tool modes, connection tokens, account-wide restrictions, and per-call history actually work — one endpoint fronting 9,000+ apps, the best native audit trail in this series, and no policy at the point where everything converges. --- ## The Three Planes: Identity, Control, Observability - [The three planes of running agents: identity, control, observability](https://agenticcontrolplane.com/three-planes): Okta issues agent identities before the session. Honeycomb reconstructs agent behavior after the fact. Between them sits the moment of action — the tool call — where the only question that prevents an incident gets decided. A map of the three planes and how they compose. --- ## Recent Posts (2026-08-31) - [Your Rules File Is Not a Policy](https://agenticcontrolplane.com/blog/your-rules-file-is-not-a-policy): AGENTS.md said ask before pushing. The agent force-pushed. Across Claude Code, Cursor, and opencode, the incident reports share one shape: rules written in prose bind the model only as strongly as its attention. What binds is enforcement at the tool call. - [How to Set Up Permissions Across Your Team's Fleet of Coding Agents](https://agenticcontrolplane.com/blog/set-up-permissions-across-your-teams-coding-agents): A step-by-step guide to one permission policy for every coding agent your team runs — Claude Code, Codex, Cursor, mixed fleets, orchestrators. Workspace, invites, roles, shadow-then-enforce, and the ordering mistake that forks your org. - [Codex Exec and MCP Approvals: Headless Without the Bypass Flag](https://agenticcontrolplane.com/blog/codex-headless-mcp-approvals): In non-interactive Codex, MCP tool calls that need approval auto-cancel — stdin is closed, nobody can answer — and the only documented way through is --dangerously-bypass-approvals-and-sandbox. There's a better shape: make the approval question answerable before the run starts. - [Do Claude Code Deny Rules Actually Work?](https://agenticcontrolplane.com/blog/claude-code-deny-rules-not-working): The bug tracker says: sometimes. A catalog of the documented ways Claude Code deny rules fail or get bypassed — Bash pattern gaps, subagents, @-file attachments, recursive grep, symlinks — what still holds, and how to get a deny that actually denies. --- ## Links - Website: https://agenticcontrolplane.com - ACP Cloud: https://cloud.agenticcontrolplane.com/login - GitHub (GatewayStack monorepo): https://github.com/agentic-control-plane/GatewayStack - GitHub (org — installer, benchmark, ADCS spec, SDKs): https://github.com/agentic-control-plane - npm: https://www.npmjs.com/org/gatewaystack - API endpoint: https://api.agenticcontrolplane.com