agent-hooks-sdk 0.1.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. agent_hooks_sdk-0.1.0a1/PKG-INFO +79 -0
  2. agent_hooks_sdk-0.1.0a1/README.md +49 -0
  3. agent_hooks_sdk-0.1.0a1/pyproject.toml +59 -0
  4. agent_hooks_sdk-0.1.0a1/python/Cargo.lock +332 -0
  5. agent_hooks_sdk-0.1.0a1/python/Cargo.toml +19 -0
  6. agent_hooks_sdk-0.1.0a1/python/README.md +49 -0
  7. agent_hooks_sdk-0.1.0a1/python/agent_hooks/__init__.py +66 -0
  8. agent_hooks_sdk-0.1.0a1/python/agent_hooks/_core.pyi +26 -0
  9. agent_hooks_sdk-0.1.0a1/python/agent_hooks/_types.py +279 -0
  10. agent_hooks_sdk-0.1.0a1/python/agent_hooks/approval.py +54 -0
  11. agent_hooks_sdk-0.1.0a1/python/agent_hooks/canonical.py +32 -0
  12. agent_hooks_sdk-0.1.0a1/python/agent_hooks/context.py +168 -0
  13. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/__init__.py +23 -0
  14. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/_schemas.py +36 -0
  15. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/harness.py +127 -0
  16. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/plugin.py +63 -0
  17. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/reference.py +139 -0
  18. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/runner.py +119 -0
  19. agent_hooks_sdk-0.1.0a1/python/agent_hooks/ctk/scripted.py +73 -0
  20. agent_hooks_sdk-0.1.0a1/python/agent_hooks/emitter.py +224 -0
  21. agent_hooks_sdk-0.1.0a1/python/agent_hooks/exceptions.py +41 -0
  22. agent_hooks_sdk-0.1.0a1/python/agent_hooks/interceptor.py +21 -0
  23. agent_hooks_sdk-0.1.0a1/python/agent_hooks/path.py +90 -0
  24. agent_hooks_sdk-0.1.0a1/python/agent_hooks/py.typed +0 -0
  25. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/agent_shutdown.schema.json +391 -0
  26. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/agent_startup.schema.json +391 -0
  27. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/input.schema.json +391 -0
  28. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/output.schema.json +391 -0
  29. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/post_model_call.schema.json +393 -0
  30. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/post_tool_call.schema.json +393 -0
  31. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/pre_model_call.schema.json +392 -0
  32. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context/pre_tool_call.schema.json +391 -0
  33. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/agent-context.schema.json +230 -0
  34. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/approval.schema.json +59 -0
  35. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/interception-point.schema.json +17 -0
  36. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/interception-record.schema.json +56 -0
  37. agent_hooks_sdk-0.1.0a1/python/agent_hooks/schema/verdict.schema.json +73 -0
  38. agent_hooks_sdk-0.1.0a1/python/src/lib.rs +141 -0
  39. agent_hooks_sdk-0.1.0a1/python/tests/__init__.py +0 -0
  40. agent_hooks_sdk-0.1.0a1/python/tests/test_canonical.py +55 -0
  41. agent_hooks_sdk-0.1.0a1/python/tests/test_ctk_reference.py +28 -0
  42. agent_hooks_sdk-0.1.0a1/python/tests/test_decided_by.py +49 -0
  43. agent_hooks_sdk-0.1.0a1/python/tests/test_golden_identity.py +38 -0
  44. agent_hooks_sdk-0.1.0a1/python/tests/test_path.py +50 -0
  45. agent_hooks_sdk-0.1.0a1/python/tests/test_types.py +67 -0
  46. agent_hooks_sdk-0.1.0a1/rust/Cargo.toml +17 -0
  47. agent_hooks_sdk-0.1.0a1/rust/core/Cargo.toml +31 -0
  48. agent_hooks_sdk-0.1.0a1/rust/core/src/builder.rs +216 -0
  49. agent_hooks_sdk-0.1.0a1/rust/core/src/canonical.rs +148 -0
  50. agent_hooks_sdk-0.1.0a1/rust/core/src/ctk.rs +412 -0
  51. agent_hooks_sdk-0.1.0a1/rust/core/src/ctk_engine.rs +450 -0
  52. agent_hooks_sdk-0.1.0a1/rust/core/src/emitter.rs +236 -0
  53. agent_hooks_sdk-0.1.0a1/rust/core/src/enforce.rs +216 -0
  54. agent_hooks_sdk-0.1.0a1/rust/core/src/ffi_surface.rs +183 -0
  55. agent_hooks_sdk-0.1.0a1/rust/core/src/lib.rs +47 -0
  56. agent_hooks_sdk-0.1.0a1/rust/core/src/path.rs +224 -0
  57. agent_hooks_sdk-0.1.0a1/rust/core/src/types.rs +307 -0
  58. agent_hooks_sdk-0.1.0a1/rust/core/src/verdict.rs +197 -0
  59. agent_hooks_sdk-0.1.0a1/rust/core/tests/ctk_reference.rs +23 -0
  60. agent_hooks_sdk-0.1.0a1/rust/core/tests/golden_identity.rs +56 -0
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-hooks-sdk
3
+ Version: 0.1.0a1
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Rust
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Requires-Dist: jsonschema>=4.21 ; extra == 'ctk'
14
+ Requires-Dist: pytest>=7.4 ; extra == 'ctk'
15
+ Requires-Dist: agent-hooks-sdk[ctk] ; extra == 'dev'
16
+ Requires-Dist: mypy>=1.8 ; extra == 'dev'
17
+ Requires-Dist: ruff>=0.4 ; extra == 'dev'
18
+ Requires-Dist: maturin>=1.7,<2.0 ; extra == 'dev'
19
+ Provides-Extra: ctk
20
+ Provides-Extra: dev
21
+ Summary: Framework-neutral agent control contract: interception points, agent context, verdict, and conformance test kit. Python wrapper over the canonical Rust core.
22
+ Keywords: ai-agents,governance,interception,control,conformance
23
+ Author-email: Responsible AI <responsibleai@microsoft.com>
24
+ License: MIT
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
27
+ Project-URL: Homepage, https://github.com/responsibleai/agent-hooks
28
+ Project-URL: Specification, https://github.com/responsibleai/agent-hooks/blob/main/spec/AGENT-HOOKS-0.1.md
29
+
30
+ # agent-hooks (Python SDK)
31
+
32
+ Python implementation of [AGENT-HOOKS-0.1](../../spec/AGENT-HOOKS-0.1.md):
33
+ interception-point enums, `AgentContext` builder, `Verdict` types, host-side
34
+ `InterceptionEmitter`, and the Conformance Test Kit.
35
+
36
+ ```bash
37
+ # Not yet on PyPI (the name "agent-hooks" is held by an unrelated
38
+ # project; the distribution is named agent-hooks-sdk). Install from source:
39
+ pip install "agent-hooks-sdk @ git+https://github.com/responsibleai/agent-hooks#subdirectory=sdk/python"
40
+ ```
41
+
42
+ ## Host (framework adapter) usage
43
+
44
+ ```python
45
+ from agent_hooks import AgentContextBuilder, InterceptionEmitter, InterceptionBlocked
46
+
47
+ builder = AgentContextBuilder(agent_id="...", framework="my-fw", session_id="...")
48
+ emitter = InterceptionEmitter().register(my_consumer)
49
+
50
+ await emitter.emit(builder.agent_startup(tools_registered=[...]))
51
+ ctx = builder.pre_tool_call(call_id="tc-1", name="http_get", args={"url": u})
52
+ try:
53
+ await emitter.emit(ctx)
54
+ except InterceptionBlocked as e:
55
+ return tool_error(e.result.verdict.reason)
56
+ result = invoke_tool(ctx["tool_call"]["args"]) # post-transform args
57
+ ```
58
+
59
+ ## Interceptor usage
60
+
61
+ ```python
62
+ from agent_hooks import Interceptor, AgentContext, Verdict, Decision
63
+
64
+ class MyPolicy:
65
+ def intercept(self, ctx: AgentContext) -> Verdict:
66
+ if ctx["interception_point"] == "pre_tool_call" and ctx["tool_call"]["name"] == "rm":
67
+ return Verdict(Decision.DENY, reason="dangerous")
68
+ return Verdict.ALLOW
69
+ ```
70
+
71
+ ## Running the CTK against your framework
72
+
73
+ Implement `agent_hooks.ctk.Harness` (see `conformance/HARNESS.md`), then:
74
+
75
+ ```bash
76
+ pytest --agent-hooks-harness=my_pkg:MyHarness \
77
+ --agent-hooks-vectors=path/to/conformance/vectors
78
+ ```
79
+
@@ -0,0 +1,49 @@
1
+ # agent-hooks (Python SDK)
2
+
3
+ Python implementation of [AGENT-HOOKS-0.1](../../spec/AGENT-HOOKS-0.1.md):
4
+ interception-point enums, `AgentContext` builder, `Verdict` types, host-side
5
+ `InterceptionEmitter`, and the Conformance Test Kit.
6
+
7
+ ```bash
8
+ # Not yet on PyPI (the name "agent-hooks" is held by an unrelated
9
+ # project; the distribution is named agent-hooks-sdk). Install from source:
10
+ pip install "agent-hooks-sdk @ git+https://github.com/responsibleai/agent-hooks#subdirectory=sdk/python"
11
+ ```
12
+
13
+ ## Host (framework adapter) usage
14
+
15
+ ```python
16
+ from agent_hooks import AgentContextBuilder, InterceptionEmitter, InterceptionBlocked
17
+
18
+ builder = AgentContextBuilder(agent_id="...", framework="my-fw", session_id="...")
19
+ emitter = InterceptionEmitter().register(my_consumer)
20
+
21
+ await emitter.emit(builder.agent_startup(tools_registered=[...]))
22
+ ctx = builder.pre_tool_call(call_id="tc-1", name="http_get", args={"url": u})
23
+ try:
24
+ await emitter.emit(ctx)
25
+ except InterceptionBlocked as e:
26
+ return tool_error(e.result.verdict.reason)
27
+ result = invoke_tool(ctx["tool_call"]["args"]) # post-transform args
28
+ ```
29
+
30
+ ## Interceptor usage
31
+
32
+ ```python
33
+ from agent_hooks import Interceptor, AgentContext, Verdict, Decision
34
+
35
+ class MyPolicy:
36
+ def intercept(self, ctx: AgentContext) -> Verdict:
37
+ if ctx["interception_point"] == "pre_tool_call" and ctx["tool_call"]["name"] == "rm":
38
+ return Verdict(Decision.DENY, reason="dangerous")
39
+ return Verdict.ALLOW
40
+ ```
41
+
42
+ ## Running the CTK against your framework
43
+
44
+ Implement `agent_hooks.ctk.Harness` (see `conformance/HARNESS.md`), then:
45
+
46
+ ```bash
47
+ pytest --agent-hooks-harness=my_pkg:MyHarness \
48
+ --agent-hooks-vectors=path/to/conformance/vectors
49
+ ```
@@ -0,0 +1,59 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.7,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ # Distribution name: "agent-hooks" is squatted on PyPI and the
7
+ # similarity check blocks all separator variants (incl. agenthooks).
8
+ # Import name stays agent_hooks.
9
+ name = "agent-hooks-sdk"
10
+ version = "0.1.0a1"
11
+ description = "Framework-neutral agent control contract: interception points, agent context, verdict, and conformance test kit. Python wrapper over the canonical Rust core."
12
+ readme = "README.md"
13
+ requires-python = ">=3.10"
14
+ license = { text = "MIT" }
15
+ authors = [{ name = "Responsible AI", email = "responsibleai@microsoft.com" }]
16
+ keywords = ["ai-agents", "governance", "interception", "control", "conformance"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Rust",
26
+ "Topic :: Software Development :: Libraries",
27
+ ]
28
+ dependencies = []
29
+
30
+ [project.optional-dependencies]
31
+ ctk = ["jsonschema>=4.21", "pytest>=7.4"]
32
+ dev = ["agent-hooks-sdk[ctk]", "mypy>=1.8", "ruff>=0.4", "maturin>=1.7,<2.0"]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/responsibleai/agent-hooks"
36
+ Specification = "https://github.com/responsibleai/agent-hooks/blob/main/spec/AGENT-HOOKS-0.1.md"
37
+
38
+ [project.entry-points.pytest11]
39
+ agent_hooks_ctk = "agent_hooks.ctk.plugin"
40
+
41
+ [tool.maturin]
42
+ module-name = "agent_hooks._core"
43
+ features = ["pyo3/extension-module"]
44
+ manifest-path = "python/Cargo.toml"
45
+ python-source = "python"
46
+
47
+ [tool.ruff]
48
+ line-length = 100
49
+ target-version = "py310"
50
+
51
+ [tool.ruff.lint]
52
+ select = ["E", "F", "W", "I", "B", "UP", "C4", "SIM", "RUF", "BLE"]
53
+ ignore = [
54
+ "RUF002", # en-dash in docstrings is intentional (spec section ranges)
55
+ ]
56
+
57
+ [tool.mypy]
58
+ strict = true
59
+ warn_unreachable = true
@@ -0,0 +1,332 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "agent-hooks-python"
7
+ version = "0.1.0-alpha.1"
8
+ dependencies = [
9
+ "agent-hooks-sdk",
10
+ "pyo3",
11
+ "pyo3-build-config",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "agent-hooks-sdk"
16
+ version = "0.1.0-alpha.1"
17
+ dependencies = [
18
+ "async-trait",
19
+ "serde",
20
+ "serde_jcs",
21
+ "serde_json",
22
+ "sha2",
23
+ "thiserror",
24
+ ]
25
+
26
+ [[package]]
27
+ name = "async-trait"
28
+ version = "0.1.89"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
31
+ dependencies = [
32
+ "proc-macro2",
33
+ "quote",
34
+ "syn",
35
+ ]
36
+
37
+ [[package]]
38
+ name = "block-buffer"
39
+ version = "0.10.4"
40
+ source = "registry+https://github.com/rust-lang/crates.io-index"
41
+ checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
42
+ dependencies = [
43
+ "generic-array",
44
+ ]
45
+
46
+ [[package]]
47
+ name = "cfg-if"
48
+ version = "1.0.4"
49
+ source = "registry+https://github.com/rust-lang/crates.io-index"
50
+ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
51
+
52
+ [[package]]
53
+ name = "cpufeatures"
54
+ version = "0.2.17"
55
+ source = "registry+https://github.com/rust-lang/crates.io-index"
56
+ checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
57
+ dependencies = [
58
+ "libc",
59
+ ]
60
+
61
+ [[package]]
62
+ name = "crypto-common"
63
+ version = "0.1.7"
64
+ source = "registry+https://github.com/rust-lang/crates.io-index"
65
+ checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
66
+ dependencies = [
67
+ "generic-array",
68
+ "typenum",
69
+ ]
70
+
71
+ [[package]]
72
+ name = "digest"
73
+ version = "0.10.7"
74
+ source = "registry+https://github.com/rust-lang/crates.io-index"
75
+ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
76
+ dependencies = [
77
+ "block-buffer",
78
+ "crypto-common",
79
+ ]
80
+
81
+ [[package]]
82
+ name = "generic-array"
83
+ version = "0.14.7"
84
+ source = "registry+https://github.com/rust-lang/crates.io-index"
85
+ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
86
+ dependencies = [
87
+ "typenum",
88
+ "version_check",
89
+ ]
90
+
91
+ [[package]]
92
+ name = "heck"
93
+ version = "0.5.0"
94
+ source = "registry+https://github.com/rust-lang/crates.io-index"
95
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
96
+
97
+ [[package]]
98
+ name = "itoa"
99
+ version = "1.0.18"
100
+ source = "registry+https://github.com/rust-lang/crates.io-index"
101
+ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
102
+
103
+ [[package]]
104
+ name = "libc"
105
+ version = "0.2.186"
106
+ source = "registry+https://github.com/rust-lang/crates.io-index"
107
+ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
108
+
109
+ [[package]]
110
+ name = "memchr"
111
+ version = "2.8.2"
112
+ source = "registry+https://github.com/rust-lang/crates.io-index"
113
+ checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
114
+
115
+ [[package]]
116
+ name = "once_cell"
117
+ version = "1.21.4"
118
+ source = "registry+https://github.com/rust-lang/crates.io-index"
119
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
120
+
121
+ [[package]]
122
+ name = "portable-atomic"
123
+ version = "1.13.1"
124
+ source = "registry+https://github.com/rust-lang/crates.io-index"
125
+ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
126
+
127
+ [[package]]
128
+ name = "proc-macro2"
129
+ version = "1.0.106"
130
+ source = "registry+https://github.com/rust-lang/crates.io-index"
131
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
132
+ dependencies = [
133
+ "unicode-ident",
134
+ ]
135
+
136
+ [[package]]
137
+ name = "pyo3"
138
+ version = "0.29.0"
139
+ source = "registry+https://github.com/rust-lang/crates.io-index"
140
+ checksum = "cd274650b21d4bfc26a0a47587962c1edb425f69287324355cd040c3ea66071c"
141
+ dependencies = [
142
+ "libc",
143
+ "once_cell",
144
+ "portable-atomic",
145
+ "pyo3-build-config",
146
+ "pyo3-ffi",
147
+ "pyo3-macros",
148
+ ]
149
+
150
+ [[package]]
151
+ name = "pyo3-build-config"
152
+ version = "0.29.0"
153
+ source = "registry+https://github.com/rust-lang/crates.io-index"
154
+ checksum = "c5e2a7d2f0d013342f295c048ad19237add5154a55b1c5a254c0ec93d4109078"
155
+ dependencies = [
156
+ "target-lexicon",
157
+ ]
158
+
159
+ [[package]]
160
+ name = "pyo3-ffi"
161
+ version = "0.29.0"
162
+ source = "registry+https://github.com/rust-lang/crates.io-index"
163
+ checksum = "ca85c467da1bbc8d866eea5deff9cf29ea5f7785054a17da36e65bda9c05845b"
164
+ dependencies = [
165
+ "libc",
166
+ "pyo3-build-config",
167
+ ]
168
+
169
+ [[package]]
170
+ name = "pyo3-macros"
171
+ version = "0.29.0"
172
+ source = "registry+https://github.com/rust-lang/crates.io-index"
173
+ checksum = "9ac53762fd065daa3194dd09337a38bd793a188100fd1a9304c4ab312d901771"
174
+ dependencies = [
175
+ "proc-macro2",
176
+ "pyo3-macros-backend",
177
+ "quote",
178
+ "syn",
179
+ ]
180
+
181
+ [[package]]
182
+ name = "pyo3-macros-backend"
183
+ version = "0.29.0"
184
+ source = "registry+https://github.com/rust-lang/crates.io-index"
185
+ checksum = "4ca3a1557399783172dc5bf39cfca835157732532cba56b71d2292161e53b362"
186
+ dependencies = [
187
+ "heck",
188
+ "proc-macro2",
189
+ "quote",
190
+ "syn",
191
+ ]
192
+
193
+ [[package]]
194
+ name = "quote"
195
+ version = "1.0.46"
196
+ source = "registry+https://github.com/rust-lang/crates.io-index"
197
+ checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
198
+ dependencies = [
199
+ "proc-macro2",
200
+ ]
201
+
202
+ [[package]]
203
+ name = "ryu-js"
204
+ version = "0.2.2"
205
+ source = "registry+https://github.com/rust-lang/crates.io-index"
206
+ checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f"
207
+
208
+ [[package]]
209
+ name = "serde"
210
+ version = "1.0.228"
211
+ source = "registry+https://github.com/rust-lang/crates.io-index"
212
+ checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
213
+ dependencies = [
214
+ "serde_core",
215
+ "serde_derive",
216
+ ]
217
+
218
+ [[package]]
219
+ name = "serde_core"
220
+ version = "1.0.228"
221
+ source = "registry+https://github.com/rust-lang/crates.io-index"
222
+ checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
223
+ dependencies = [
224
+ "serde_derive",
225
+ ]
226
+
227
+ [[package]]
228
+ name = "serde_derive"
229
+ version = "1.0.228"
230
+ source = "registry+https://github.com/rust-lang/crates.io-index"
231
+ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
232
+ dependencies = [
233
+ "proc-macro2",
234
+ "quote",
235
+ "syn",
236
+ ]
237
+
238
+ [[package]]
239
+ name = "serde_jcs"
240
+ version = "0.2.0"
241
+ source = "registry+https://github.com/rust-lang/crates.io-index"
242
+ checksum = "d3a60f3fda61525e439ef6d67422118f11e986566997d9021c56867ad814a0aa"
243
+ dependencies = [
244
+ "ryu-js",
245
+ "serde",
246
+ "serde_json",
247
+ ]
248
+
249
+ [[package]]
250
+ name = "serde_json"
251
+ version = "1.0.150"
252
+ source = "registry+https://github.com/rust-lang/crates.io-index"
253
+ checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
254
+ dependencies = [
255
+ "itoa",
256
+ "memchr",
257
+ "serde",
258
+ "serde_core",
259
+ "zmij",
260
+ ]
261
+
262
+ [[package]]
263
+ name = "sha2"
264
+ version = "0.10.9"
265
+ source = "registry+https://github.com/rust-lang/crates.io-index"
266
+ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
267
+ dependencies = [
268
+ "cfg-if",
269
+ "cpufeatures",
270
+ "digest",
271
+ ]
272
+
273
+ [[package]]
274
+ name = "syn"
275
+ version = "2.0.118"
276
+ source = "registry+https://github.com/rust-lang/crates.io-index"
277
+ checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
278
+ dependencies = [
279
+ "proc-macro2",
280
+ "quote",
281
+ "unicode-ident",
282
+ ]
283
+
284
+ [[package]]
285
+ name = "target-lexicon"
286
+ version = "0.13.5"
287
+ source = "registry+https://github.com/rust-lang/crates.io-index"
288
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
289
+
290
+ [[package]]
291
+ name = "thiserror"
292
+ version = "1.0.69"
293
+ source = "registry+https://github.com/rust-lang/crates.io-index"
294
+ checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
295
+ dependencies = [
296
+ "thiserror-impl",
297
+ ]
298
+
299
+ [[package]]
300
+ name = "thiserror-impl"
301
+ version = "1.0.69"
302
+ source = "registry+https://github.com/rust-lang/crates.io-index"
303
+ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
304
+ dependencies = [
305
+ "proc-macro2",
306
+ "quote",
307
+ "syn",
308
+ ]
309
+
310
+ [[package]]
311
+ name = "typenum"
312
+ version = "1.20.1"
313
+ source = "registry+https://github.com/rust-lang/crates.io-index"
314
+ checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
315
+
316
+ [[package]]
317
+ name = "unicode-ident"
318
+ version = "1.0.24"
319
+ source = "registry+https://github.com/rust-lang/crates.io-index"
320
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
321
+
322
+ [[package]]
323
+ name = "version_check"
324
+ version = "0.9.5"
325
+ source = "registry+https://github.com/rust-lang/crates.io-index"
326
+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
327
+
328
+ [[package]]
329
+ name = "zmij"
330
+ version = "1.0.21"
331
+ source = "registry+https://github.com/rust-lang/crates.io-index"
332
+ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
@@ -0,0 +1,19 @@
1
+ [package]
2
+ name = "agent-hooks-python"
3
+ version = "0.1.0-alpha.1"
4
+ edition = "2021"
5
+ license = "MIT"
6
+ description = "PyO3 bindings for the agent-hooks Rust core."
7
+ publish = false
8
+ readme = "README.md"
9
+
10
+ [lib]
11
+ name = "_core"
12
+ crate-type = ["cdylib"]
13
+
14
+ [dependencies]
15
+ agent-hooks-sdk = { path = "../rust/core" }
16
+ pyo3 = { version = "0.29", features = ["extension-module", "abi3-py310"] }
17
+
18
+ [build-dependencies]
19
+ pyo3-build-config = "0.29"
@@ -0,0 +1,49 @@
1
+ # agent-hooks (Python SDK)
2
+
3
+ Python implementation of [AGENT-HOOKS-0.1](../../spec/AGENT-HOOKS-0.1.md):
4
+ interception-point enums, `AgentContext` builder, `Verdict` types, host-side
5
+ `InterceptionEmitter`, and the Conformance Test Kit.
6
+
7
+ ```bash
8
+ # Not yet on PyPI (the name "agent-hooks" is held by an unrelated
9
+ # project; the distribution is named agent-hooks-sdk). Install from source:
10
+ pip install "agent-hooks-sdk @ git+https://github.com/responsibleai/agent-hooks#subdirectory=sdk/python"
11
+ ```
12
+
13
+ ## Host (framework adapter) usage
14
+
15
+ ```python
16
+ from agent_hooks import AgentContextBuilder, InterceptionEmitter, InterceptionBlocked
17
+
18
+ builder = AgentContextBuilder(agent_id="...", framework="my-fw", session_id="...")
19
+ emitter = InterceptionEmitter().register(my_consumer)
20
+
21
+ await emitter.emit(builder.agent_startup(tools_registered=[...]))
22
+ ctx = builder.pre_tool_call(call_id="tc-1", name="http_get", args={"url": u})
23
+ try:
24
+ await emitter.emit(ctx)
25
+ except InterceptionBlocked as e:
26
+ return tool_error(e.result.verdict.reason)
27
+ result = invoke_tool(ctx["tool_call"]["args"]) # post-transform args
28
+ ```
29
+
30
+ ## Interceptor usage
31
+
32
+ ```python
33
+ from agent_hooks import Interceptor, AgentContext, Verdict, Decision
34
+
35
+ class MyPolicy:
36
+ def intercept(self, ctx: AgentContext) -> Verdict:
37
+ if ctx["interception_point"] == "pre_tool_call" and ctx["tool_call"]["name"] == "rm":
38
+ return Verdict(Decision.DENY, reason="dangerous")
39
+ return Verdict.ALLOW
40
+ ```
41
+
42
+ ## Running the CTK against your framework
43
+
44
+ Implement `agent_hooks.ctk.Harness` (see `conformance/HARNESS.md`), then:
45
+
46
+ ```bash
47
+ pytest --agent-hooks-harness=my_pkg:MyHarness \
48
+ --agent-hooks-vectors=path/to/conformance/vectors
49
+ ```
@@ -0,0 +1,66 @@
1
+ # Copyright (c) Microsoft Corporation.
2
+ # Licensed under the MIT License.
3
+ """agent-hooks: framework-neutral agent lifecycle hook contract.
4
+
5
+ Implements AGENT-HOOKS-0.1. See ``spec/AGENT-HOOKS-0.1.md`` for the normative
6
+ text. This package provides:
7
+
8
+ - :class:`InterceptionPoint`, :class:`Decision`, :class:`EnforcementMode` — enums (§3, §5, §8)
9
+ - :class:`Verdict`, :class:`Transform`, :class:`Evidence` — interceptor return (§5)
10
+ - :class:`AgentContext` and per-hook builders — host payload (§4)
11
+ - :class:`Interceptor`, :class:`ApprovalResolver` — protocols (§7, §9)
12
+ - :class:`InterceptionEmitter` — host-side helper that builds context, dispatches to
13
+ interceptors, applies the verdict, and returns a :class:`InterceptionRecord` (§6)
14
+ - :func:`canonical_json`, :func:`context_identity` — §10
15
+ - :mod:`agent_hooks.ctk` — Conformance Test Kit (§13)
16
+ """
17
+ from __future__ import annotations
18
+
19
+ from agent_hooks._types import (
20
+ ALLOW,
21
+ SPEC_VERSION,
22
+ Decision,
23
+ EnforcementMode,
24
+ Evidence,
25
+ HostError,
26
+ InterceptionPoint,
27
+ InterceptionRecord,
28
+ Transform,
29
+ Verdict,
30
+ )
31
+ from agent_hooks.approval import (
32
+ ApprovalOutcome,
33
+ ApprovalRequest,
34
+ ApprovalResolution,
35
+ ApprovalResolver,
36
+ )
37
+ from agent_hooks.canonical import canonical_json, context_identity
38
+ from agent_hooks.context import AgentContext, AgentContextBuilder
39
+ from agent_hooks.emitter import InterceptionEmitter
40
+ from agent_hooks.exceptions import InterceptionBlocked, InterceptionSuspended
41
+ from agent_hooks.interceptor import Interceptor
42
+
43
+ __all__ = [
44
+ "ALLOW",
45
+ "SPEC_VERSION",
46
+ "AgentContext",
47
+ "AgentContextBuilder",
48
+ "ApprovalOutcome",
49
+ "ApprovalRequest",
50
+ "ApprovalResolution",
51
+ "ApprovalResolver",
52
+ "Decision",
53
+ "EnforcementMode",
54
+ "Evidence",
55
+ "HostError",
56
+ "InterceptionBlocked",
57
+ "InterceptionEmitter",
58
+ "InterceptionPoint",
59
+ "InterceptionRecord",
60
+ "InterceptionSuspended",
61
+ "Interceptor",
62
+ "Transform",
63
+ "Verdict",
64
+ "canonical_json",
65
+ "context_identity",
66
+ ]
@@ -0,0 +1,26 @@
1
+ # Type stubs for the PyO3 native module (agent_hooks._core).
2
+ # All functions take/return UTF-8 JSON strings.
3
+
4
+ SPEC_VERSION: str
5
+
6
+ class AgentHooksCoreError(ValueError):
7
+ """Raised by every _core function on failure. ``.code`` is the §11
8
+ ``host_error:*`` wire string."""
9
+ code: str
10
+
11
+ def spec_version() -> str: ...
12
+ def canonical_json(value_json: str, /) -> str: ...
13
+ def context_identity(ctx_json: str, /) -> str: ...
14
+ def validate_verdict(verdict_json: str, /) -> str: ...
15
+ def apply_transform(target_json: str, path: str, value_json: str, /) -> str: ...
16
+ def apply_transform_ctx(ctx_json: str, path: str, value_json: str, /) -> str: ...
17
+ def validate_transform_ctx(ctx_json: str, path: str, value_json: str, /) -> str: ...
18
+ def finalize(
19
+ ctx_json: str, verdict_json: str, mode: str, input_identity: str, decided_by: int, /
20
+ ) -> str: ...
21
+
22
+ # CTK engine (§13.2)
23
+ def ctk_scripted_intercept(rules_json: str, ctx_json: str, /) -> str: ...
24
+ def ctk_scripted_resolve(rules_json: str, ctx_json: str, identity: str, /) -> str: ...
25
+ def ctk_should_skip(vector_json: str, harness_caps_json: str, /) -> str: ...
26
+ def ctk_assert(vector_json: str, recorded_json: str, run_record_json: str, /) -> str: ...