Repository navigation
feat(policy-engine): introducing Agent Control Spec (ACS) - #2747
Merged
MohammadHaroonAbuomar merged 145 commits intoJun 2, 2026
Merged
MohammadHaroonAbuomar merged 145 commits into
MohammadHaroonAbuomar merged 145 commits into
Conversation
|
Welcome to the Agent Governance Toolkit! Thanks for your first pull request. |
Vendors responsibleai/AgentControlSpecification@318dbca into the new policy-engine/ directory. ACS becomes the AGT-owned policy engine per the AGT 5.0 redesign documented in architecture-exploration.md. Headline divergences from upstream ACS (to be implemented in M1-M2): - Effects removed from verdict; transform verdict type introduced (Q2). - Optional evidence field on verdict + telemetry events (Q4). - Cedar promoted to a built-in policy type (Q10). - approval top-level manifest section (Q13). - AGT folder discovery, scope filter, and merge layer pre-resolves manifests before they reach this engine; engine never sees extends from an AGT host (Q6). Original ACS LICENSE preserved at policy-engine/LICENSE.acs. Original ACS README preserved at policy-engine/README.vendored-acs.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
…t/evidence specs
5 normative spec docs implementing user decisions Q2-Q14:
- SPECIFICATION-AGT-DELTA.md: section-by-section deltas from upstream ACS
spec — drop effects, add transform verdict, add evidence field, promote
Cedar to built-in policy type, add approval section, add reserved reasons,
document cargo feature split.
- agt/AGT-MANIFEST-1.0.md: full manifest surface AGT hosts author including
new top-level approval and limits sections.
- agt/AGT-RESOLUTION-1.0.md: AGT-side folder discovery + scope filtering +
merge layer that pre-resolves manifest chains before the engine sees them
(preserves AGT v4 folder discovery while keeping ACS engine simple).
- agt/AGT-SNAPSHOT-1.0.md: per-intervention-point snapshot shape so
AGT-authored Rego/Cedar rules are portable across SDKs.
- agt/AGT-EVIDENCE-1.0.md: proof_artefact + verification_pointers
convention for high-assurance dispatchers.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Synthesized fixes addressing 5 unique blockers and 5 warnings from the
multi-model review by claude-opus-4.7-1m-internal and gpt-5.5.
Blockers:
1. (Opus) restore result_labels to D1 verdict members; IFC propagation
was silently dropped.
2. (Opus) renumber approval to §24 to avoid colliding with upstream §22
Versioning and §23 References; patch summary-of-impacts.
3. (Opus) AGT-RESOLUTION emitted policy_set on a type:rego policy; rego
only accepts bundle. Rewrote §2.5 to materialize a Rego bundle on
disk and bind type:rego with bundle path.
4. (GPT) AGT-RESOLUTION path traversal returned an empty manifest that
evaluates to allow; replaced with fail-closed
runtime_error:resolution_path_traversal. §5 empty-manifest fallback
removed; missing governance now MUST fail closed or substitute a
host-registered default.
5. (GPT) D1.4 action identity bound only to pre-transform input; auditor
could not replay the executed action. Bisected into input_identity
and enforced_identity; approval binding moves to enforced_identity.
Warnings:
- Cedar default mapping aligned to envelope.agent.id per AGT-SNAPSHOT §1
(was snapshot.agent.id).
- Telemetry event names standardized on upstream
intervention_point.{allowed,denied,warned,escalated} plus the new
intervention_point.transformed; removed invented intervention_point.decided.
- Six new runtime_error:resolution_* reasons added to D6.
- Cedar advice schema specified in D3.3.
- AGT-SNAPSHOT §2.2 clarifies IFC paths are input.ifc.* and
response.ifc.*, not snapshot.ifc.*.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
…eld, AGT reserved reasons
M2.S1 and M2.S3 from plan v3. Implements SPECIFICATION-AGT-DELTA D1 and D2
without removing the upstream effects path (kept for parity through M2.S5
when the workspace split lands and effects can be feature-gated off).
verdict.rs:
- Decision::Transform variant added; permits() helper bisects allow/warn/
transform from deny/escalate.
- Transform struct parses {path, value}; rejects transforms whose path is
not rooted at (TransformTargetForbidden) or whose path
fails JsonPath parse.
- Evidence struct parses {artefact, verification_pointers}; sorted
pointer_keys() helper for telemetry per AGT-EVIDENCE-1.0 §3.
- normalize_policy_output rejects transform on non-transform decisions and
transform decisions without a body.
- 12 new unit tests; lib suite 43 → 55.
error.rs:
- 3 new variants for D6 reserved reasons:
TransformTargetForbidden -> runtime_error:transform_target_forbidden
TransformInvalid -> runtime_error:transform_invalid
ApprovalResolverMissing -> runtime_error:approval_resolver_missing
- reason() and detail() updated; AGENTS.md house style preserved.
Test suite: 130 tests pass, 0 failures (was 118).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
…eview
Round-2 review by claude-opus-4.7-1m-internal and gpt-5.5 reached
consensus: 0 blockers, no disagreements. Both reviewers raised 2
warnings each, all converging on these 4 fixes.
- DELTA summary-of-impacts §5 Modes was 'Unchanged' but D1's effects
removal changes evaluate_only validation semantics. Now describes the
transform-shaped validation.
- DELTA §11 IFC was 'Unchanged' but AGT-SNAPSHOT diverges from upstream
on the path (input.ifc.* vs input.snapshot.ifc.*). Now flagged as
path-clarified and the upstream policy/lib/ifc.rego replacement is
called out so M4 doesn't ship a fail-closed-on-every-call default.
- DELTA §19 omitted the removal of intervention_point.effect_applied.
Now stated explicitly and points consumers at intervention_point.transformed.
- AGT-EVIDENCE §4 used SHOULD store while DELTA D1.4 used MUST be in
every audit record. Tightened to MUST.
No code changes; spec docs only.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
….S4)
Add ApprovalSection, ApprovalResolverConfig, and ApprovalOnTimeout types
to the vendored ACS manifest parser. The new field on Manifest is
optional and backwards compatible; manifests without an `approval` block
continue to parse and validate as before.
The Manifest::approval() accessor exposes the parsed section. The
runtime treats resolver configuration as opaque per
SPECIFICATION-AGT-DELTA D5; only the section shape is validated.
Validation rules per D5:
- on_timeout must be one of deny|allow|suspend
- default_resolver must match a key in resolvers when both are set
- timeout_seconds, fatigue_threshold, fatigue_window_seconds when
present must be > 0
- bad shapes fail closed with runtime_error:manifest_invalid
10 unit tests cover all five validation rules plus three positive
parse-and-round-trip cases. Test suite grows from 130 to 140 passing.
This commit was originally landed with the wrong subject line during a
worktree coordination overlap; the reword corrects the history without
changing any file content.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Promote Cedar to a built-in policy type alongside rego, test, and custom, implementing the manifest-side surface from AGT M2.S2 per `policy-engine/spec/SPECIFICATION-AGT-DELTA.md` §D3.1. The new `PolicyConfig::Cedar(CedarPolicyConfig)` variant accepts the fields fixed by D3.1: `policy_set` xor `policy_path` (exactly one required), optional `entities_path`, optional `schema_path`, and an optional `query` object whose shape is open for AGT v5. Unknown fields are rejected via `serde(deny_unknown_fields)` so a manifest that mixes rego-shaped fields (e.g. `bundle`) into a cedar policy is caught at deserialization. Relative cedar paths resolve against the declaring manifest's directory in `resolve_relative_paths`, matching the rego.bundle behaviour. `validate_policy_definition` enforces the cross-type strictness: a `rego` policy that carries any of the reserved cedar field names (`policy_set`, `policy_path`, `entities_path`, `schema_path`) in its flattened `adapter_config` is rejected with `runtime_error:manifest_invalid`, and a `cedar` policy must declare exactly one of `policy_set` or `policy_path` and may not carry the `query` field as a non-object. The prepared-invocation surface for cedar lands in the next commit (M2.S2 D2). To keep this commit compilable and to preserve the fail-closed contract in the interim, `prepare_policy_invocation` returns `runtime_error:policy_invocation_failed` for any cedar binding that reaches it. No existing rego, test, or custom path changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mohammad Haroon Abuomar <MohammadHaroonAbuomar@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Add policy-engine/spec/schema/approval.schema.json (draft 2020-12) describing the AGT D5 top-level approval section shape: default_resolver, timeout_seconds, on_timeout enum, fatigue_threshold, fatigue_window_seconds, and named resolvers with a required type discriminator plus open additional properties. Reference the new schema from manifest.schema.json as an optional approval property so manifest validators (current and future) load it through the existing schema tree. The engine still treats resolver configuration as opaque per SPECIFICATION-AGT-DELTA D5; the schema validates shape only. Refs M2.S4, AGT 5.0 architecture-exploration Q13. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <MohammadHaroonAbuomar@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Wire the cedar branch of `prepare_policy_invocation` to its own `PreparedPolicyInvocation::Cedar(CedarPolicyInvocation)` variant rather than the M2.S2 D1 placeholder error. The prepared invocation carries the resolved cedar policy source (`policy_set` xor `policy_path`), the optional `entities_path` / `schema_path` artefacts, the optional request-template `query` from the policy definition, the final policy input the runtime built for this intervention point, and the canonical JSON serialization of that input. `engine_type()` returns the new `cedar` constant and `policy_input()` exposes the input for the cedar arm, keeping the prepared-invocation surface symmetrical across all four policy types. The dispatcher trait and the CedarTestDispatcher reference implementation land in the next commit (M2.S2 D3). The existing OpaPolicyDispatcher continues to reject non-rego invocations with `runtime_error:policy_invocation_failed` per SPECIFICATION.md §12.3, so a cedar binding bound to the OPA dispatcher still fails closed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mohammad Haroon Abuomar <MohammadHaroonAbuomar@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Reads input.snapshot.envelope.budgets per AGT-SNAPSHOT-1.0.md §1 and emits AGT deny verdicts (SPECIFICATION-AGT-DELTA.md §D1) when any host tracked counter has reached its configured limit. Provides individual predicates (max_tool_calls_exceeded, max_tokens_exceeded, timeout_exceeded, max_cost_exceeded) and a combined deny_if_budget_exceeded helper for the M6 GovernancePolicy migration path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
PII regex constants track the canonical source list in agent-os/src/agent_os/integrations/base.py::PII_PATTERNS (SSN, email, phone, credit card, secret). Provides matches_any, first_match (which returns the earliest matching span across all patterns), and a deny_if_pattern helper that yields the AGT deny verdict shape from SPECIFICATION-AGT-DELTA.md §D1. The earliest selector breaks ties on pattern index so verdicts are deterministic across SDKs and OPA versions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Reads input.tool.content_hash (manifest tool catalog) and input.snapshot.tool_call.content_hash (per AGT-SNAPSHOT-1.0.md §2.5) and denies with reason tool_content_hash_mismatch when the snapshot hash is missing or differs from the manifest-declared hash. Returns no verdict when the manifest did not declare a hash, so the helper is safe to include unconditionally in the default policy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Reads input.tool.security_labels as an allowlist of permitted egress hosts (per SPECIFICATION §11 a tool entry MAY set security_labels) and resolves the call destination from a small list of common snapshot paths under input.snapshot.tool_call.args plus the input.annotations.egress.destination override. Hosts may pass their own destination_paths and allowlist via the rules argument. glob.match handles wildcard entries such as *.example.com without requiring authors to spell out every subdomain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Reads input.annotations.drift_score (host-supplied annotator output, range 0..1) and produces an AGT warn verdict with reason drift_detected when the score reaches the configured threshold. The helper returns nothing when the annotation is absent or non-numeric so callers can chain it into a default policy without false positives. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Reads input.annotations.confidence.score (host-supplied annotation, range 0..1) and emits an AGT deny verdict with reason confidence_below_threshold when the score falls below the manifest configured minimum. Returns nothing when the annotation is absent or non-numeric so the policy falls through to allow on missing signal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Combines agt.patterns.first_match with the AGT transform verdict shape (SPECIFICATION-AGT-DELTA.md §D1.1). The returned verdict carries transform.path equal to $policy_target and a fully replaced value, so the dispatcher applies the substitution without host side logic. The substitution runs in Rego via a single regex.replace over the combined pattern alternation, which keeps redaction deterministic across SDKs and avoids the recursive rule restriction in OPA. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Produces AGT escalate verdicts (SPECIFICATION-AGT-DELTA.md §D1.2) that the host approval path (§17.1) resolves through the resolver declared in the approval manifest section (§D5). escalate_if guards a verdict on a host supplied condition; escalate_if_approver_required emits the approval_required reason when the manifest names a non-empty approver list; escalate_with_message carries a free form human message. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
AGT stock IFC label-flow library. The function surface (dominates, max_sensitivity, flow_allowed, allow, deny, verdict, verdict_propagating, and their _with_lattice variants) mirrors the upstream agent_control_specification.lib.ifc package so policies written against the AGT helpers stay familiar, but the snapshot paths are AGT-correct per AGT-SNAPSHOT-1.0.md §2.2 and §2.7. The library exposes source_labels and result_labels convenience accessors that read input.snapshot.input.ifc.source_labels and input.snapshot.response.ifc.result_labels respectively, plus an allow_if_dominates shorthand for the no write down policy. The upstream library reads input.snapshot.ifc.* which AGT does not populate, so AGT users MUST import data.agt.ifc instead. The upstream policy/lib/ifc.rego and policy/lib/ifc_test.rego are kept in place because examples/ifc_agent and the spec-18-ifc conformance case references still depend on the upstream package name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Default verdict rule for hosts that do not author their own Rego. The manifest binds its rego policy to data.agt.defaults.verdict and supplies thresholds, allowlists, and pattern lists under data.agt.defaults.config (loaded as an OPA data document). The rule chains every AGT stock helper in severity order: ifc deny > confidence deny > budgets deny > content_hash deny > egress deny > pattern deny > approval escalate > redact transform > drift warn > allow. The cfg helper avoids a self recursive rule by reading data.agt.defaults.config from outside the package namespace. This is the GovernancePolicy auto translation target for the M6 migration tool. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Invokes opa test against every library file and its sibling _test.rego in policy-engine/policy/lib. Honors OPA_BIN override, falls back to ~/.local/bin/opa when opa is not on PATH, and exits non-zero on test failure so CI can gate on the result. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
…stDispatcher Land the dispatcher surface for the AGT D3 built-in cedar policy type: - `CedarPolicyDispatcher` is the host-facing trait parallel to the rego dispatcher path in `opa.rs`. Implementations evaluate a `CedarPolicyInvocation` and return a verdict-shaped JsonValue that the runtime normalizes through `normalize_policy_output`. - `build_cedar_request` implements the AGT D3.2 default mapping. The principal is `Agent::"<envelope.agent.id>"`, the action is `Action::"<intervention_point>"`, the resource is `Tool::"<name>"` when a tool is projected and `PolicyTarget::"<kind>"` otherwise, and the context keys are the snapshot keys (minus envelope) plus the `annotations.*` keys. The source paths follow `spec/agt/AGT-SNAPSHOT-1.0.md` §1. - `CedarTestDispatcher` is the deterministic test double tests can drive per D3.3. It parses `policy_set` as a small JSON pseudo-cedar document (rules with `effect`, `principal`, `action`, `resource`, optional `reason`, optional `advice`), builds the cedar request, matches rules by entity equality (forbid wins, then first permit), and emits an allow, deny, or advice-translated verdict. - `translate_advice` validates the AGT D3.3 advice shape (verdict in warn / escalate / transform, transform body required for transform, string-typed reason and message) and converts advice JSON into the verdict JSON the runtime expects. Path-in-$policy_target validation remains in `verdict::Transform::from_value` so a transform advice with a path outside `$policy_target` fails closed with `runtime_error:transform_target_forbidden` exactly like any other transform verdict, keeping the error contract centralized. Both dispatchers also implement `PolicyDispatcher` so a host can swap a cedar dispatcher in directly behind the runtime, the same way `OpaPolicyDispatcher` does for rego. The feature-gated `CedarBuiltinDispatcher` backed by the upstream `cedar-policy` 4.x crate is deferred to a follow-up milestone. I could not validate that build path in the current dev environment: the `cc` on `PATH` is a `zig cc` wrapper that rejects the `--target=x86_64-unknown-linux-gnu` target query that `cc-rs` passes when compiling the `psm` transitive dependency of `cedar-policy`'s `stacker` dep. The prompt explicitly allows this fallback. The trait surface, the test dispatcher, and the manifest plumbing land now; hosts that need real cedar evaluation today implement `CedarPolicyDispatcher` themselves and link `cedar-policy` at the host crate level. The builtin lands once the dev container ships a real `gcc` or once we pin to a cedar-policy version whose deps avoid the `stacker` / `psm` chain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mohammad Haroon Abuomar <MohammadHaroonAbuomar@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Land the normative JSON schema for the AGT D3.3 cedar advice payload at `policy-engine/spec/schema/cedar_advice.schema.json`. The schema is draft 2020-12, matches the artefact set under `spec/schema/wire/`, and captures the contract `SPECIFICATION-AGT-DELTA.md` §D3.3 fixes: - `verdict` is required and limited to `warn`, `escalate`, or `transform`. The `allow` and `deny` decisions never come from advice; cedar's own authorization result drives those. - `reason` is optional and MUST NOT use the reserved `runtime_error:` prefix. - `message` is optional and free form. - `transform` is the AGT D1.1 single target replacement body. It is required when `verdict` is `transform` and forbidden otherwise. The conditional is expressed with an `allOf` / `if` / `then` / `else` block so that a malformed advice fails closed at validation time rather than at `Transform::from_value` time. `transform.path` MUST be rooted at `$policy_target`; the runtime still enforces the path-in-target invariant inside `normalize_policy_output` and emits `runtime_error:transform_target_forbidden` for a violating path. The cedar dispatcher (see `core/src/cedar.rs::translate_advice`) performs the same shape validation in Rust to keep the manifest-loader and dispatcher boundaries independent of the JSON schema artefact at runtime; the schema artefact is the canonical documentation source for SDKs and policy authors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mohammad Haroon Abuomar <MohammadHaroonAbuomar@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
…spatcher Add the AGT M2.S2 D5 test coverage for the new cedar surface. Manifest validation in `policy.rs::cedar_manifest_tests`: - rego policy with `policy_set` is rejected with `runtime_error:manifest_invalid` - rego policy with `policy_path` is rejected with the same reason - cedar policy with the rego-shaped `bundle` field is rejected at deserialization via `deny_unknown_fields` - cedar policy with neither `policy_set` nor `policy_path` is rejected - cedar policy with both `policy_set` and `policy_path` is rejected - positive coverage: cedar with only `policy_set` or only `policy_path` (plus optional entities and schema paths) parses cleanly - cedar with an unknown field is rejected by `deny_unknown_fields` - cedar with a non-object `query` is rejected Dispatcher behaviour in `cedar.rs::tests`: - AGT D3.2 default mapping: principal is `Agent::"<envelope.agent.id>"`, action is `Action::"<intervention_point>"`, resource is `Tool::"<name>"` when a tool is projected and `PolicyTarget::"<kind>"` otherwise, context keys exclude envelope - a missing envelope agent id fails closed with `runtime_error:policy_invocation_failed` - AGT D3.3 allow path: a permit rule with no advice produces a normalized `Decision::Allow` verdict - AGT D3.3 deny path: a forbid rule wins over a permit rule and the rule reason flows through to the verdict reason - no matching rule emits `deny` with `no_matching_policy` - AGT D3.3 advice translation produces `transform`, `escalate`, and `warn` verdicts with reason and message preserved - malformed advice fails closed with `runtime_error:policy_output_invalid` for: missing `verdict`, unknown `verdict`, transform without body, and warn / escalate carrying a transform body - AGT D1.1 confinement: transform advice with a path outside `$policy_target` fails closed with `runtime_error:transform_target_forbidden` after `normalize_policy_output` re-validates the dispatcher output, proving the existing path-in-target check covers the cedar advice path with no duplicate logic - dispatcher error paths: missing inline `policy_set`, invalid policy set JSON, and non-cedar invocations routed through the `PolicyDispatcher` trait all fail closed with `runtime_error:policy_invocation_failed` All 169 `agent_control_specification_core` tests pass (29 added by this commit, 140 pre-existing). `cargo clippy --all-targets -- -D warnings` on the core crate is clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Mohammad Haroon Abuomar <MohammadHaroonAbuomar@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
…1.0 (M3.S1)
M3.S1 from plan v3. New top-level Python package agt-policies (5.0.0a1)
that hosts AGT 5.0 host-side primitives over the vendored ACS engine.
This commit lands the manifest resolution layer:
agt.manifest_resolution.discover - §2.1 governance.yaml walk with
path-traversal fail-closed (not
v4's empty-list-allow)
agt.manifest_resolution.scope - §2.3 glob-based scope filter
agt.manifest_resolution.merge - §2.4 rule merge preserving the
deny-immutability invariant
across chains; same-name-without-
override drops the child
agt.manifest_resolution.build - §2.5 end-to-end resolve_manifest
that materializes a generated Rego
bundle under .agt/resolved-bundle/
and emits a flat ACS manifest with
extends:[] ready for the engine
agt.manifest_resolution.errors - D6 reserved resolution reasons
wired as a ResolutionError class
29 pytest tests covering: path-traversal fail-closed; root-first
ordering; scope glob normalization; rule merge with deny-immutability
and same-name-no-override drops; top-level section merges; end-to-end
bundle materialization with sha256 sidecar; intervention point
annotations union; inherit:false truncation; reserved reason strings
matching D6 byte for byte.
29 passed in 0.12s.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: AGT 5.0 ACS merge <agentgovtoolkit@microsoft.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
The compose `test` service ran agent-os's suite but the root Dockerfile never installed `agt-policies` (import name `agt`), which agent-os imports at runtime but does not declare as a pip dependency. Non-v5 tests that touch the policy layer failed at runtime with `ModuleNotFoundError: No module named 'agt'`. Install it alongside the other editable sibling packages. The v5 native runtime (`agent_control_specification`) is still absent in this image, but those bridge tests are guarded by an importorskip/skipif and the bridge imports the binding lazily, so they skip cleanly rather than error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
The docker-compose-test image installed agt-policies but not the agent_control_specification native binding its v5 runtime bridge hard-requires. Every adapter that routes a check through the bridge raised ModuleNotFoundError, failing 232 tests. Add the maturin-based SDK build (Rust stable + maturin, gcc already present) to the dev stage, mirroring the test (agent-os) CI matrix job, with an in-layer import smoke test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
liamcrumm
approved these changes
Jun 2, 2026
ACS (the vendored policy-engine/ runtime) was invisible in the top-level docs. Surface it as an AGT module: - Root README: add ACS to the Packages and Specifications tables. - Docs site: new packages/agent-control-specification.md page, wired into the mkdocs nav, the packages overview, and the homepage cards and Specifications table. - policy-engine/README.md: reshape into an AGT-module README that leads with what ACS is (why, what, core idea, example) and how the AGT integration works (host adapters, agt-policies bridge, native runtime), folding in the integration framing. Fix two stale doc links and remove the redundant README.vendored-acs.md. - Python SDK README: add a What is ACS intro. - Glossary: add Agent Control Specification, Intervention Point, Transform Verdict, and Verdict. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
Rework the ACS package page header so it renders on the MkDocs site (markdown-enabled centered block, real badges, and a styled Public Preview admonition instead of a raw GitHub blockquote). Remove the upstream repository provenance sentence and the Original ACS source attribution row from the policy-engine README so ACS reads as AGT-owned source. MIT attribution is preserved via LICENSE.acs and the License section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
Remove the demo_multisdk directory and its Rust example. These were live-demo scratch artifacts that hardcoded absolute developer paths (/home/liamcrumm/...) in the Rust and .NET entrypoints and are not wired into CI, docs, or Cargo example targets. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
Remove workspace/notes.txt and report.md, which are produced by the coding_agent example at runtime, and gitignore them so example runs do not redirty the tree. The hello.txt input fixture is kept. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
Inline the seven AGT divergences (D1-D7) from SPECIFICATION-AGT-DELTA.md directly into SPECIFICATION.md so the policy-engine ships a single authoritative contract, then delete the delta file and repoint every reference to it. Spec changes: - Replace the upstream effects model with the transform verdict (new section 14, fifth decision, transform_target_forbidden and transform_invalid reasons). - Add evidence object on verdicts (section 13.3) and its telemetry propagation (evidence_artefact plus evidence_verification_pointer_keys, never the pointer URL values). - Add the cedar policy type (section 12.4) with request and verdict mapping that matches core/src/cedar.rs. - Bisect action identity into input_identity and enforced_identity (section 13.1); approval binds to enforced_identity. - Document the optional approval manifest section (section 24) with the full ApprovalSection shape, and the approval_resolver_missing reason. - Add the AGT host-side extends resolution note (section 2.2) and the resolution_* reserved reasons (section 16). - Section 16 now carries the full 18 canonical runtime-error reasons and drops effect_invalid and effect_target_forbidden. Tests and references: - parity_canonical.rs now reads only SPECIFICATION.md. - Repoint all source, doc, schema, rego, and cedar references from the delta file to the relevant SPECIFICATION.md sections. Verified: cargo test -p agent_control_specification_core green, otel integration green, docs link check 0 new broken. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
Wire agt-policies into Python CI and Docker tests, verify OPA downloads, and pin the new workflow tooling installs. Move resolved policy bundles out of governed workspaces, clean up runtime-owned bundles, fix adapter budget accounting, and harden manifest-resolution policy rendering against invalid fields and operator drift. Remove the unpublished ACS SDK as a bare generator dependency and keep the dependency-confusion scanner aware that the SDK name is local-only. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
liamcrumm
force-pushed
the
agent-policy-spec
branch
from
June 2, 2026 15:45
9aaa8cd to
19fc61f
Compare
Ensure resolved AGT governance rules are actually bound to the generated agt_legacy_rules policy before emitting the ACS manifest. A governance chain with rules but no matching intervention-point binding now fails closed instead of producing rules that never execute. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add missing conformance cases for evaluate-only and transform semantics, restore release-claim coverage, and update the Python conformance runner for bisected action identity fields. Add a coverage guard for ACS-backed Agent OS adapter scenario tests and harden workflow generator tests around OPA checksum verification and pinned tooling. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use parsed URL hostnames to detect Azure OpenAI endpoints instead of substring matching the full API base URL. This prevents path text such as .azure.com from selecting Azure authentication mode. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Liam Crumm <liamcrumm@gmail.com>
liamcrumm
force-pushed
the
agent-policy-spec
branch
from
June 2, 2026 16:03
19fc61f to
1b58405
Compare
Add the Open Policy Agent download host token to the repository spelling terms so generated workflow URLs pass changed-line spell checking. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a step-by-step ACS tutorial that builds a direct policy enforcement point with a manifest, Rego policy, and Python host flow covering allow, transform, deny, and fail-closed behavior. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bring 4 new upstream commits into the AGT 5.0 / ACS branch: - docs: polish docs site (UX enhancement, clean IA) (microsoft#2771) - fix(mesh-sdk): close client-side gap with POP-aware relay/registry (v4.0.0) (microsoft#2772) - fix(attestation): make verify_evidence strict by default (CVSS 8.1) (microsoft#2769) - fix(ci): harden JS lint steps - fix mastra-agentmesh TS errors (microsoft#2745) Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
After Liam's ACS sync (`e5b64ea4`), the EndpointAnnotator's URL-config validation message changed from "missing required field 'url'" to "missing required field 'endpoint' or 'url'" — both names are now accepted, with `endpoint` preferred. The bad_endpoint_config_reserved_reason_and_oversize_outputs_fail_closed test in policy-engine/integrations/annotators/tests/moderation_flow.rs was still asserting the old wording and was the only failing test in the workspace. Updated assertion to match the new message. Verified by running `cargo test -p agent_control_specification_annotators --test moderation_flow --release --all-features` — 6/6 pass. Full workspace --all-features: 373/0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Exclude the dynamic Discord badge image from markdown-link-check because its Cloudflare challenge returns 403 to automated checkers while the actual Discord invite link remains checked separately. Signed-off-by: Liam Crumm <liamcrumm@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MohammadHaroonAbuomar
marked this pull request as ready for review
June 2, 2026 17:34
MohammadHaroonAbuomar
requested a review
from Imran Siddique (imran-siddique)
as a code owner
June 2, 2026 17:34
Jack Batzner (jackbatzner)
approved these changes
Jun 2, 2026
MohammadHaroonAbuomar
merged commit Jun 2, 2026
484724c
into
microsoft:main
129 of 135 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Introduces the Agent Control Specification (ACS) as AGT's new policy engine for v5.0.
ACS is vendored from
responsibleai/AgentControlSpecificationintopolicy-engine/and replaces the prior YAML / OPA / Cedar dispatcher with a single, deterministic, fail-closed runtime that ships with stock Rego and Cedar libraries, a normative wire schema, and consistent surface across the five language SDKs.What's in this PR
policy-engine/spec/SPECIFICATION.md+SPECIFICATION-AGT-DELTA.md(D1–D7) + per-IP shape docs (AGT-MANIFEST-1.0,AGT-SNAPSHOT-1.0,AGT-EVIDENCE-1.0,AGT-RESOLUTION-1.0) — RFC-2119 normative, with conformance testspolicy-engine/core/default = ["opa", "cedar"]), 373 cargo tests with--all-featurespolicy-engine/policy/lib/,policy-engine/policy/cedar-lib/policy-engine/sdk/{rust,python,node,dotnet}Decision.Transform,Verdict.Evidence, bisected identity,FromPathAsyncagent-governance-python/agt-policies/AgtRuntime,SnapshotBuilder, governance-chain manifest resolution,GovernancePolicy → ACS manifestbridge,agt migrate v4-to-v5CLIagent-governance-python/agent-os/src/agent_os/integrations/AgtRuntimevia the newAdapterRuntimeBridge(openai, langchain, anthropic, autogen, crewai, gemini, llamaindex, guardrails, google_adk, mistral, pydantic_ai, semantic_kernel, maf, smolagents, a2a, agentshield, bedrock)policy-engine/scripts/demo_end_to_end.shAGT deltas vs upstream ACS (normative, see
SPECIFICATION-AGT-DELTA.md)transformdecision (5-decision surface).effects[]array is removed; verdicts containingeffectsfail closed withruntime_error:policy_output_invalid. Multi-step rewriting moves to annotators per D1.3.input_identity(pre-transform) andenforced_identity(post-transform) on every result. Approval resolver binds toenforced_identity.verification_pointerskeys (no URLs) on every verdict, propagated to telemetry events.policies.type: cedaris a built-in (not a custom adapter); stock Cedar mirror atpolicy/cedar-lib/.approval:in the manifest, structurally validated againstApprovalSectionwithdeny_unknown_fields. Empty{}is the documented minimum (host wires the resolver viaAgtRuntime(approval_resolver=...)).runtime_error:reasons covertransform_target_forbidden,transform_invalid,approval_resolver_missing,resolution_path_traversal,resolution_cycle,resolution_invalid_governance,resolution_merge_conflict.default = ["opa", "cedar"]; users can opt in/out per build.Migration story for existing AGT users
agt migrate v4-to-v5(inagent-governance-python/agt-policies/src/agt/cli/migrate.py) walks a v4 project, lists every legacy artefact, and (with--write) rewrites the project to the v5 shape: flat ACS manifests + generated Rego bundles. Dry-run by default, idempotent, deterministic, stdlib + pyyaml only.Test matrix (last verified locally on this branch)
cargo test --workspace --all-features --releaseagt-policies pytestagent-os/tests/test_integrations.py + test_v5_bridge.pyReviewer trail
The branch went through four rounds of multi-model code review (Claude Opus + GPT-5.4) reaching consensus LGTM before the AAIF technical review. Liam Crumm picked up the work and added 39 commits on top of the original 103, including:
SPECIFICATION.md76a05f9d)0ea6871e)24d81de4)d63711fe)Type of Change
effects[]is removed from verdict;Decision::EffectsbecomesDecision::Transform; v4 GovernancePolicy users should runagt migrate v4-to-v5policy-engine/spec/,docs/adr/0029-policy-distribution-and-registries.md, and the per-package docsPackage(s) Affected
AdapterRuntimeBridgeChecklist
mainSigned-off-by:)Attribution & Prior Art
Prior art / related projects:
responsibleai/AgentControlSpecification(snapshot at upstream commit318dbca). License: Apache-2.0. Seepolicy-engine/LICENSE.acs.cedar-policy/cedar(Apache-2.0)open-policy-agent/opa(Apache-2.0)AI Assistance
Substantial portions of this branch were drafted and reviewed with the assistance of GitHub Copilot CLI (Claude Opus + GPT-5.4). The multi-model review trail kept consensus discipline before each milestone shipped. Every claim in commit messages is grounded in code or spec evidence.
Convergence path (per AGT_AAIF.docx proposal)
This PR is the AGT-side of a planned two-layer governance stack. The RAI team's AgentShield semantic / deterministic content-control layer will replace AGT's policy service in a follow-up ADR before AAIF submission, giving every AGT integration AgentShield capabilities without breaking changes. AGT remains the infrastructure-governance layer (identity, trust, authorization, audit, lifecycle, policy evaluation).
Notes for reviewers
microsoft:main(verified after merging current main); 0 behind.MohammadHaroonAbuomar-authored commits are SSH-signed; the public signing key has been registered against the account (verification badge should be active across the diff).OneDrive/AGT/Presentations/AAIF_AGT_Technical_Review_v2_AGT5.pptx) is in progress; will be flipped to ready-for-review after the TC vote and after the AgentShield convergence ADR lands.