Catalog PyPI
Back to packageRELEASE DETAILS

0.1.0b2

PyPI

agent-hooks-sdk

Framework-neutral agent control contract: interception points, agent context, verdict, and conformance test kit. Python wrapper over the canonical Rust core. Cooperative contract, not a security boundary: the host is fully trusted (see SECURITY.md).

ai-agentsconformancecontrolgovernanceinterception
Published13 Oct 2026
Direct dependencies6
Transitive dependenciesNot calculated

README

Version 0.1.0b2 documentation

agent-hooks (Python SDK)

Python implementation of AGENT-HOOKS-0.1: interception-point enums, AgentContext builder, Verdict types, host-side InterceptionEmitter with the four composition profiles, the pluggable identity-provider seam, and the Conformance Test Kit.

Trust model. agent-hooks is a cooperative contract, not a security boundary: the host framework is fully trusted, interceptors run in-process with full data access, and no complete-mediation claim is made. Read SECURITY.md and spec §1.4 before relying on it.

pip install --pre "agent-hooks-sdk[ctk]"
# import name: agent_hooks

Host (framework adapter) usage

from agent_hooks import AgentContextBuilder, InterceptionBlocked, InterceptionEmitter

builder = AgentContextBuilder(agent_id="my-agent", framework="my-fw", session_id="s-1")
emitter = InterceptionEmitter().register(MyPolicy())

await emitter.emit(builder.agent_startup(tools_registered=["http_get"]))
ctx = builder.pre_tool_call(call_id="tc-1", name="http_get", args={"url": url})
try:
    await emitter.emit(ctx)
except InterceptionBlocked as e:
    return tool_error(e.result.verdict.reason)
result = invoke_tool(ctx["tool_call"]["args"])  # post-transform args

Host declaration

A host can load its configuration, declared surface and interceptor bindings from a host declaration document (spec §7.7) instead of calling the setters. The document is a versioned contract of its own, agent-hooks-declaration/1.0, separate from the wire version. The host registers in code what the document may reference: kind resolvers, custom identity providers, approval resolvers and redactors, plus the surface its code supports.

from agent_hooks import HostRegistry, HostSurface, InterceptionEmitter

registry = (
    HostRegistry(HostSurface.from_capabilities(["model_calls", "tool_calls", "host_declaration"]))
    .kind("com.example.egress", lambda config, ctx: EgressGuard(**config))
    .approval_resolver("operator-queue", OperatorQueue())
)
emitter = InterceptionEmitter.from_declaration_path("agent-hooks.declaration.json", registry)

from_declaration_json(text, registry), from_declaration_value(obj, registry) and from_declaration(HostDeclaration.builder().mode("enforce").bind(...).build(), registry) build the same emitter from JSON text, a parsed value or code; equal documents yield byte-identical records. A document that names anything the registry cannot honour is refused before any emission with DeclarationError, which carries .code (declaration_error:<class>), .findings (JSON pointer and detail) and, for an unsupported version, .accepted. The emitter is then sealed: register and the configuration setters raise EmitterSealed; the record sink and take_records stay open. Every record stamps declaration with the contract version, and emitter.declaration holds the resolved document whose canonical_json() is the equivalence oracle.

DECLARATION_VERSION and SUPPORTED_DECLARATION_VERSIONS name the contract versions this SDK writes and accepts; they sit next to SPEC_VERSION.

Interceptor usage

from agent_hooks import AgentContext, Verdict


class MyPolicy:
    def intercept(self, ctx: AgentContext) -> Verdict:
        if ctx["interception_point"] == "pre_tool_call" and ctx["tool_call"]["name"] == "rm":
            return Verdict.deny(reason="dangerous")
        return Verdict.allow()

Verdict.allow(), Verdict.deny(...), Verdict.warn(...) (allow + recorded warning) and Verdict.escalate(...) (liftable deny for the approval seam, §9) are the constructor shortcuts for the §5 shapes.

Running the CTK against your framework

Implement agent_hooks.ctk.Harness (see conformance/HARNESS.md). A harness that declares Capability.HOST_DECLARATION also implements setup_declared(scenario, document, registry) and builds its emitter with InterceptionEmitter.from_declaration_value(document, registry); one that does not skips the declaration/* vectors with a stated reason. Then:

pytest --agent-hooks-harness=my_pkg:MyHarness

The vectors ship inside the wheel; pass --agent-hooks-vectors=<dir> only to run a different vector set.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 6

Native requirements
6 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
jsonschema
Environment
{
  "extras": "",
  "marker": "extra == \"ctk\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
jsonschema>=4.26.0; extra == "ctk"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"ctk\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
pytest>=9.1.1; extra == "ctk"runtime
agent-hooks-sdk
Environment
{
  "extras": "ctk",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
agent-hooks-sdk[ctk]; extra == "dev"runtime
mypy
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
mypy>=2.2.0; extra == "dev"runtime
ruff
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
ruff>=0.15.21; extra == "dev"runtime
maturin
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.10",
  "evaluation": "NOT_EVALUATED"
}
maturin<2.0,>=1.14.1; extra == "dev"runtime

Distribution files

6 collected
agent_hooks_sdk-0.1.0b2-cp310-abi3-macosx_10_12_x86_64.whl

bdist_wheel · 759.2 KB · Python cp310

Source file
agent_hooks_sdk-0.1.0b2-cp310-abi3-macosx_11_0_arm64.whl

bdist_wheel · 720.78 KB · Python cp310

Source file
agent_hooks_sdk-0.1.0b2-cp310-abi3-manylinux_2_28_aarch64.whl

bdist_wheel · 779.28 KB · Python cp310

Source file
agent_hooks_sdk-0.1.0b2-cp310-abi3-manylinux_2_28_x86_64.whl

bdist_wheel · 817.42 KB · Python cp310

Source file
agent_hooks_sdk-0.1.0b2-cp310-abi3-win_amd64.whl

bdist_wheel · 640.6 KB · Python cp310

Source file
agent_hooks_sdk-0.1.0b2.tar.gz

sdist · 219.11 KB · Python source

Source file

Repository

PENDING
responsibleai/agent-hooks

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 22:10 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:48b6f3aec89cccb637d4ffe0f54d48937b69a5ff7a0708705ad5441c3a7f85d8

Other collected versions

View all collected versions →