Skip to content

Python: agent-framework-agent-hooks — middleware adapter for the AGENT-HOOKS-0.1 control contract - #1

Draft
MohammadHaroonAbuomar wants to merge 5 commits into
mainfrom
feature/agent-hooks-contract
Draft

Python: agent-framework-agent-hooks — middleware adapter for the AGENT-HOOKS-0.1 control contract#1
MohammadHaroonAbuomar wants to merge 5 commits into
mainfrom
feature/agent-hooks-contract

Conversation

@MohammadHaroonAbuomar

Copy link
Copy Markdown
Owner

Problem

Controls for agentic workloads (policy engines, approval flows, information-flow checks, audit pipelines) are rebuilt per framework, and each framework answers differently whether a control can stop an action, what happens when a control crashes, and what evidence exists afterwards. AGENT-HOOKS-0.1 (https://github.com/responsibleai/agent-hooks) is a framework-neutral control contract: eight interception points, a three-verdict model (allow / deny with optional human-approval lift / transform), normative fail-closed host obligations, and a conformance kit that makes "supported" checkable (https://responsibleai.github.io/agent-hooks/).

What this adds

A self-contained workspace package, agent-framework-agent-hooks, following the layout of the existing integration packages. One factory wires the contract into the middleware pipeline:

agent = Agent(..., middleware=agent_hooks_middleware(interceptors=[policy], resolver=approvals))

Middleware mapping (full analysis in MAPPING.md)

Agent Framework seam Interception point
AgentMiddleware input / output (plus synthesized agent_startup / agent_shutdown per run)
ChatMiddleware pre_model_call / post_model_call
FunctionMiddleware pre_tool_call / post_tool_call (transform writes back into executed arguments)

All three tiers have native control semantics (call_next, MiddlewareTermination, result override), so blocking and transforming compose with the framework rather than fighting it. Deny anywhere raises MiddlewareTermination; adapter errors terminate the run (fail closed), never fall through.

Limitations (deliberate, documented in MAPPING.md)

  • No framework lifecycle seam for session boundaries: agent_startup/agent_shutdown bracket one agent run (a session-scoped seam is the concrete upstream ask).
  • Streaming runs enforce pre-action points only; post/output enforcement over streams needs a stream_result_hooks integration (natural follow-up).
  • post_model_call tool-call extraction is best-effort across client result shapes.

Test evidence

5/5 pytest green against published agent-hooks-sdk 0.1.0a4: run-point sequencing, deny-blocks-tool with post-point suppression and session-trail closure, transform write-back proving execution sees the approved value, and no-op behavior outside a bracketed run. Ruff clean under the repository configuration.

Conformance

The contract ships a 47-vector conformance kit and a public claims registry; the reference policy runtime (https://github.com/responsibleai/agent-control-spec) passes 46/47 as an interceptor-side consumer. An Agent Framework host conformance claim would follow once the streaming and session seams land.

Survey of how the eight interception points of the agent-hooks control
contract (github.com/responsibleai/agent-hooks) land on the Python
middleware pipeline: agent/chat/function middleware cover six points
cleanly; the run brackets are synthesized with a session-per-run scope;
streaming post-action points and session-scoped brackets are the two
seams that would need upstream support.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
agent-framework-agent-hooks implements AGENT-HOOKS-0.1 on the
middleware pipeline: the middleware trio emits the eight interception
points (session-per-run scope), block verdicts terminate via
MiddlewareTermination with the post-action result discarded, transforms
write back through the context so execution uses the approved value,
and composition/approval/identity/record semantics come from the
published agent-hooks-sdk package. Tests cover allow/deny/transform
flows and no-op behavior outside a bracketed run.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Adopts the deny constructor introduced in 0.1.0a4 in place of wire
dicts; transform and allow verdicts use the typed constructors.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>

@MohammadHaroonAbuomar MohammadHaroonAbuomar left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review pass (self-review before sharing). Findings; fixes follow on the branch.

  1. post_tool_call is skipped when the tool raises. AgentHooksFunctionMiddleware.process emits the post point only on the success path; a raising call_next propagates without post_tool_call (is_error: true). The contract brackets every completed invocation, success or error.
  2. Raw context.result flows into the post_tool_call value. A non-JSON-serializable tool result would fail inside the emitter's marshalling, terminating the run with a crash-shaped error rather than a typed record; project the value defensively the way _arguments_to_dict does for arguments.

@MohammadHaroonAbuomar
MohammadHaroonAbuomar force-pushed the feature/agent-hooks-contract branch from 6104483 to 479b412 Compare July 30, 2026 04:33
A raising tool invocation still emits post_tool_call with
tool_result.is_error before the exception propagates, and tool results
are projected to JSON-safe values before marshalling so an exotic
result type cannot crash the record path. Covered by a new test.

Signed-off-by: MohammadHaroonAbuomar <40180927+MohammadHaroonAbuomar@users.noreply.github.com>
@MohammadHaroonAbuomar
MohammadHaroonAbuomar force-pushed the feature/agent-hooks-contract branch from 479b412 to 00ea9f5 Compare July 30, 2026 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant