v0.8.4 — @requires_human_oversight decorator (Code-as-Harness anchor)
Wednesday cut on top of v0.8.3. Patch bump — one new public decorator + protocol shapes. No breaking changes.
Honest framing (called out before the code)
The 2026-05-20 Product Improvements doc proposed an @requires_human_oversight decorator backed by a new audit_emitter.await_response(request_id, timeout=...) bidirectional RPC channel. agent-airlock's existing audit emitter is one-way (emit-only, sinks to log/OTel/file). Grafting a request/response channel onto a sink would have invented a new transport abstraction inside the library.
Honest reframe: operator-supplied approver callable, same shape as v0.8.1 vaccinate_openapi(spec) / v0.8.3 classify_sdk_lineage(...) building-block pattern. agent-airlock ships the decorator + protocol shapes; the operator owns the transport (Slack, PagerDuty, CLI prompt, whatever).
ADD — @requires_human_oversight decorator
from agent_airlock import requires_human_oversight, OversightVerdict, OversightResponse
def slack_approver(req):
decision = my_slack_client.request_approval(channel=req.channel, tool=req.tool_name, args=req.args, timeout=req.timeout_seconds)
return OversightResponse(
request_id=req.request_id,
verdict=OversightVerdict.GRANT if decision == "approve" else OversightVerdict.DENY,
approver=decision.user_email,
)
@requires_human_oversight(approver=slack_approver, channel="prod-deploys")
def deploy_to_prod(version: str) -> str:
return cluster.deploy(version)| Verdict | Behaviour |
|---|---|
GRANT |
Wrapped function called, return value returned |
DENY |
OversightDeniedError raised (carries request + response for audit) |
TIMEOUT |
OversightTimeoutError raised (carries request) |
request_id mismatch |
ValueError (protocol fault — catches buggy approvers loudly) |
- Composes with
@Airlock(...)— stack the oversight gate outside the airlock decorator so human approval fires before policy validation InProcessRecordedApprovertesting helper returns pre-set verdicts per tool name; unrecorded tools default to TIMEOUT- Audit events:
oversight.request | .grant | .deny | .timeoutvia optional one-wayaudit_emittercallable + always viaagent-airlock.oversightstructlog logger
NOTE — Suggestion 2 (multi-agent topology adapter) deferred
The 2026-05-20 doc proposed a Co-Scientist-style multi-agent supervisor adapter (Nature 2026-05-19). The doc itself tagged it [major-needs-decision]. v0.8.4 does not include it — the strategic question is logged at ROADMAP_2026.md#post-v084-strategic-question-2026-05-20.
The doc's framing of S2 as "per-vendor vs per-framework" was inaccurate — agent-airlock already ships vendor-specific adapters (gemini3_tool_shape_adapter.py, gpt5_5_tool_shape_adapter.py, anthropic_claude_agent_sdk.py). The real question (reframed in the roadmap): should we add a multi-agent topology adapter shape distinct from existing single-agent tool-shape adapters?
Stats
- 2,487 tests · 83.11% coverage (gate 82%)
- CI 7/7 green (lint, security, GitGuardian, test 3.10/3.11/3.12/3.13)
- Surface additions in
__all__: 8 new symbols
Install
pip install agent-airlock==0.8.4