The outbound gate is policy + action-on-non-match, so "hold every send for review" is only expressible as a trick: policy allowlist with an empty list, so nothing matches and the non-match action always fires.
Hit this dogfooding my own agent inbox: with the gate at open and action "hold for review", every recipient matches and nothing is ever held - sends went straight out while the dashboard implied they were queued. It took reading the OpenAPI schema to find the empty-allowlist workaround. The wedge feature shouldn't be a riddle.
Proposal: add an optional require_review boolean to the outbound protection object.
"outbound": {
"gate": { "policy": "allowlist", "allowlist": [], "action": "review" },
"require_review": true
}
require_review: true short-circuits gate evaluation: every outbound send is held for review, regardless of policy or list contents.
- Composes instead of overloading: "review everything except these addresses" falls out of combining it with the allowlist.
- Fully additive: optional, defaults to false, no schema shape change, no migration, old clients ignore it.
Considered policy: none (never match, action always fires) - also additive, but "none" reads as "no protection", the opposite of its meaning, and it overloads matching semantics to express an orthogonal switch.
The dashboard "Always require human review" toggle then just writes require_review: true, and the empty-allowlist trick can retire as the documented path.
The outbound gate is policy + action-on-non-match, so "hold every send for review" is only expressible as a trick: policy
allowlistwith an empty list, so nothing matches and the non-match action always fires.Hit this dogfooding my own agent inbox: with the gate at
openand action "hold for review", every recipient matches and nothing is ever held - sends went straight out while the dashboard implied they were queued. It took reading the OpenAPI schema to find the empty-allowlist workaround. The wedge feature shouldn't be a riddle.Proposal: add an optional
require_reviewboolean to the outbound protection object.require_review: trueshort-circuits gate evaluation: every outbound send is held for review, regardless of policy or list contents.Considered
policy: none(never match, action always fires) - also additive, but "none" reads as "no protection", the opposite of its meaning, and it overloads matching semantics to express an orthogonal switch.The dashboard "Always require human review" toggle then just writes
require_review: true, and the empty-allowlist trick can retire as the documented path.