safety-protocol 0.3.0__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 (41) hide show
  1. safety_protocol-0.3.0/LICENSE +21 -0
  2. safety_protocol-0.3.0/MANIFEST.in +23 -0
  3. safety_protocol-0.3.0/PKG-INFO +217 -0
  4. safety_protocol-0.3.0/README.md +179 -0
  5. safety_protocol-0.3.0/examples/agent_client.py +70 -0
  6. safety_protocol-0.3.0/examples/agent_insurance_sim.py +886 -0
  7. safety_protocol-0.3.0/examples/claims_demo_verified.py +180 -0
  8. safety_protocol-0.3.0/examples/cli.py +20 -0
  9. safety_protocol-0.3.0/examples/generate_testnet_wallets.py +88 -0
  10. safety_protocol-0.3.0/examples/guard_config.json +59 -0
  11. safety_protocol-0.3.0/examples/live_settlement_test.py +237 -0
  12. safety_protocol-0.3.0/examples/llm_agent.py +492 -0
  13. safety_protocol-0.3.0/examples/llm_agent_real.py +308 -0
  14. safety_protocol-0.3.0/examples/mock_merchant.py +128 -0
  15. safety_protocol-0.3.0/examples/reference_deployment.py +394 -0
  16. safety_protocol-0.3.0/examples/safe_spend_demo.py +141 -0
  17. safety_protocol-0.3.0/examples/salesforce/guard_config.salesforce.json +61 -0
  18. safety_protocol-0.3.0/examples/scope_lint_demo.py +94 -0
  19. safety_protocol-0.3.0/examples/scope_test.py +213 -0
  20. safety_protocol-0.3.0/examples/settlement_demo.py +125 -0
  21. safety_protocol-0.3.0/pyproject.toml +85 -0
  22. safety_protocol-0.3.0/setup.cfg +4 -0
  23. safety_protocol-0.3.0/src/safety_protocol/__init__.py +201 -0
  24. safety_protocol-0.3.0/src/safety_protocol/cli.py +132 -0
  25. safety_protocol-0.3.0/src/safety_protocol/core.py +424 -0
  26. safety_protocol-0.3.0/src/safety_protocol/data/guard_config.json +59 -0
  27. safety_protocol-0.3.0/src/safety_protocol/deployment.py +384 -0
  28. safety_protocol-0.3.0/src/safety_protocol/guard_service.py +241 -0
  29. safety_protocol-0.3.0/src/safety_protocol/insurance.py +221 -0
  30. safety_protocol-0.3.0/src/safety_protocol/onchain.py +271 -0
  31. safety_protocol-0.3.0/src/safety_protocol/onchain_audit.py +346 -0
  32. safety_protocol-0.3.0/src/safety_protocol/onchain_payment_verifier.py +174 -0
  33. safety_protocol-0.3.0/src/safety_protocol/payments.py +380 -0
  34. safety_protocol-0.3.0/src/safety_protocol/protocol.py +547 -0
  35. safety_protocol-0.3.0/src/safety_protocol/real_wallet.py +189 -0
  36. safety_protocol-0.3.0/src/safety_protocol/scope_linter.py +191 -0
  37. safety_protocol-0.3.0/src/safety_protocol.egg-info/SOURCES.txt +38 -0
  38. safety_protocol-0.3.0/tests/test_cli.py +74 -0
  39. safety_protocol-0.3.0/tests/test_insurance.py +37 -0
  40. safety_protocol-0.3.0/tests/test_packaging.py +36 -0
  41. safety_protocol-0.3.0/tests/test_sovereign_agent.py +31 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Michael / TheDub-lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,23 @@
1
+ include LICENSE
2
+ include README.md
3
+ include pyproject.toml
4
+
5
+ # Packaged default config (also shipped as wheel package-data)
6
+ recursive-include src/safety_protocol/data *.json
7
+
8
+ # Worked examples (developer-facing), not marketing assets
9
+ recursive-include examples *.py *.json
10
+
11
+ # Keep the source distribution lean: no marketing/promo assets, no root demo,
12
+ # no local state or build cruft.
13
+ exclude carrier_deck.html
14
+ exclude examples/loss_curve.png
15
+ exclude examples/loss_curve.svg
16
+ exclude sovereign_agent.py
17
+ exclude agent_capabilities.py
18
+ exclude agent_memory.json
19
+ exclude testnet_wallets.json
20
+ prune src/safety_protocol/__pycache__
21
+ prune src/safety_protocol.egg-info
22
+ global-exclude __pycache__
23
+ global-exclude *.py[cod]
@@ -0,0 +1,217 @@
1
+ Metadata-Version: 2.4
2
+ Name: safety-protocol
3
+ Version: 0.3.0
4
+ Summary: Safety protocol framework for LLM agents — binding, scope, enforcement, monitoring, approval, audit, killswitch
5
+ Author-email: Michael <michael@example.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/TheDub-lab/agentcover-sovereign
8
+ Project-URL: Repository, https://github.com/TheDub-lab/agentcover-sovereign
9
+ Project-URL: Issues, https://github.com/TheDub-lab/agentcover-sovereign/issues
10
+ Keywords: ai-agents,agent-safety,agent-governance,authorization,llm,guardrails,scope,audit,killswitch
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Provides-Extra: onchain
24
+ Requires-Dist: requests>=2.31; extra == "onchain"
25
+ Provides-Extra: crypto
26
+ Requires-Dist: eth-account>=0.11; extra == "crypto"
27
+ Provides-Extra: demo
28
+ Requires-Dist: openai>=1.30; extra == "demo"
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0; extra == "dev"
31
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
32
+ Requires-Dist: build>=1.2; extra == "dev"
33
+ Requires-Dist: twine>=5.0; extra == "dev"
34
+ Provides-Extra: all
35
+ Requires-Dist: requests>=2.31; extra == "all"
36
+ Requires-Dist: eth-account>=0.11; extra == "all"
37
+ Dynamic: license-file
38
+
39
+ # safety-protocol
40
+
41
+ [![CI](https://github.com/TheDub-lab/agentcover-sovereign/actions/workflows/ci.yml/badge.svg)](https://github.com/TheDub-lab/agentcover-sovereign/actions/workflows/ci.yml)
42
+ [![PyPI](https://img.shields.io/pypi/v/safety-protocol.svg)](https://pypi.org/project/safety-protocol/)
43
+ [![Python](https://img.shields.io/pypi/pyversions/safety-protocol.svg)](https://pypi.org/project/safety-protocol/)
44
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
45
+
46
+ Enforceable governance for LLM agents. Instead of hoping the model behaves,
47
+ every action passes through infrastructure that enforces **binding, closed
48
+ vocabulary, least-privilege scope, spend caps, approval gates, a hash-chained
49
+ audit trail, and a kill switch**. Deny-by-default: an action is permitted only
50
+ if a rule explicitly allows it.
51
+
52
+ The agent proposes; the protocol decides. The agent cannot talk its way around
53
+ it, because the check is not a prompt instruction.
54
+
55
+ ## Install
56
+
57
+ ```bash
58
+ pip install safety-protocol
59
+ ```
60
+
61
+ Zero runtime dependencies — the guard, scope linter, audit trail and reference
62
+ deployment are stdlib. Optional integrations are extras:
63
+
64
+ | Extra | Adds |
65
+ | --------- | ----------------------------------------------------------- |
66
+ | `onchain` | `requests` — verify a settled payment against a JSON-RPC node |
67
+ | `crypto` | `eth-account` — real EIP-3009 / USDC settlement signing |
68
+ | `demo` | `openai` — the repo-root Nebius/Nemotron demo agent |
69
+
70
+ ```bash
71
+ pip install "safety-protocol[onchain,crypto]"
72
+ ```
73
+
74
+ ## Quickstart (library)
75
+
76
+ ```python
77
+ from safety_protocol import SafetyProtocol, BoundAgent, ScopeRule
78
+
79
+ protocol = SafetyProtocol(
80
+ agent_id="agent-001",
81
+ user_id="alice",
82
+ scope_rules=[
83
+ ScopeRule(
84
+ action_type="api_call",
85
+ allowed_targets=["https://api.example.com/v1/search"],
86
+ match="exact",
87
+ methods=["POST"],
88
+ param_schema={
89
+ "required": ["query"],
90
+ "properties": {"query": {"type": "string", "maximum": 200}},
91
+ "additional_properties": False,
92
+ },
93
+ forbidden_targets=["admin", "billing"],
94
+ max_cost=1.00,
95
+ ),
96
+ ],
97
+ budget_limit=50.0,
98
+ approval_threshold_cost=10.0,
99
+ allowed_action_types=["api_call"],
100
+ )
101
+
102
+ agent = BoundAgent(agent_id="agent-001", user_id="alice", safety_protocol=protocol)
103
+
104
+ result = agent.propose_action(
105
+ action_type="api_call",
106
+ target="https://api.example.com/v1/search",
107
+ params={"query": "test"},
108
+ estimated_cost=2.50,
109
+ )
110
+ print(result.outcome) # ActionOutcome.ALLOWED
111
+ ```
112
+
113
+ ## The guard (CLI + HTTP)
114
+
115
+ Give the guard a **user-controlled** config; it lints the rules before going
116
+ live and **fails closed** — a config that is too broad refuses to start. The
117
+ agent only ever sends intents; it can never widen its own scope.
118
+
119
+ ```bash
120
+ safety-guard init --out guard_config.json # write a default config
121
+ safety-guard lint --config guard_config.json # exit 1 if too broad
122
+ safety-guard check --config guard_config.json \
123
+ --action api_call --target https://api.research.example/v1/search \
124
+ --method POST --params '{"query":"hi"}'
125
+ safety-guard pay --config guard_config.json \
126
+ --recipient 0xMerchant1111111111111111111111111111111 --usd 0.10
127
+ safety-guard serve --config guard_config.json # HTTP on 127.0.0.1:8080
128
+ ```
129
+
130
+ The HTTP surface (any agent, any language):
131
+
132
+ | Method | Path | Body |
133
+ | ------ | -------------- | ----------------------------------------------- |
134
+ | POST | `/guard` | `{action_type, target, method?, params?, cost?}` |
135
+ | POST | `/pay` | `{recipient, usd, resource?}` |
136
+ | POST | `/approve` | `{token, approved, approver}` |
137
+ | POST | `/killswitch` | `{reason}` |
138
+ | GET | `/audit` | — (immutable decision log) |
139
+ | GET | `/health` | — (status + lint summary) |
140
+
141
+ Equivalent module entry point: `python -m safety_protocol.guard_service --config guard_config.json`.
142
+
143
+ ## Config reference
144
+
145
+ ```jsonc
146
+ {
147
+ "agent_id": "guard-agent",
148
+ "user_id": "alice",
149
+ "budget_limit": 20.0, // global session cap (null = none)
150
+ "approval_threshold_cost": 2.0, // actions >= this need human sign-off
151
+ "allowed_action_types": ["api_call", "payment"], // closed verb vocabulary
152
+ "scope_rules": [
153
+ {
154
+ "action_type": "api_call",
155
+ "allowed_targets": ["https://api.research.example/v1/search"], // allowlist
156
+ "match": "exact", // exact | prefix | glob | regex
157
+ "methods": ["POST"], // transport verbs permitted
158
+ "param_schema": { // params MUST satisfy this
159
+ "required": ["query"],
160
+ "properties": {"query": {"type": "string", "maximum": 200}},
161
+ "additional_properties": false
162
+ },
163
+ "forbidden_targets": ["admin", "billing"],
164
+ "forbid_match": "token", // token | substring
165
+ "max_cost": 1.00, // per-rule cap (tightest wins)
166
+ "requires_approval": false
167
+ }
168
+ ]
169
+ }
170
+ ```
171
+
172
+ Every dimension is enforced. Leaving any of them broad (a wildcard prefix, an
173
+ unbound method, an unvalidated param) is what makes the other controls
174
+ decorative — the `safety-guard lint` command exists to catch exactly that
175
+ before deploy.
176
+
177
+ ## Architecture
178
+
179
+ | Layer | What it is | Status |
180
+ | ----- | ---------- | ------ |
181
+ | **1. Enforcement** | binding, scope, budget, approval, monitor, audit, killswitch | production-usable |
182
+ | **2. On-chain anchors** | SBT-style binding + on-chain audit of key events | **simulated** (in-memory, same interface as a real chain) |
183
+ | **3. Insurance** | claims evidence, underwriter reports | interface / reference |
184
+
185
+ > **The on-chain layer is simulated.** It is not third-party verifiable until a
186
+ > real contract is deployed. The library discloses this in every binding proof
187
+ > (`on_chain_backend: "simulated_in_memory"`). Use ERC-5192 SBT or ERC-8004 on a
188
+ > real chain in production.
189
+
190
+ `ReferenceDeployment` wires all three layers together; the layers are
191
+ composable and each adds value on its own.
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ pip install -e ".[dev]"
197
+ python -m pytest
198
+ ruff check
199
+ ```
200
+
201
+ The repo-root files (`sovereign_agent.py`, `agent_capabilities.py`) are a
202
+ standalone demo agent and are **not** part of the package:
203
+
204
+ ```bash
205
+ pip install -e ".[demo]"
206
+ python sovereign_agent.py --offline # no API key needed; same gate logic
207
+ python sovereign_agent.py # live via NEBIUS_API_KEY
208
+ ```
209
+
210
+ ## Origin
211
+
212
+ Originally built for the Nebius x NVIDIA Global AI Hackathon (Track: Personal
213
+ AI), then hardened into a general enforcement library.
214
+
215
+ ## License
216
+
217
+ MIT. See [`LICENSE`](LICENSE).
@@ -0,0 +1,179 @@
1
+ # safety-protocol
2
+
3
+ [![CI](https://github.com/TheDub-lab/agentcover-sovereign/actions/workflows/ci.yml/badge.svg)](https://github.com/TheDub-lab/agentcover-sovereign/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/safety-protocol.svg)](https://pypi.org/project/safety-protocol/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/safety-protocol.svg)](https://pypi.org/project/safety-protocol/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
+
8
+ Enforceable governance for LLM agents. Instead of hoping the model behaves,
9
+ every action passes through infrastructure that enforces **binding, closed
10
+ vocabulary, least-privilege scope, spend caps, approval gates, a hash-chained
11
+ audit trail, and a kill switch**. Deny-by-default: an action is permitted only
12
+ if a rule explicitly allows it.
13
+
14
+ The agent proposes; the protocol decides. The agent cannot talk its way around
15
+ it, because the check is not a prompt instruction.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ pip install safety-protocol
21
+ ```
22
+
23
+ Zero runtime dependencies — the guard, scope linter, audit trail and reference
24
+ deployment are stdlib. Optional integrations are extras:
25
+
26
+ | Extra | Adds |
27
+ | --------- | ----------------------------------------------------------- |
28
+ | `onchain` | `requests` — verify a settled payment against a JSON-RPC node |
29
+ | `crypto` | `eth-account` — real EIP-3009 / USDC settlement signing |
30
+ | `demo` | `openai` — the repo-root Nebius/Nemotron demo agent |
31
+
32
+ ```bash
33
+ pip install "safety-protocol[onchain,crypto]"
34
+ ```
35
+
36
+ ## Quickstart (library)
37
+
38
+ ```python
39
+ from safety_protocol import SafetyProtocol, BoundAgent, ScopeRule
40
+
41
+ protocol = SafetyProtocol(
42
+ agent_id="agent-001",
43
+ user_id="alice",
44
+ scope_rules=[
45
+ ScopeRule(
46
+ action_type="api_call",
47
+ allowed_targets=["https://api.example.com/v1/search"],
48
+ match="exact",
49
+ methods=["POST"],
50
+ param_schema={
51
+ "required": ["query"],
52
+ "properties": {"query": {"type": "string", "maximum": 200}},
53
+ "additional_properties": False,
54
+ },
55
+ forbidden_targets=["admin", "billing"],
56
+ max_cost=1.00,
57
+ ),
58
+ ],
59
+ budget_limit=50.0,
60
+ approval_threshold_cost=10.0,
61
+ allowed_action_types=["api_call"],
62
+ )
63
+
64
+ agent = BoundAgent(agent_id="agent-001", user_id="alice", safety_protocol=protocol)
65
+
66
+ result = agent.propose_action(
67
+ action_type="api_call",
68
+ target="https://api.example.com/v1/search",
69
+ params={"query": "test"},
70
+ estimated_cost=2.50,
71
+ )
72
+ print(result.outcome) # ActionOutcome.ALLOWED
73
+ ```
74
+
75
+ ## The guard (CLI + HTTP)
76
+
77
+ Give the guard a **user-controlled** config; it lints the rules before going
78
+ live and **fails closed** — a config that is too broad refuses to start. The
79
+ agent only ever sends intents; it can never widen its own scope.
80
+
81
+ ```bash
82
+ safety-guard init --out guard_config.json # write a default config
83
+ safety-guard lint --config guard_config.json # exit 1 if too broad
84
+ safety-guard check --config guard_config.json \
85
+ --action api_call --target https://api.research.example/v1/search \
86
+ --method POST --params '{"query":"hi"}'
87
+ safety-guard pay --config guard_config.json \
88
+ --recipient 0xMerchant1111111111111111111111111111111 --usd 0.10
89
+ safety-guard serve --config guard_config.json # HTTP on 127.0.0.1:8080
90
+ ```
91
+
92
+ The HTTP surface (any agent, any language):
93
+
94
+ | Method | Path | Body |
95
+ | ------ | -------------- | ----------------------------------------------- |
96
+ | POST | `/guard` | `{action_type, target, method?, params?, cost?}` |
97
+ | POST | `/pay` | `{recipient, usd, resource?}` |
98
+ | POST | `/approve` | `{token, approved, approver}` |
99
+ | POST | `/killswitch` | `{reason}` |
100
+ | GET | `/audit` | — (immutable decision log) |
101
+ | GET | `/health` | — (status + lint summary) |
102
+
103
+ Equivalent module entry point: `python -m safety_protocol.guard_service --config guard_config.json`.
104
+
105
+ ## Config reference
106
+
107
+ ```jsonc
108
+ {
109
+ "agent_id": "guard-agent",
110
+ "user_id": "alice",
111
+ "budget_limit": 20.0, // global session cap (null = none)
112
+ "approval_threshold_cost": 2.0, // actions >= this need human sign-off
113
+ "allowed_action_types": ["api_call", "payment"], // closed verb vocabulary
114
+ "scope_rules": [
115
+ {
116
+ "action_type": "api_call",
117
+ "allowed_targets": ["https://api.research.example/v1/search"], // allowlist
118
+ "match": "exact", // exact | prefix | glob | regex
119
+ "methods": ["POST"], // transport verbs permitted
120
+ "param_schema": { // params MUST satisfy this
121
+ "required": ["query"],
122
+ "properties": {"query": {"type": "string", "maximum": 200}},
123
+ "additional_properties": false
124
+ },
125
+ "forbidden_targets": ["admin", "billing"],
126
+ "forbid_match": "token", // token | substring
127
+ "max_cost": 1.00, // per-rule cap (tightest wins)
128
+ "requires_approval": false
129
+ }
130
+ ]
131
+ }
132
+ ```
133
+
134
+ Every dimension is enforced. Leaving any of them broad (a wildcard prefix, an
135
+ unbound method, an unvalidated param) is what makes the other controls
136
+ decorative — the `safety-guard lint` command exists to catch exactly that
137
+ before deploy.
138
+
139
+ ## Architecture
140
+
141
+ | Layer | What it is | Status |
142
+ | ----- | ---------- | ------ |
143
+ | **1. Enforcement** | binding, scope, budget, approval, monitor, audit, killswitch | production-usable |
144
+ | **2. On-chain anchors** | SBT-style binding + on-chain audit of key events | **simulated** (in-memory, same interface as a real chain) |
145
+ | **3. Insurance** | claims evidence, underwriter reports | interface / reference |
146
+
147
+ > **The on-chain layer is simulated.** It is not third-party verifiable until a
148
+ > real contract is deployed. The library discloses this in every binding proof
149
+ > (`on_chain_backend: "simulated_in_memory"`). Use ERC-5192 SBT or ERC-8004 on a
150
+ > real chain in production.
151
+
152
+ `ReferenceDeployment` wires all three layers together; the layers are
153
+ composable and each adds value on its own.
154
+
155
+ ## Development
156
+
157
+ ```bash
158
+ pip install -e ".[dev]"
159
+ python -m pytest
160
+ ruff check
161
+ ```
162
+
163
+ The repo-root files (`sovereign_agent.py`, `agent_capabilities.py`) are a
164
+ standalone demo agent and are **not** part of the package:
165
+
166
+ ```bash
167
+ pip install -e ".[demo]"
168
+ python sovereign_agent.py --offline # no API key needed; same gate logic
169
+ python sovereign_agent.py # live via NEBIUS_API_KEY
170
+ ```
171
+
172
+ ## Origin
173
+
174
+ Originally built for the Nebius x NVIDIA Global AI Hackathon (Track: Personal
175
+ AI), then hardened into a general enforcement library.
176
+
177
+ ## License
178
+
179
+ MIT. See [`LICENSE`](LICENSE).
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ agent_client.py — a 'real' agent that calls the HTTP guard.
4
+
5
+ This is what an actual agent integration looks like: the agent forms an
6
+ intent, POSTs it to the guard, and only acts on an allow. It never sees
7
+ or edits the rules. Language-agnostic — any agent in any language hits
8
+ the same HTTP endpoints.
9
+
10
+ Prereq: python examples/cli.py serve --config examples/guard_config.json
11
+ Then: python examples/agent_client.py
12
+ """
13
+ import sys, os, json, urllib.request
14
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
15
+
16
+ BASE = "http://127.0.0.1:8080"
17
+ MERCHANT = "0xMerchant1111111111111111111111111111111111"
18
+
19
+
20
+ def _post(path, payload):
21
+ req = urllib.request.Request(
22
+ BASE + path, data=json.dumps(payload).encode(),
23
+ headers={"Content-Type": "application/json"}, method="POST")
24
+ with urllib.request.urlopen(req, timeout=10) as r:
25
+ return json.loads(r.read().decode())
26
+
27
+
28
+ def ask_guard(action_type, target, method=None, params=None, cost=0.0):
29
+ return _post("/guard", {
30
+ "action_type": action_type, "target": target,
31
+ "method": method, "params": params or {}, "cost": cost,
32
+ })
33
+
34
+
35
+ def main():
36
+ # The agent's plan. It proposes; the guard disposes.
37
+ intents = [
38
+ ("api_call", "https://api.research.example/v1/search",
39
+ "POST", {"query": "agent safety"}, 0.50),
40
+ ("api_call", "https://api.research.example/v1/admin/config",
41
+ "POST", {"query": "x"}, 0.50), # forbidden token -> block
42
+ ("payment", MERCHANT, "x402", {"resource": "weather"}, 0.10),
43
+ ("payment", "0xEvil9999999999999999999999999999999999",
44
+ "x402", {"resource": "weather"}, 0.10), # forbidden recipient
45
+ ]
46
+
47
+ print("AGENT running through the guard (guard decides, agent obeys)\n")
48
+ for action_type, target, method, params, cost in intents:
49
+ d = ask_guard(action_type, target, method, params, cost)
50
+ decision = "ALLOWED" if d["allowed"] else "BLOCKED"
51
+ print(f" intent: {action_type} {method or ''} {target}")
52
+ print(f" guard -> {decision}"
53
+ + (f" ({d['block_reason']})" if d["block_reason"] else ""))
54
+ # The agent ONLY proceeds on allow. On block/approval it stops.
55
+ if d["allowed"]:
56
+ print(f" agent: proceeding with {action_type}")
57
+ else:
58
+ print(f" agent: NOT executing (guard denied)")
59
+ print()
60
+
61
+ # Show the audit trail the guard kept
62
+ print("GUARD AUDIT (every decision, immutable):")
63
+ with urllib.request.urlopen(BASE + "/audit", timeout=10) as r:
64
+ events = json.loads(r.read().decode()).get("events", [])
65
+ for e in events[-6:]:
66
+ print(f" [{e['event_type']}] {e.get('data', {}).get('target', '')}")
67
+
68
+
69
+ if __name__ == "__main__":
70
+ main()