feat: language parity for require_approval approval chains (TypeScript, .NET, Rust, Go) #3083
Description
Summary
#2478 adds a require_approval verdict plus the approval-chain execution layer (human, LLM judge, and webhook approvers, action binding per ADR-0030, configurable timeouts, and audit linkage) to the Python PolicyEvaluator and govern(). This issue tracks bringing the same approval-chain execution to the other AGT language SDKs, so governance behavior stays consistent across the ecosystem.
The Python wiring is landing under #3067 (PolicyEvaluator / govern integration after ADR-0030). This tracker is the single place to follow the non-Python work.
What Python adds (#2478, #3067)
- A
require_approvalverdict that pauses execution and routes the decision to an approval chain. - Approval chains: an ordered list of approvers that short-circuits on the first deny.
- Approver types: human (notification plus vote with a timeout), LLM judge (a model votes allow or deny with a reason, with verdict caching), and webhook (POST the context, expect a JSON verdict).
- Action-bound, fail-closed coordination per ADR-0030 (action binding plus digest, with a configurable timeout that defaults to deny).
- Audit records for the approval request, each vote, and the final verdict.
Gap in other SDKs
All four SDKs already recognize the require_approval verdict and carry an approver count, but none implement the approval-chain execution layer (no coordinator, no approver types, no timeout or audit linkage):
| SDK | Path | Current state |
|---|---|---|
| TypeScript | agent-governance-typescript/ |
require_approval is a valid policy action in src/policy.ts, no chain execution |
| .NET | agent-governance-dotnet/ |
PolicyAction.RequireApproval plus an Approvers list in Policy/PolicyDecision.cs, no chain execution |
| Rust | agent-governance-rust/ |
a "requires-approval" decision plus min_approvals in agentmesh/src/policy.rs, no chain execution |
| Go | agent-governance-golang/ |
RequiresApproval plus MinApprovals in packages/agentmesh/policy.go, no chain execution |
Proposed work
For each SDK, port the approval-chain execution layer on top of the verdict support that already exists:
- route a
require_approvalverdict to an ordered approval chain that short-circuits on the first deny - implement at least the webhook approver as the MVP, then human and LLM judge approvers where the SDK has the surface for them
- honor the action-bound, fail-closed semantics from ADR-0030 (action binding plus digest, timeout defaults to deny)
- record the approval request, votes, and final verdict on the audit trail
- add tests covering the allow, deny, and timeout paths
One PR per language keeps each change reviewable. Where an approver type does not map cleanly onto a given SDK runtime, note it as not applicable rather than forcing it.
References
- Source feature: feat: human-in-the-loop and LLM judge approval chains for PolicyEvaluator #2478 (Python design and implementation)
- Python wiring: Track PolicyEvaluator/govern wiring for require_approval after ADR-0030 #3067 (PolicyEvaluator /
governafter ADR-0030) - Design anchor: ADR-0030 (action-bound, fail-closed approval protocol)
- Parity precedent: Track cross-language skill-aware audit trail hardening parity (TypeScript, .NET, Go, Rust) #2986, feat: language parity for wire-protocol-aware policy evaluation (TS, Rust, .NET, Go) #2537
Activity
github-actions commentedon Jun 16, 2026
🟡 Contributor Check: MEDIUM
Automated check by AGT Contributor Check.
carloshvp commentedon Jul 17, 2026
Current parity status:
This tracker should remain open until the four language slices are resolved. The next unclaimed implementation slice is .NET or Rust.
carloshvp commentedon Jul 17, 2026
.NET parity is now implemented in draft PR #3363. It adds the ADR-0030 action-bound approval flow, durable store contract, ordered stages, fail-closed webhook and timeout handling, audit linkage, tamper checks, idempotency, and one-time consume under
agent-governance-dotnet/. The zero-required-non-advisory-stage path is explicitly documented as fail-closed, aligned with the safer Go behavior. Local validation:dotnet build AgentGovernance.slnsucceeded anddotnet test AgentGovernance.slnpassed all 806 tests. This tracker should remain open for review and the remaining Rust slice.floze-the-genius commentedon Jul 22, 2026
Hi, I would like to take the remaining Rust slice of #3083.
I have a local implementation based on ADR-0030 that routes the existing
PolicyDecision::RequiresApprovalresult into an action-bound coordinator. The scope includes a durable store contract, ordered identity/role stages, fail-closed expiry, one-time execution consumption, hash-linked entries, linked audit events, and a runtime-neutral versioned webhook transport.Two deliberate choices:
The current local validation is 535 release-workspace tests passing, including 21 focused approval tests. Before I open the PR, does this scope match what you want for the Rust parity slice?
feat(typescript): add action-bound approval protocol parity (microsof…
imran-siddique commentedon Sep 19, 2026
Floze (@floze-the-genius) yes, this scope matches ADR-0030. Please open the Rust PR against current main and link it here.
Keeping LLM output advisory is required by the accepted design. Keeping the HTTP client outside the core crate is also fine, provided the adapter still verifies who approved and that the response belongs to the exact request.
Please include tests showing that changed actions, expired approvals and unverified approvers are rejected, and that two workers cannot use the same one-time approval. Show what survives a restart, and distinguish the storage interface from any working persistent implementation.
Keep #3083 open, since it tracks all four languages. This confirms the proposed scope; implementation review follows on the PR.