Guides/Framework

OWASP Agent Control Standard (ACS): What It Controls and What It Doesn't

8 min readReviewed September 3, 2026
On this page
Abstract art of a runtime transaction path meeting a policy interception plane before reaching an external system

OWASP Agent Control Standard

General Analysis

An accounts-payable agent has valid credentials and a $75,000 payment ready to send. The invoice in its context says the supplier changed bank accounts. Somewhere between the model accepting that instruction and the banking API receiving it, the request has to stop.

That stop is what we went looking for when we read the Agent Control Standard schemas and roadmap. ACS has a lot of surface area, but its useful idea is quite narrow: framework code pauses an agent before a runtime effect, sends the pending action to a policy authority, waits, then honors the answer. If the first record of the payment appears in a trace after the bank responds, the control has missed its moment.

OWASP introduced ACS in September 2026 as a v0.1 public preview. The ACS resource page is dated September 1, while the announcement has a September 2 dateline. The preview is specific enough to interrogate. Calling it a finished runtime control would get well ahead of what the project has released.

Readers looking for the separate ASI01-ASI10 risk taxonomy can use our OWASP Top 10 for Agentic AI guide. We stayed with the runtime mechanics here.

Where does the Guardian actually sit?#

ACS calls the governed system the Observed Agent and its policy authority the Guardian Agent. The name invites a mental picture of one model supervising another. We were glad to find a less fashionable design in the project definitions: deterministic policy runs first. An LLM-backed Guardian layer is optional and receives cases delegated by that policy.

Keep hard authorization rules in the deterministic layer. A probabilistic judgment might help with an ambiguous support request; it shouldn't decide whether a payment exceeds an account limit.

The timing of the hooks matters more than their names. A tool request hook fires before execution. A tool result hook fires after the tool has run but before its output returns to the agent. The second hook can prevent a poisoned result from reaching another model turn. It can't unsend money or undo an account change. The v0.1 schema package also covers messages, retrieval, memory, and subagents, but none of those extra surfaces makes a late hook early.

Take the invoice as a hypothetical transaction. Framework code wraps the proposed payment in a steps/toolCallRequest envelope, adds session context and trusted provenance, and sends it to the Guardian. The reply may allow the call, deny it, modify it, or ask for approval. While that happens, the banking service should see no request.

A standard can define the exchange; it can't force every route through it. Can an agent call the bank with a direct SDK or raw HTTP client that skips the framework adapter? What happens when a subagent or scheduled job uses a different path? We would ask to see the call graph and the exact line that blocks each route. A box labeled "Guardian" on an architecture slide proves very little.

The Guardian boundary lives inside the runtime, at a choke point every consequential action must cross. Put it beside that path and you have advice. Put it after the call and you have telemetry.

Flow diagram showing an observed agent pausing a tool request at a pre-execution hook, sending it to a Guardian, and reaching the external tool only after an allow or modify decision
Figure 1. ACS becomes a runtime control only when the tool request waits at the hook and the Observed Agent enforces the Guardian's decision before calling the target.

The hook name alone says little about what it can stop. Timing is the useful distinction:

SurfaceWhen it runsCan it stop the external effect?What to verify
steps/toolCallRequestBefore tool executionYes, if the runtime waits and enforces the verdictDirect-call bypasses, timeout behavior, and modified arguments
steps/toolCallResultAfter the tool runs, before agent ingestionNo; the effect has already happenedWhether poisoned output reaches memory or another model turn
Trace exportAfter the hook or decision emits telemetryNoComplete correlation without leaking sensitive arguments

See how your AI systems hold up under real attacks

General Analysis maps AI applications and agents, red teams prompts, retrieval, tools, MCP servers, browser actions, permissions, and business workflows, then turns findings into evidence your team can reproduce and retest.

Reading v0.1 against the roadmap#

The ACS repository describes the public preview as documentation and requirements, ACS definitions and JSON schemas, observability definitions for OpenTelemetry and OCSF, and Agent Bill of Materials requirements. Instrumentation for agents and a sample Guardian application remain on the roadmap. That distinction should be in the first conversation with any vendor claiming ACS support.

ACS uses JSON-RPC envelopes. During the session handshake, the Observed Agent declares the methods it implements and the Guardian declares the ones it evaluates. Read both lists. A method missing from methods_evaluated is allowed by default, so a valid handshake can coexist with a large enforcement gap.

The preview separates Instrument, Trace, and Inspect. Instrument carries hooks and Guardian decisions, which is where a pending action can be stopped. Trace records security and observability data. Inspect describes components in an Agent Bill of Materials. Treating the whole package as one enforcement layer makes the audit trail sound like a brake.

The observability integrations belong on the record-keeping side of that line. OpenTelemetry provides machinery for generating, collecting, and exporting telemetry. OCSF provides a common security-event schema. They can make a Guardian decision easier to follow once an implementation maps the data. They don't issue the decision or hold the tool call.

We read the roadmap because the schemas alone give an overly generous impression of current coverage. v1 is slated to add agent instrumentation, a sample Guardian application, ACS-to-OpenTelemetry and ACS-to-OCSF mappers, plus FastMCP and A2A client instrumentation. Protocol extensions for MCP and A2A deny and modify operations are scheduled for v3, along with an agent implementation that supports them.

What bothered us is how easy the schema/roadmap split is to misread. The v0.1 response schema already knows the words deny and modify, and MCP-related schema surfaces are present. Those definitions describe an ACS disposition today. The roadmap still places MCP/A2A deny and modify support at v3. If an implementation claims that coverage now, ask for the protocol trace and watch the target system during the denial.

How we would evaluate an implementation#

Our first move would be to disconnect the Guardian in the middle of a consequential request. Under the current v0.1 Instrument specification, a decision failure defaults to proceed. A timeout, broken transport, or unusable verdict therefore lets the action continue unless the deployment selects deny.

Would the $75,000 payment leave because the policy process went quiet? The answer needs to come from a failure test, not a configuration screen. A customer-service lookup may justify a different availability choice, which is why the failure posture belongs at the method level.

We would keep the test plan short:

  • Trace every path to an external effect and prove it hits a pre-execution hook. Include direct network clients and subagents.
  • Delay the Guardian, break its connection, and return malformed replies. Observe the target system for side effects.
  • Put false provenance in a prompt or retrieved document and confirm that authoritative provenance still comes from deterministic framework code.
  • Replay a decision with the original input and recorded policy version. A free-form reason string isn't enough for reconstruction.

The enforcement loop should be this boring. This is illustrative runtime logic, not an ACS SDK API:

Code source: illustrative.

TypeScript
const verdict = await guardian.evaluate(toolCallRequest, timeout) if (!verdict) return applyFailurePosture(onDecisionFailure) if (verdict.decision === 'deny') throw new PolicyDenied(verdict.reasoning) if (verdict.decision === 'modify') toolCall = apply(verdict.modifications) if (verdict.decision === 'ask' || verdict.decision === 'defer') return pause(verdict) return execute(toolCall)

Then look at the boring numbers. How much latency does the hook add? How often does it time out? How often do people bypass it because approvals pile up? A control that developers route around has excellent coverage only on paper.

The Guardian also has to make its decision from whatever the Observed Agent reports. Complete hook coverage won't repair dishonest context or a bad policy. Narrow credentials and service-side authorization still have to contain the damage, and the Guardian needs authentication and separation from the agent it governs.

We found no independent adoption or efficacy study showing that ACS implementations reduce successful production attacks. The public preview gives teams a concrete contract to examine; empirical maturity is still an open question. The OWASP GenAI Industry Framework Crosswalk doesn't settle it. Every mapping there is unreviewed until a named reviewer signs it, and its CoSAI and EU AI Act Code of Practice entries are candidate mappings only. Use them as leads, then verify any audit claim against the source framework.

Browse all