AI-narrated article. Prose is preserved with pronunciation adjustments; code and image cues refer to the written article.
Safe Platform Access for AI Agents: Bind Approval to the Operation, Not the Conversation
This is the AI-narrated article. The prose follows the written post; pronunciation is adjusted, and code and images are announced separately.
An OAuth token and tool schema cannot authorize a deployment. Bind resource ownership, exact-operation approval and worker credentials behind the platform boundary.
TL;DR: An authenticated tool call is only a request. Keep the agent behind a bounded platform interface, derive identity from verified context, resolve resource ownership server-side, and separate admission from provider execution. Bind approval to an immutable operation revision, exact payload and expiry, then recheck permissions and target freshness before dispatch. This article supplies a narrow OPA execution policy and a changed-target rejection example. It also explains audience-bound MCP credentials, downstream identity separation, durable status and idempotency. Policy evaluation proves the gate logic; it does not prove trustworthy inputs or complete platform security.
A tool call is a request, not a change ticket
An agent investigates a staging incident, finds an undersized worker pool, and calls request_capacity_change. The tool has a schema, an OAuth token and a reassuring description. None proves that the caller owns that service, that the target is staging, or that a human approved the particular change now being executed.
The architectural tension is useful autonomy versus reusable authority. Give the agent a bounded request interface. Keep authorization, immutable change records and provider credentials behind the platform boundary. A compromised prompt can then produce a rejected request rather than an unrestricted Terraform execution.
This article proposes an application contract. MCP standardizes tool interaction and transport authorization; it does not supply your tenant model, approval workflow or deployment policy. The protocol references below use the 2026-07-28 revision.
Split three identities before exposing tools
Use distinct identities for the caller at the MCP server, the adapter at the Platform API, and the worker at the provider. The adapter's workload identity identifies the adapter. It does not automatically establish end-user delegation. Carry verified requester context through an explicit delegation mechanism, or authorize the workload as its own principal; never invent an end-user identity from tool arguments.
For protected HTTP MCP deployments, clients send the resource parameter in authorization and token requests, and servers validate the intended token audience. Authorization accompanies every HTTP request. An invalid or expired token and insufficient permission are different rejection conditions. MCP authorization.
Audience answers where the token belongs; scope describes requested access. Neither answers whether this principal may modify this service in this environment. Resolve those objects server-side, then evaluate ownership and operation-specific policy. RFC 8707.
Do not forward the inbound MCP bearer token unchanged to a cloud API. MCP prohibits token passthrough. If the adapter brokers OAuth, bind consent to the actual user/client combination and validate redirect/state handling; otherwise it can become a confused deputy. Discovery fetches also need destination and redirect restrictions. MCP security guidance.
Design the tool catalog around decisions
Expose describe_service, plan_capacity_change, request_capacity_change and get_operation. A plan can disclose sensitive configuration, so read and planning paths still need target authorization. Prefer service identifiers and bounded replica counts over arbitrary shell commands, URLs, credential aliases or Terraform variables.
The MCP adapter validates structure and forwards a typed request. The Platform API derives tenant and actor from authenticated context, resolves service ownership, checks scope and quotas, and persists the accepted operation. The worker executes only an admitted, current operation using narrowly scoped downstream credentials.
Image. Authority matrix: the agent requests, the Platform API admits, and the worker executes after exact approval
Tool annotations are hints, not enforcement. A readOnlyHint supplied by an untrusted server is not a security control; even a trusted description cannot substitute for server checks. Validate inputs, enforce access controls, rate-limit calls and sanitize outputs. Return selected evidence instead of raw secrets or entire provider responses. MCP tools.
A complete execution-policy example
Suppose the permitted operation scales checkout workers in staging between one and twenty replicas. Save the following as execution.rego. It is a narrow OPA 1.9.0 execution gate, not a complete MCP server. The API constructs input from verified identity, an immutable stored operation, a stored approval and server time. None of these authority-bearing fields may come directly from agent JSON.
Code example. Refer to the written article for the complete code.
The digest must cover the canonical target, action and parameters. The platform computes it, persists immutable revisions, and verifies an approval record from an authenticated reviewer. Equality against an attacker-supplied digest proves nothing. Replace the hard-coded team/service relationship with authoritative ownership data when generalizing this policy. OPA evaluates the provided documents; your integration must authenticate their origin. Rego language.
Save this evaluation input as approved.json. Values are illustrative fixtures, including server-time units; they are not bearer tokens or production approvals.
Code example. Refer to the written article for the complete code.
Prerequisites: PowerShell, a scratch directory and the official Windows amd64 OPA 1.9.0 executable. Obtain it from the pinned release using your normal artifact-verification process. Save it as opa.exe beside the two files. These commands evaluate policy only; they never call Kubernetes or AWS.
Code example. Refer to the written article for the complete code.
The intended decisions are true for the approved staging fixture and false for the changed target. A passing evaluation validates this gate, not identity verification, storage integrity or provider permissions. Add regression cases for expired approvals, self-approval, changed digests, another tenant, and out-of-range or fractional replicas before integrating it. OPA policy testing.
Diagnose the approval that survived a target change
A realistic failure is a mutable operation row with approved=true. Someone changes staging to production after review, but the dispatcher checks only that boolean. The reviewer approved one action; the worker performs another. This is an illustrative failure scenario, not a claimed incident.
Correlate the operation revision, approved digest and worker dispatch record. Stop dispatch for the affected operation, invalidate stale approval, and create a new immutable revision requiring review. If execution already started, inspect the provider receipt and actual state before retrying or compensating. Blind resubmission can duplicate an uncertain effect.
Approval records should bind operation ID, revision, payload digest, reviewer authority and expiry. Recheck current requester authorization and target preconditions immediately before dispatch. Where a provider supports it, use resource versions or conditional updates to reject changes against stale observed state. Approval validity and target freshness solve different problems.
Make acceptance and execution separately observable
Persist the operation and durable dispatch intent before returning HTTP 202. Provide a status URL and polling guidance. Bind an idempotency key to tenant, requester and canonical request: identical retries return the existing operation; different payloads using the same key fail. Authorize status and cancellation requests too. A 202 means accepted, not applied. Asynchronous request-reply.
Durable workflows can coordinate approvals, timeouts and execution. Temporal Queries read state, Signals deliver asynchronous writes, and Updates support tracked writes with validation. These primitives do not authenticate your approver. Establish reviewer identity and permission before delivering the decision. Workflow messages.
Workers must tolerate retries. Durable orchestration does not establish exactly-once cloud effects; use provider idempotency where available and reconcile ambiguous outcomes. Audit actor, target, operation revision, policy decision, worker attempt and provider receipt. Keep tokens out of logs. Activity definition.
FAQ
Does OAuth scope authorize a production change? It provides part of the permission context; target ownership, environment policy and exact-operation approval remain application checks.
Can the model approve its own tool request? It can request an operation. An approval requires a separately authenticated, authorized reviewer under the proposed contract.
Must every operation require a human? No. Explicit policy may admit bounded low-risk operations automatically; apply the same immutable request and execution checks.
Does a denied policy evaluation make the whole system safe? No. The gate depends on trusted inputs and mandatory enforcement on every execution path, including retries and administrative bypasses.