No AEP event / adapter mapping for "system permission layer already gated this action"
Repo: packages/aep (paired with an open-agent-audit issue on the adapter side)
Problem
When the platform's permission layer denies (or automatically approves) a high-risk tool call, the wasmagent AEP emitter records action.capability_decision.decision = 'deny' (or 'allow'), and that's all. Downstream, open-agent-audit's canonical schema does have a human_approval event type, but no adapter mapping produces one — because AEP has no "this was gated by a policy engine" signal distinct from "the agent decided" vs "a human decided".
The consequence: OAA's OAA-R-OVERSIGHT-001 fires as if no oversight ever happened, even when the platform gated the call.
(See companion issue in open-agent-audit — oaa-04-oversight-false-positive-on-adapted-aep.)
Evidence in wasmagent-js
packages/aep/src/types.ts:4-11:
export const CapabilityDecisionSchema = z.object({
capability: z.string(),
subject: z.string(),
resource: z.string(),
decision: z.enum(["allow", "deny", "ask_user", "dry_run"]),
reason_code: z.string().optional(),
});
The decision values are all system decisions. There is no analogue for "a human approved this", nor a way to distinguish "gated by policy engine at check-time" from "gate not present at all".
packages/aep/src/emitter.ts has addAction, addCapabilityDecision, addInputRef, addOutputRef, addVerifierResult, setBudgetLedger. There is NO addHumanApproval (or addPolicyGate) helper.
Impact
- Any AEP integrator that hooks a permission layer will look "unoverseen" from OAA's perspective — false positives.
- Real gaps in human review (a state-changing tool that was NOT gated) get lost in the noise.
- Emitters that want to signal "our policy engine caught this at layer X" have no schema-blessed way to say so.
Proposed fix (choose one)
Option 1 (schema addition): add a new field on CapabilityDecisionSchema:
export const CapabilityDecisionSchema = z.object({
capability: z.string(),
subject: z.string(),
resource: z.string(),
decision: z.enum(["allow", "deny", "ask_user", "dry_run"]),
reason_code: z.string().optional(),
/** The layer that made this decision. Adapters may map policy_gate to a
* human_approval-equivalent event so downstream oversight rules don't
* false-positive when the platform's permission layer already caught it. */
decided_by: z.enum(["policy_gate", "agent", "human_reviewer"]).optional(),
});
Option 2 (new event type): add an HumanApprovalRecord / PolicyGateRecord alongside ActionEvidence, with fields {approver_id, decision, justification, action_id}. The emitter grows addHumanApproval({...}). This is heavier but maps more cleanly to OAA's canonical human_approval.
Option 3 (docs only): document that CapabilityDecisionSchema.subject conventionally names the deciding layer (agent, human, policy_engine). Zero schema change but leaves everyone using string conventions.
We think Option 1 is the sweet spot — one field, zero new tables, backward compatible (optional), and gives the OAA adapter a clean signal.
Reciprocal work needed downstream
Once one of the options ships, open-agent-audit/packages/adapters/src/aep-v0_2.ts:213-219 should be updated so that capability_decision.decided_by === 'policy_gate' or 'human_reviewer' maps into a canonical human_approval event (rather than only policy_decision). We've filed a companion issue there.
Filed by: CATL Ariba Joule integration team. Our platform gates every state-changing action via a permission layer. We want that fact to survive into OAA's audit; today it doesn't.
No AEP event / adapter mapping for "system permission layer already gated this action"
Repo:
packages/aep(paired with an open-agent-audit issue on the adapter side)Problem
When the platform's permission layer denies (or automatically approves) a high-risk tool call, the wasmagent AEP emitter records
action.capability_decision.decision = 'deny'(or 'allow'), and that's all. Downstream, open-agent-audit's canonical schema does have ahuman_approvalevent type, but no adapter mapping produces one — because AEP has no "this was gated by a policy engine" signal distinct from "the agent decided" vs "a human decided".The consequence: OAA's
OAA-R-OVERSIGHT-001fires as if no oversight ever happened, even when the platform gated the call.(See companion issue in open-agent-audit —
oaa-04-oversight-false-positive-on-adapted-aep.)Evidence in wasmagent-js
packages/aep/src/types.ts:4-11:The
decisionvalues are all system decisions. There is no analogue for "a human approved this", nor a way to distinguish "gated by policy engine at check-time" from "gate not present at all".packages/aep/src/emitter.tshasaddAction,addCapabilityDecision,addInputRef,addOutputRef,addVerifierResult,setBudgetLedger. There is NOaddHumanApproval(oraddPolicyGate) helper.Impact
Proposed fix (choose one)
Option 1 (schema addition): add a new field on
CapabilityDecisionSchema:Option 2 (new event type): add an
HumanApprovalRecord/PolicyGateRecordalongsideActionEvidence, with fields{approver_id, decision, justification, action_id}. The emitter growsaddHumanApproval({...}). This is heavier but maps more cleanly to OAA's canonicalhuman_approval.Option 3 (docs only): document that
CapabilityDecisionSchema.subjectconventionally names the deciding layer (agent, human, policy_engine). Zero schema change but leaves everyone using string conventions.We think Option 1 is the sweet spot — one field, zero new tables, backward compatible (optional), and gives the OAA adapter a clean signal.
Reciprocal work needed downstream
Once one of the options ships,
open-agent-audit/packages/adapters/src/aep-v0_2.ts:213-219should be updated so thatcapability_decision.decided_by === 'policy_gate'or'human_reviewer'maps into a canonicalhuman_approvalevent (rather than onlypolicy_decision). We've filed a companion issue there.Filed by: CATL Ariba Joule integration team. Our platform gates every state-changing action via a permission layer. We want that fact to survive into OAA's audit; today it doesn't.