Slim ACS-Core: relax MODIFY, system/ping, and wrapped MCP to SHOULD - #21
Slim ACS-Core: relax MODIFY, system/ping, and wrapped MCP to SHOULD#21bar-capsule wants to merge 2 commits into
Conversation
Lowers the adoption floor for frameworks claiming ACS-Core conformance by relaxing three items within Core to conditional requirements, without removing them from Core or introducing new profiles. The hook taxonomy minimum, dispositions ALLOW/DENY/ASK/DEFER, SessionContext with chain hash and Intent, replay protection, baseline HMAC-SHA256 integrity, and decision-honoring behavior remain MUST. Changes: - Dispositions: ALLOW/DENY/ASK/DEFER stay MUST. MODIFY moves to SHOULD, with composition rules ([..]/specification.md#63-modify-composition-normative) still normative for implementers. Deployments that do not implement MODIFY declare so in the handshake; Guardians MUST NOT return MODIFY to such deployments (DENY with audit substitution). - Liveness `system/ping`: SHOULD-implement. MAY be omitted by deployments where both parties co-locate or rely on transport-level liveness. - Wrapped MCP `protocols/MCP/*`: SHOULD-implement by deployments that govern MCP tool calls. MAY be omitted by deployments that do not use MCP. Support is declared in the handshake. What stays mandatory in Core (the differentiation from a stateless single-call evaluator): SessionContext + chain_hash + Intent option, the 6-hook lifecycle minimum, four dispositions, replay protection, HMAC baseline integrity, and decision honoring. These preserve the runtime governance properties that distinguish ACS from a stateless policy evaluator. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds subagent lifecycle hooks to the Core minimum (8 hooks instead of 6). Rationale (Ariel): a sub-agent is itself an Observed Agent under delegated authority. Without subagentStart/subagentStop on the Core floor, a Guardian is blind to cross-agent propagation and to the confused-deputy attack class that delegation enables. ACS already has the schemas, the AgBOM models subagent components, and the wire shape is identical to other steps -- the cost of mandating these is marginal, the cost of leaving them optional is a structural gap in runtime governance. Frameworks without a sub-agent abstraction satisfy this requirement vacuously: the hooks never fire, the framework still declares them as implemented in the handshake. Net Core hook count: 6 -> 8. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR Agent-Control-Standard#21 promotes subagentStart and subagentStop from SHOULD to MUST in the ACS-Core hook minimum (8 hooks instead of 6). Update the FAQ to match: - "How do I make my framework ACS-conformant?" lists subagent hooks in the mandatory floor with a short justification. - "What if my framework does not have a particular hook surface?" no longer lists subagent hooks under "Additional hooks (SHOULD)"; they are now part of Core. Frameworks without a sub-agent abstraction satisfy this requirement vacuously, which is the same shape as the merged spec's "implement when observable" pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update: subagent hooks promoted to mandatory (per Ariel)Added Net Core after both relaxations and this addition:
Rationale for the subagent promotion (Ariel's reasoning): a sub-agent is itself an Observed Agent operating under delegated authority. Without Frameworks without a sub-agent abstraction satisfy this vacuously (the hooks never fire). Same shape as the existing "implement when observable" pattern. Shape of the slim: dropping the three things that add infrastructure burden (MODIFY composition rules, system/ping plumbing, MCP awareness for non-MCP deployments), adding the two things that close a structural governance gap. The PR's adoption-floor goal still holds — a framework can implement the 8 hooks and the rest of Core in one focused session — and the security floor is materially better. FAQ updated in parallel (PR #20, commit |
|
Merge-order note (for whoever lands these): this one sets the ACS-Core floor, so it should go in before #20 and #22. It promotes the subagent hooks to MUST and relaxes MODIFY,
No git conflict with either (this only touches |
|
this work should actually also bump the patch version @bar-capsule |
|
I spent a while on this one because four lines that change what a MUST means are worth more scrutiny than four lines usually get. The direction is defensible and I'll say why below, but there are two places where the text as written can't be implemented, and one that I think gets the security trade backwards. Taking them in order of how much they block. The MODIFY declaration has nowhere to liveLine 20 says deployments that don't implement MODIFY "MUST advertise this in the handshake." I went to check what field that would be, and there isn't one. Here's the full ClientHello property set from Nothing about dispositions, on either message shape. And a vendor can't just invent one, because the schema description says "Unknown fields MUST be ignored at every level," so a conformant peer is required to throw the extension away. The part that made me think this was an oversight rather than a decision: §9.2 already solved this exact problem for ASK, and it went the other way. I think Wrapped MCP's demotion is what made this feel safe, because that one does land on a real field ( Either add Nothing defines what an agent does with a MODIFY it can't applyThis is the one I'd fix even if you disagree with everything else here. Once MODIFY is optional, some agents will receive one anyway, because the declaration above doesn't work yet and handshakes are the first thing an integration gets wrong. I went looking for the defined behavior and couldn't find it. So an implementer writes the obvious three lines: unknown or unapplicable disposition, proceed with the original payload. Under a house style where Before this PR that was flatly non-conformant and a test could assert it. After, it's an unspecified path inside a negotiated capability, and nothing can call it a violation. One sentence fixes it, mirroring §6.3: an Observed Agent that receives a disposition it cannot apply MUST treat the decision as DENY and MUST record an audit event. While you're in there, the substitution on line 20 mandates an audit event with no The subagent clause has two readings and both are defensibleI like the reasoning here more than the other three changes, and I think the confused-deputy argument is right. The clause still needs work, because I read it twice and got two different answers. Reading one: "Frameworks that do not have a sub-agent abstraction" means the framework genuinely has no such concept. Under that reading Claude Code and Cursor both have subagents, so neither gets the exemption. Reading two: the parenthetical "(the hooks never fire)" is the operative test, so a framework that emits no subagent event satisfies it vacuously regardless of whether the concept exists. Those give opposite answers for the same deployment, which means the clause can't settle a conformance dispute. Worse under reading two, any deployment can claim vacuity by declining to implement the emitter, which makes the promotion from SHOULD to MUST a no-op. The deeper problem is that "has no sub-agent abstraction" is a fact about a framework's internals and not a fact on the wire. A deployment that spawns subagents and doesn't instrument them sends a ClientHello that's byte-identical to one from a framework that genuinely has none. No Guardian, auditor, or test can tell them apart. Every other omission in this PR got a declaration mechanism ("Support is declared in the handshake" on line 26, "MUST advertise this in the handshake" on line 20), and this one didn't. Two more things I'd want you to look at before settling this:
And My suggestion: make the vacuity claim a wire fact (a ClientHello boolean a Guardian can refuse on and an auditor can hold a vendor to), or split the pair so One thing this PR can't fix but should probably acknowledgeWhile tracing the subagent change I hit something bigger. ACS spends 428 lines constraining what the Observed Agent MUST emit and never constrains what the Guardian MUST evaluate. The ServerHello's So a Guardian can accept every subagent hook a conformant client emits and evaluate none of them, and both parties stay conformant. Every hook-coverage claim in ACS is unfalsifiable from the enforcement side. That's not yours to solve in a four-line PR. But this is the first change whose stated security rationale depends on the half that's missing, so it's worth a sentence in the PR body at least, and probably an issue. Wrapped MCP: the fallback doesn't cover what you'd want it toLine 26 lets deployments "that do not use MCP" omit the namespace. The problem is what happens to deployments that do.
There's a timing problem underneath it. "Deployments that do not use MCP" is assessed once, at handshake, and MCP servers get added at runtime. Suggestion: condition the requirement on The ping justification points at something that isn't definedLine 25 lets deployments omit I'll grant the strongest form of your case here, because The trouble is the recommended alternative. Decision-failure monitoring depends on an audit stream, and in #22 that stream is I'd either strike the unanchored justification, or define what a transport-level liveness signal is per transport, or require ACS-Core deployments to declare a liveness mechanism rather than merely permit omitting one. Small stuff, quick to fixThe quick-reference table at line 83 still says ping is mandatory, in this same file, 58 lines below the bullet that makes it optional: That row also doesn't mention the subagent hooks you just promoted, says "dispositions" unqualified, and has no Wrapped MCP entry. Since it's the row people paste into comparison matrices, I'd update it in this PR. Line 30's guarantee paragraph is also untouched and still says the agent "honors the Guardian's decisions," which is now true for four of five. One clause would fix it, something like noting a minimum-conformant deployment can permit or refuse an action but cannot alter it, and redaction requires MODIFY support. Version
The practical effect is that two peers who disagree about whether MODIFY is required both send I know the project is pre-1.0 and SemVer says you owe nobody compatibility below 1.0.0. That argument works right up until #20's FAQ starts telling compliance teams to rely on this, which it does. A SequencingThese three PRs aren't textually conflicting (I checked, the file sets are disjoint), but #20 and #22 both restate what this PR changes. #20's FAQ already carries your subagent language nearly verbatim at line 124 and hasn't picked up any of the three relaxations, so it'll contradict this PR on three of four items the moment both land. #22's conformance suite cites This one should go first, with #20 rebased against the final text and #22 updating its citations. I've left the details on both of those PRs. Last thing, and it's procedural rather than technical: |
Summary
Lowers the ACS-Core adoption floor by relaxing three items to conditional requirements within Core, without removing anything from Core or introducing new profiles. The behavior contract that makes ACS distinct (SessionContext + Intent, the hook lifecycle minimum, decision honoring) stays mandatory.
Three changes
system/pingprotocols/MCP/*What stays mandatory in ACS-Core
The seven things that make ACS a meaningful runtime governance contract, not a stateless single-call policy evaluator:
request_id,timestamp,acs_version,metadata)sessionStart/agentTrigger,userMessage,toolCallRequest,toolCallResult,agentResponse,sessionEndchain_hashand the Intent invariant (the runtime context that makes governance meaningful, not just per-call yes/no)request_idUUID +timestamp+ Guardian replay rejection)Why these three specifically
All three add real deployment friction without being load-bearing for the spec's core property (preventing the agent from acting on injected reasoning):
MODIFY requires the agent to rewrite its own outbound payload according to Guardian-provided modifications. That's qualitatively different from ALLOW/DENY/ASK/DEFER, which are state-machine outcomes the agent doesn't have to construct. A framework that doesn't implement MODIFY can still ALLOW/DENY/ASK/DEFER cleanly.
system/ping is useful for managed-Guardian deployments where the agent needs to verify reachability before sending real traffic. Co-located deployments don't need it; transport-level liveness covers the same property.
Wrapped MCP forces every conformant framework to be MCP-aware, including frameworks whose deployments don't use MCP at all. Declaring MCP support in the handshake is the right cut.
ACS picks "stateful and meaningful on hooks." SessionContext with a hash-chained audit and an immutable Intent are required in Core; the dispositions you actually implement track the policy outcomes a framework can produce. Compositional risk is governable because the Guardian sees the running session, not just one call. The cost is that ACS-Core is a slightly higher implementation bar than "wire up one hook and return a verdict."
This PR reduces the gap on the implementation-bar axis without giving up the statefulness or the meaningful hook minimum that distinguish ACS.
What this is NOT changing
on_decision_failure: proceed): unchangedOpen questions for working-group review
Handshake field for MODIFY-incapable clients. The PR says deployments not implementing MODIFY "declare so in the handshake," but doesn't pin the field name. Suggest a follow-up that adds a
dispositions_supportedfield to ClientHello, parallel to the existingapprover_types_supported. Could ride this PR or land separately.FIDES interaction. FIDES-style enforcement uses MODIFY for redaction (
modifications.redactions). A FIDES Guardian targeting a MODIFY-incapable client would need to substitute DENY for actions that would otherwise be redaction-rewritten. Worth flagging in the FIDES paradigm-binding docs.Wrapped MCP signalling. The PR says MCP support "is declared in the handshake." Today the handshake's
wrapped_protocolsfield carries this implicitly. Worth making explicit in a follow-up that absence of MCP fromwrapped_protocolsmeans the deployment is MCP-incapable.Test plan
specification/v0.1.0/remain valid (no schema changes in this PR)docs/spec/conformance.md🤖 Generated with Claude Code