Skip to content

Python: build the Agent Hooks middleware from a host declaration document #9329

Open

Description

@MohammadHaroonAbuomar

Motivation

Agent Framework supports Agent Hooks in Python through create_agent_hooks_middleware. Today a host configures it in code: interceptors, composition, identity provider, resolver, mode. Agent Hooks 0.1.0-beta.2 adds a host declaration document (spec section 7.7, contract agent-hooks-declaration/1.0): one JSON file that states the host's configuration, its declared surface, and its interceptor bindings by kind. An administrator can deploy that file through existing settings channels, and the loader refuses anything the host's code cannot honour before any emission.

Agent Framework should accept that document.

Proposal

Add a way to build the Agent Hooks middleware from a declaration, next to the existing code path:

  • create_agent_hooks_middleware_from_declaration(document_or_path_or_json, *, registry=None, ...) that loads through InterceptionEmitter.from_declaration_* from agent-hooks-sdk.
  • A host registry over Agent Framework's surface (all eight points, terminate posture, the capabilities the adapter declares today) where an app registers its own binding kinds, resolver and redactor.
  • A framework binding kind agent_framework.interceptor so a document can name an interceptor registered in code.

The existing code path keeps working. The document must state tool_seam_host_error: terminate, because the contract defaults to continue and the loader refuses a mismatch with the code's posture.

Scope

  • python/packages/core/agent_framework/_agent_hooks.py and the package exports.
  • Tests that run offline, covering the three construction paths, each refusal class, and the posture rule.
  • Bump the agent-hooks-sdk dev pin to 0.1.0b2 so the new tests run in CI.

Notes

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 13, 2026
  2. sunny-kavixo commented on Oct 13, 2026

    @sunny-kavixo

    Hi MohammadHaroonAbuomar and Microsoft Agent Framework maintainers,

    I'm interested in contributing to Issue #9329.

    I have experience with Python, AI agent workflows, middleware integration, debugging, and regression testing. I've also contributed to Docling Pipelines and submitted a fix for Microsoft Amplifier (PR #205).

    I reviewed the proposed implementation scope and noticed that no pull request is currently linked.

    Before starting, could you please confirm whether this issue is available for contribution and whether the proposed API design is ready for implementation?

    I'd be happy to collaborate with the original author, follow the repository's contribution guidelines, implement the changes incrementally, and add the required offline tests.

    Thank you for your consideration!

  3. eavanvalkenburg commented on Oct 13, 2026

    @eavanvalkenburg
    Member

    /plan

  4. github-actions commented on Oct 13, 2026

    @github-actions
    Contributor

    Summary

    The issue asks Agent Framework (Python) to support building the AGENT-HOOKS-0.1 enforcement middleware from a host declaration document — a JSON file (added in agent-hooks-sdk 0.1.0-beta.2, spec §7.7) that states host configuration, declared surface, and interceptor bindings, instead of only configuring everything in Python code as today.

    I verified the relevant code and the upstream spec/SDK directly (not from any proposed PR):

    • Today, python/packages/core/agent_framework/_agent_hooks.py exposes exactly two public factories: create_agent_hooks_middleware(...) (code-only configuration) and create_agent_hooks_middleware_from_emitter(...) (host-owned InterceptionEmitter/AgentContextBuilder). Both return a MiddlewareBundle. There is no declaration-document path.
    • agent-hooks-sdk 0.1.0-beta.2 (released the same day as this issue) does add exactly what's described: HostDeclaration, HostRegistry, HostSurface, DeclarationError, and InterceptionEmitter.from_declaration / from_declaration_path / from_declaration_json / from_declaration_value, per the upstream CHANGELOG and declaration.py.
    • The current dev pin in python/pyproject.toml is agent-hooks-sdk>=0.1.0a4,<0.2, which does not yet guarantee 0.1.0-beta.2 is resolved/tested in CI, confirming the issue's point about bumping the pin.
    • A prior conformance report (conformance/claims/maf/REPORT.md in the agent-hooks repo) shows Agent Framework already has a full 47/47 conformance claim on the code-configured path, including the tool_seam_host_error: terminate posture this issue calls out as required — so that posture requirement is a real, already-understood constraint, not new.

    No existing feature, workaround, or sample in this repository currently exposes a declaration-document loader, so this is a genuine capability gap rather than something already solved.

    Recommendation

    Code change is warranted. This is a natural, additive extension of an already-merged, first-class experimental feature (create_agent_hooks_middleware, merged via #7515), following the same one-factory/private-middleware pattern. It lets hosts move interception configuration out of Python code into a deployable JSON file managed through existing settings/config channels — a capability the upstream SDK now explicitly supports and that other language SDKs (Rust, TypeScript, .NET, Go) already implement. The risk is low: it's purely additive (new factory, no changes to existing factories' behavior), and the existing module already isolates the optional agent-hooks-sdk dependency behind lazy imports, so the pattern extends cleanly.

    Proposed plan

    1. Add create_agent_hooks_middleware_from_declaration(...) in _agent_hooks.py, mirroring the existing two factories:
      • Accept a HostDeclaration, a file path, or a JSON string/parsed value (three construction forms, matching the SDK's from_declaration / from_declaration_path / from_declaration_json / from_declaration_value), plus an optional registry: HostRegistry | None for app-registered resolver names, approval resolvers, and redactors.
      • Internally build the InterceptionEmitter through the SDK's loader and reuse the existing _build_bundle(...) plumbing so the returned MiddlewareBundle behaves identically to the other two factories.
      • Surface DeclarationError (and its refusal classes) unchanged so a bad document fails closed before any middleware runs, per the SDK's documented behavior.
    2. Expose a default HostRegistry over Agent Framework's own surface (all eight interception points, the terminate posture the framework already enforces at the tool seam, and the capabilities the framework already declares in its conformance report), so a minimal document can be loaded without the app building a registry from scratch. Let apps extend it with their own binding kinds, resolver, and redactor.
    3. Add the agent_framework.interceptor binding kind, a resolver that looks up an interceptor previously registered in code (by name), so a declaration document can reference code-defined interceptors without embedding arbitrary code in JSON.
    4. Update exports: add the new factory to __init__.py's lazy export map and __init__.pyi, and to PACKAGE_STATUS.md's AGENT_HOOKS entry, consistent with the repo's lazy-export conventions.
    5. Bump the dev dependency agent-hooks-sdk floor in python/pyproject.toml from >=0.1.0a4 to >=0.1.0b2 so CI actually exercises the declaration loader.
    6. Tests in test_agent_hooks.py (or a new test file) covering, offline:
      • All three construction paths (document object, path, JSON string) producing an equivalent bundle.
      • Each of the documented refusal classes (e.g., unsupported version, unknown field, unresolved reference/kind, surface the host can't honor) raising DeclarationError before any middleware executes.
      • The tool_seam_host_error: terminate posture rule: a document that doesn't declare terminate is refused, since the framework's code posture is fixed.
      • That existing create_agent_hooks_middleware / create_agent_hooks_middleware_from_emitter behavior and tests remain unaffected (regression safety for the two existing paths).
    7. Documentation: extend the module docstring and any relevant sample/README text to describe the declaration path alongside the two existing factories.

    You'd know this is resolved when: the new factory builds a working MiddlewareBundle from a real declaration document in a test, each refusal class is exercised and asserted, the agent-hooks-sdk floor is bumped and CI stays green, and the existing two factories' tests still pass unchanged.

    This is a proposal only — no code has been changed. One open question worth confirming before implementation: whether the default HostRegistry's declared capability list should mirror exactly what's in the existing upstream conformance claim (model_calls, tool_calls, int64_json, bigint_json, host_declaration) or be narrower/broader for the initial version.

    Generated by Issue Planning for #9329 · copilot · auto · 137.9 AIC · ⌖ 4.93 AIC · ⊞ 10.8K · ◷

  5. sunny-kavixo commented on Oct 13, 2026

    @sunny-kavixo

    Hi Eduard van Valkenburg (@eavanvalkenburg) and MohammadHaroonAbuomar,

    Thank you for initiating the planning process and providing the detailed implementation proposal.

    I've reviewed the generated plan, including the declaration-based factory, HostRegistry configuration, interceptor bindings, SDK dependency update, and offline regression coverage.

    I'm interested in contributing to this implementation and would be happy to follow the proposed architecture.

    Before starting, could you please confirm whether I may take ownership of this issue and whether the default HostRegistry capabilities should match the existing conformance claim or use a narrower initial scope?

    Once confirmed, I can begin with a focused implementation, preserve backward compatibility, add the required tests, and submit a PR for review.

    Thank you for your guidance!

  6. MohammadHaroonAbuomar commented on Oct 15, 2026

    @MohammadHaroonAbuomar
    ContributorAuthor

    Thank you Sandeep | AI Data & Automation (@sunny-kavixo) for offering to take this on. The implementation is up as #9405. Reviews are welcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Python

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions