forma-sdk 1.1.0__py3-none-any.whl

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.
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: forma-sdk
3
+ Version: 1.1.0
4
+ Summary: FORMA — AI agent compliance SDK. Zero-config tracking, EU AI Act/DPDP/RBI compliance, cryptographic audit trails.
5
+ Home-page: https://github.com/amit5115/forma-sdk
6
+ Author: FORMA
7
+ Author-email: sdk@forma.ai
8
+ Keywords: ai agents compliance eu-ai-act rbi dpdp audit cryptography llm openai
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: httpx>=0.24.0
24
+ Requires-Dist: pydantic>=2.0
25
+ Provides-Extra: cli
26
+ Requires-Dist: click>=8.0; extra == "cli"
27
+ Provides-Extra: openai
28
+ Requires-Dist: openai>=1.0; extra == "openai"
29
+ Provides-Extra: anthropic
30
+ Requires-Dist: anthropic>=0.20; extra == "anthropic"
31
+ Provides-Extra: litellm
32
+ Requires-Dist: litellm>=1.0; extra == "litellm"
33
+ Provides-Extra: langchain
34
+ Requires-Dist: langchain-core>=0.1; extra == "langchain"
35
+ Provides-Extra: all
36
+ Requires-Dist: click>=8.0; extra == "all"
37
+ Requires-Dist: openai>=1.0; extra == "all"
38
+ Requires-Dist: anthropic>=0.20; extra == "all"
39
+ Requires-Dist: litellm>=1.0; extra == "all"
40
+ Requires-Dist: langchain-core>=0.1; extra == "all"
41
+ Dynamic: author
42
+ Dynamic: author-email
43
+ Dynamic: classifier
44
+ Dynamic: description
45
+ Dynamic: description-content-type
46
+ Dynamic: home-page
47
+ Dynamic: keywords
48
+ Dynamic: license-file
49
+ Dynamic: provides-extra
50
+ Dynamic: requires-dist
51
+ Dynamic: requires-python
52
+ Dynamic: summary
53
+
54
+ # FORMA SDK
55
+
56
+ **Make non-compliance impossible — in one line of code.**
57
+
58
+ FORMA doesn't just record what your AI did; it **blocks non-compliant decisions before they execute**. Add `enforce=[...]` and PII leaks, prompt injections, and policy violations are stopped at runtime — then every decision is cryptographically signed and mapped to RBI, DPDP, EU AI Act, and ISO 42001.
59
+
60
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
61
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
62
+
63
+ ---
64
+
65
+ ## Install
66
+
67
+ ```bash
68
+ pip install forma-sdk
69
+ ```
70
+
71
+ Import name is `trustlayer` (the legacy alias `provn` also works):
72
+
73
+ ```python
74
+ import trustlayer as tl
75
+ ```
76
+
77
+ ## Quickstart — runtime enforcement
78
+
79
+ ```python
80
+ import trustlayer as tl
81
+
82
+ tl.init(api_key="tl_live_YOUR_KEY") # from forma.2bd.net → Settings
83
+
84
+ @tl.agent(
85
+ purpose="Loan application evaluation",
86
+ risk_level="HIGH",
87
+ enforce=["rbi_ml_risk", "dpdp"], # ← blocks violations BEFORE they run
88
+ )
89
+ def approve_loan(application: dict) -> dict:
90
+ return run_underwriting_model(application)
91
+ ```
92
+
93
+ Now, before any LLM or tool call executes:
94
+
95
+ - An Aadhaar / PAN / card number in the prompt → **blocked** (DPDP)
96
+ - "Ignore previous instructions…" / jailbreaks → **blocked**
97
+ - "Auto-approve without review" → **blocked** (RBI human-review rule)
98
+
99
+ A blocked action raises `ComplianceViolation`, and every decision (allow / warn / block) lands in your signed audit trail. The gate runs **locally in ~1 ms** — no network hop in your request path.
100
+
101
+ ```python
102
+ from trustlayer import ComplianceViolation
103
+
104
+ try:
105
+ result = approve_loan(application)
106
+ except ComplianceViolation as e:
107
+ print(e.reason) # "PII detected in LLM prompt: Aadhaar number. ..."
108
+ ```
109
+
110
+ ## Zero-config tracking (no enforcement)
111
+
112
+ ```python
113
+ import trustlayer as tl
114
+ tl.init(api_key="tl_live_YOUR_KEY")
115
+
116
+ # Every OpenAI / Anthropic / LangChain / LiteLLM call is now auto-captured —
117
+ # tokens, cost, latency, anomaly score — with no other code changes.
118
+ ```
119
+
120
+ ## Human approvals (EU AI Act Article 14 / RBI human review)
121
+
122
+ ```python
123
+ @tl.track
124
+ @tl.require_approval(
125
+ when=lambda result: result["amount"] > 1_000_000, # only high-stakes
126
+ message="Loan above ₹10L requires human review.",
127
+ )
128
+ def approve_loan(application: dict) -> dict:
129
+ return run_underwriting_model(application)
130
+ ```
131
+
132
+ The decision pauses in your FORMA Approvals inbox until a human approves or rejects. Fail-closed: a timeout or unreachable API is treated as a denial — a skipped review never silently passes.
133
+
134
+ ---
135
+
136
+ ## Policy packs
137
+
138
+ | Pack | Region | Enforces |
139
+ |------|--------|----------|
140
+ | `dpdp` | India | Aadhaar / PAN / card / phone blocked from prompts & tool args; consent-bypass blocked |
141
+ | `rbi_ml_risk` | India Banking | auto-approval-without-review blocked; fund-disbursal routed to approval |
142
+ | `eu_ai_act` | EU | human-oversight bypass (Art. 14) & logging suppression (Art. 12) blocked; PII protection |
143
+ | `iso42001` | Global | concealing AI involvement blocked |
144
+
145
+ ---
146
+
147
+ ## Manual step control
148
+
149
+ ```python
150
+ import openai
151
+ import trustlayer as tl
152
+
153
+ tracker = tl.init(api_key="tl_live_YOUR_KEY", auto_capture=False)
154
+
155
+ @tracker.track(name="my-agent")
156
+ def my_agent(task: str) -> str:
157
+ with tracker.llm_call(label="generate", model="gpt-4o", prompt=task) as step:
158
+ resp = openai.chat.completions.create(
159
+ model="gpt-4o",
160
+ messages=[{"role": "user", "content": task}],
161
+ )
162
+ step.prompt_tokens = resp.usage.prompt_tokens
163
+ step.completion_tokens = resp.usage.completion_tokens
164
+ return resp.choices[0].message.content
165
+
166
+ # For tools: with tracker.tool_call("send_email", {"to": addr}): ...
167
+ ```
168
+
169
+ ## Kill switch
170
+
171
+ Pass `kill_switch=True` to `@tl.agent(...)` (or `tl.init(kill_switch=True)`). When you trigger a kill from the dashboard, the next LLM/tool call raises `KillSwitchTriggered` in under ~100 ms.
172
+
173
+ ## CI/CD compliance gate
174
+
175
+ ```bash
176
+ # Blocks the deploy (exit 1) if any agent is below the threshold
177
+ trustlayer gate --pre-deploy --fail-below 80
178
+ ```
179
+
180
+ ---
181
+
182
+ ## `tl.init()` parameters
183
+
184
+ | Parameter | Type | Description |
185
+ |-----------|------|-------------|
186
+ | `api_key` | `str` | Your FORMA API key (`tl_live_…` / `tl_test_…`) |
187
+ | `enforce` | `list[str]` | Framework packs enforced on every call, e.g. `["dpdp"]` |
188
+ | `human_sponsor` | `str` | Accountable human (EU AI Act Art. 14 / RBI) |
189
+ | `auto_capture` | `bool` | Auto-patch OpenAI/Anthropic/LangChain/LiteLLM (default `True`) |
190
+ | `kill_switch` | `bool` | Start the process-level kill watcher (default `False`) |
191
+ | `compliance` | `list[str]` | Frameworks for scoring/reports |
192
+ | `agent_name` | `str` | Display name for ambient auto-captured runs |
193
+
194
+ ---
195
+
196
+ ## Node.js / TypeScript
197
+
198
+ ```bash
199
+ npm install forma-sdk
200
+ ```
201
+
202
+ ```ts
203
+ import * as tl from "forma-sdk";
204
+
205
+ tl.init({ apiKey: "tl_live_YOUR_KEY" });
206
+
207
+ const myAgent = tl.track(
208
+ async (task: string) => { /* your code */ return "done"; },
209
+ { name: "my-agent" },
210
+ );
211
+ ```
212
+
213
+ > **Note:** runtime enforcement (`enforce`), `agent`, and approvals are **Python-only** today. The Node SDK currently provides auto-tracking (`init` + `track`); enforcement parity is on the roadmap.
214
+
215
+ ---
216
+
217
+ ## Dashboard & docs
218
+
219
+ - Dashboard: **[forma.2bd.net](https://forma.2bd.net)**
220
+ - Developer guide: [forma.2bd.net/developer-guide](https://forma.2bd.net/developer-guide)
221
+ - Generate a tailored snippet: [forma.2bd.net/snippet-generator](https://forma.2bd.net/snippet-generator)
222
+
223
+ ## License
224
+
225
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,16 @@
1
+ forma_sdk-1.1.0.dist-info/licenses/LICENSE,sha256=XcrPEcYkGOsx3wUJ2ahxR4cwFgzWHEvwKG0UlPgZuDI,1062
2
+ provn/__init__.py,sha256=J1PKcwde7xcE2eDoqBp7BHPLJKPfEu0oustmJoQFZrw,4155
3
+ trustlayer/__init__.py,sha256=QUVWXPStW08x0vrnE1QO_drXGqnoct9Vfkj1lhzPyD8,5970
4
+ trustlayer/approval.py,sha256=IPMh3FfhC_WGOUhszmVRC3s78LDD8b9jiBzk6WeSiUE,9298
5
+ trustlayer/auto.py,sha256=AsfnVXHLRsETtFjCuZ0NVCo9_WshIN_lfAODInJJAPs,29909
6
+ trustlayer/cli.py,sha256=GlbPOKtMiYJPd7MY0N1BN7H_xlHGNir2sBeML6-X2TE,22741
7
+ trustlayer/client.py,sha256=tWO5XwvK_L0qt59C-VNh59hoT_koQNp6bCXzBIWOfE0,6376
8
+ trustlayer/crypto.py,sha256=xYDCD17tnyZvhyBZLcEpypF-cBQBEqjf5crq3CfxRKw,6132
9
+ trustlayer/gate_local.py,sha256=G0ByFTjMf7wWaob8iPjV8SgYQ6NkFEibeeB4H0jfur0,12750
10
+ trustlayer/models.py,sha256=OUzN-whnqxa85PXwxa2i605P53AYq1xJZ85zKaKWft4,3094
11
+ trustlayer/tracker.py,sha256=tUEFUeHkm0oaZ-ey2_IVNXtAWRW4fYQGToBGaSpUGVY,29514
12
+ forma_sdk-1.1.0.dist-info/METADATA,sha256=eJpItuLaFcK8zY-hfMxDuGsw0FXlZxCwk8c2OVfIDxo,7475
13
+ forma_sdk-1.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
14
+ forma_sdk-1.1.0.dist-info/entry_points.txt,sha256=kiyAd-hnyoaSUJVEe90v0IxyyHLYi894p-nSTApIHLE,74
15
+ forma_sdk-1.1.0.dist-info/top_level.txt,sha256=tbicwtwQi-C0BQKBUrqS9PRB3HLwbISk3PW7uSmV2qQ,17
16
+ forma_sdk-1.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ provn = provn.cli:main
3
+ trustlayer = trustlayer.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FORMA
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,2 @@
1
+ provn
2
+ trustlayer
provn/__init__.py ADDED
@@ -0,0 +1,132 @@
1
+ """
2
+ provn — zero-config AI agent observability and control.
3
+
4
+ Usage::
5
+
6
+ import provn
7
+ provn.init(api_key="tl_live_xxx")
8
+
9
+ # That's it. Every LLM call (OpenAI, Anthropic, LiteLLM, LangChain) is now:
10
+ # - captured as a real AgentRun (not just shadow events)
11
+ # - gate-checked before execution (compliance firewall)
12
+ # - kill-switch aware (global process-level kill watch)
13
+ # - cost + token tracked
14
+ # - drift detected server-side
15
+ # - compliance evaluated
16
+
17
+ Decorators still work identically and take precedence over ambient runs::
18
+
19
+ @provn.agent(
20
+ purpose="Customer support",
21
+ risk_level="HIGH",
22
+ kill_switch=True,
23
+ compliance=["EU_AI_ACT"],
24
+ )
25
+ def support_agent(ticket: str) -> dict: ...
26
+ """
27
+ from __future__ import annotations
28
+
29
+ import trustlayer as _tl
30
+ from trustlayer import (
31
+ AgentRun,
32
+ ApprovalRejectedError,
33
+ ApprovalTimeoutError,
34
+ ComplianceViolation,
35
+ KillSwitchTriggered,
36
+ PROVNClient,
37
+ PROVNTracker,
38
+ StepType,
39
+ TraceStep,
40
+ agent,
41
+ generate_keypair,
42
+ get_passport_header,
43
+ get_public_key_pem,
44
+ sign_run,
45
+ track,
46
+ verify_run,
47
+ )
48
+
49
+ __version__ = _tl.__version__
50
+
51
+
52
+ def init(
53
+ api_key: "str | None" = None,
54
+ api_url: "str | None" = None,
55
+ agent_name: "str | None" = None,
56
+ human_sponsor: "str | None" = None,
57
+ kill_switch: bool = False,
58
+ gate: bool = True,
59
+ compliance: "list[str] | None" = None,
60
+ auto_capture: bool = True,
61
+ ambient_runs: bool = True,
62
+ ) -> PROVNTracker:
63
+ """
64
+ Initialize PROVN with zero-config defaults.
65
+
66
+ One call gives you full AI agent observability and governance::
67
+
68
+ import provn
69
+ provn.init(api_key="tl_live_xxx")
70
+
71
+ After this, all LLM calls across OpenAI, Anthropic, LiteLLM, and LangChain
72
+ are automatically captured, gate-checked, kill-switch aware, cost-tracked,
73
+ and fed into drift detection and compliance evaluation — no decorators needed.
74
+
75
+ Args:
76
+ api_key: Your PROVN API key (or set TRUSTLAYER_API_KEY env var).
77
+ api_url: PROVN backend URL (default: http://localhost:8001).
78
+ agent_name: Display name for auto-captured ambient runs. Defaults to
79
+ the basename of sys.argv[0].
80
+ human_sponsor: Accountable human for compliance (e.g. "alice@company.com").
81
+ kill_switch: Start a global process-level kill-switch watcher. When an
82
+ operator triggers a kill for this agent, the next LLM call
83
+ raises KillSwitchTriggered before executing.
84
+ gate: Pre-check every auto-captured LLM call against the
85
+ compliance gate. Raises ComplianceViolation on a "block"
86
+ decision. Defaults to True.
87
+ compliance: Compliance frameworks to enforce, e.g.
88
+ ["EU_AI_ACT", "RBI_MRM", "DPDP"].
89
+ auto_capture: Monkey-patch all supported LLM libraries on init.
90
+ Defaults to True.
91
+ ambient_runs: Create real AgentRuns for undecorated LLM calls instead
92
+ of anonymous shadow events. Enables drift detection,
93
+ compliance evaluation, and cost reporting without any
94
+ decorators. Defaults to True.
95
+
96
+ Returns:
97
+ PROVNTracker instance. Useful if you want to use tracker.llm_call(),
98
+ tracker.tool_call(), or @tracker.agent() alongside zero-config mode.
99
+ """
100
+ tracker = _tl.init(
101
+ api_key=api_key,
102
+ api_url=api_url,
103
+ agent_name=agent_name,
104
+ human_sponsor=human_sponsor,
105
+ auto_capture=auto_capture,
106
+ kill_switch=kill_switch,
107
+ gate=gate,
108
+ compliance=compliance,
109
+ ambient_runs=ambient_runs,
110
+ )
111
+ return tracker
112
+
113
+
114
+ __all__ = [
115
+ "init",
116
+ "track",
117
+ "agent",
118
+ "get_passport_header",
119
+ "PROVNTracker",
120
+ "PROVNClient",
121
+ "AgentRun",
122
+ "TraceStep",
123
+ "StepType",
124
+ "KillSwitchTriggered",
125
+ "ComplianceViolation",
126
+ "ApprovalRejectedError",
127
+ "ApprovalTimeoutError",
128
+ "generate_keypair",
129
+ "get_public_key_pem",
130
+ "sign_run",
131
+ "verify_run",
132
+ ]
trustlayer/__init__.py ADDED
@@ -0,0 +1,180 @@
1
+ from .tracker import track, agent, PROVNTracker, KillSwitchTriggered, ComplianceViolation
2
+ from .client import PROVNClient
3
+ from .models import AgentRun, TraceStep, StepType
4
+ from .approval import ApprovalRejectedError, ApprovalTimeoutError
5
+ from .crypto import generate_keypair, get_public_key_pem, sign_run, verify_run
6
+
7
+ __version__ = "0.6.0"
8
+
9
+
10
+ def init(
11
+ api_key: "str | None" = None,
12
+ api_url: "str | None" = None,
13
+ agent_name: "str | None" = None,
14
+ human_sponsor: "str | None" = None,
15
+ auto_capture: bool = True,
16
+ kill_switch: bool = False,
17
+ gate: bool = True,
18
+ compliance: "list[str] | None" = None,
19
+ ambient_runs: bool = True,
20
+ enforce: "list[str] | None" = None,
21
+ ) -> PROVNTracker:
22
+ """
23
+ Initialize FORMA with zero-config defaults.
24
+
25
+ Sets the module-level default tracker used by @track and @agent.
26
+ Call this once at the top of your application.
27
+
28
+ import trustlayer as tl
29
+
30
+ tl.init(api_key="tl_live_...", enforce=["dpdp"])
31
+
32
+ # Every LLM call is now ENFORCED: PII, prompt injection, and policy
33
+ # violations are blocked BEFORE the call executes — and every
34
+ # decision lands in the FORMA audit trail. No decorators needed.
35
+
36
+ # Or with full per-agent governance:
37
+ @tl.agent(
38
+ purpose="Loan application evaluation",
39
+ risk_level="HIGH",
40
+ kill_switch=True,
41
+ enforce=["rbi_ml_risk", "dpdp"],
42
+ )
43
+ def approve_loan(application: dict): ...
44
+
45
+ Args:
46
+ api_key: FORMA API key (or FORMA_API_KEY env var).
47
+ api_url: FORMA backend URL.
48
+ agent_name: Display name for ambient auto-captured runs.
49
+ human_sponsor: Accountable human for compliance records.
50
+ auto_capture: Monkey-patch OpenAI/Anthropic/LiteLLM/LangChain. Default True.
51
+ kill_switch: Start a global process-level kill-switch watcher.
52
+ gate: Pre-check every auto-captured LLM call via compliance gate.
53
+ compliance: Compliance frameworks, e.g. ["EU_AI_ACT", "RBI_MRM"].
54
+ ambient_runs: Create real AgentRuns for undecorated LLM calls. Default True.
55
+ enforce: Framework policy packs enforced locally on every call
56
+ (e.g. ["dpdp", "rbi_ml_risk", "eu_ai_act"]). Violations
57
+ raise ComplianceViolation before the call executes.
58
+
59
+ Returns the tracker instance if you need tracker.llm_call() etc.
60
+ """
61
+ import trustlayer.tracker as _mod
62
+
63
+ tracker = PROVNTracker(
64
+ api_key=api_key,
65
+ api_url=api_url,
66
+ agent_name=agent_name,
67
+ human_sponsor=human_sponsor,
68
+ auto_capture=auto_capture,
69
+ )
70
+ _mod._default_tracker = tracker
71
+
72
+ tracker._configure_ambient(
73
+ agent_name=agent_name,
74
+ compliance=compliance,
75
+ gate=gate,
76
+ ambient_runs=ambient_runs,
77
+ )
78
+
79
+ if enforce:
80
+ try:
81
+ from .gate_local import get_shared_cache
82
+ cache = get_shared_cache(tracker._client)
83
+ if cache:
84
+ import trustlayer.auto as _auto
85
+ cache.register(_auto._ambient_config["agent_name"], list(enforce))
86
+ except Exception:
87
+ pass # never fail init due to enforcement setup
88
+
89
+ if kill_switch:
90
+ try:
91
+ tracker._start_global_kill_watch(agent_name=agent_name)
92
+ except Exception:
93
+ pass # never fail init due to kill-switch setup
94
+
95
+ return tracker
96
+
97
+
98
+ def require_approval(
99
+ via: str = "forma",
100
+ url: "str | None" = None,
101
+ timeout: int = 3600,
102
+ poll_interval: int = 5,
103
+ message: "str | None" = None,
104
+ when=None,
105
+ title: "str | None" = None,
106
+ ):
107
+ """
108
+ Module-level @require_approval — pause the agent until a human decides
109
+ in the FORMA Approvals inbox (dashboard → Approvals).
110
+
111
+ @tl.track
112
+ @tl.require_approval(
113
+ when=lambda result: result["amount"] > 1_000_000,
114
+ message="Loan above ₹10L requires human review (RBI).",
115
+ )
116
+ def approve_loan(application): ...
117
+ """
118
+ import trustlayer.tracker as _mod
119
+ return _mod._get_default_tracker().require_approval(
120
+ via=via, url=url, timeout=timeout, poll_interval=poll_interval,
121
+ message=message, when=when, title=title,
122
+ )
123
+
124
+
125
+ def get_passport_header(agent_name: "str | None" = None) -> dict:
126
+ """
127
+ Returns the X-PROVN-Passport HTTP header for inter-agent trust.
128
+
129
+ Use this when your agent calls another company's API that supports
130
+ the PROVN Inter-Agent Trust Protocol.
131
+
132
+ Example:
133
+ headers = tl.get_passport_header(agent_name="loan-approval-agent")
134
+ response = requests.post("https://api.partner.com/process",
135
+ headers=headers, json=payload)
136
+
137
+ The receiving API can verify your agent at:
138
+ GET /agent-trust/verify/{passport_id}
139
+ """
140
+ import trustlayer.tracker as _mod
141
+ tracker = _mod._get_default_tracker()
142
+ try:
143
+ import urllib.request, json as _json
144
+ url = f"{tracker.api_url.rstrip('/')}/agent-trust/my-passport"
145
+ req = urllib.request.Request(
146
+ url,
147
+ headers={"X-API-Key": tracker.api_key},
148
+ )
149
+ with urllib.request.urlopen(req, timeout=5) as resp:
150
+ data = _json.loads(resp.read())
151
+ agents = data.get("agents", [])
152
+ if agent_name:
153
+ agents = [a for a in agents if a.get("agent_name") == agent_name]
154
+ if agents:
155
+ return {"X-PROVN-Passport": agents[0]["passport_id"]}
156
+ except Exception:
157
+ pass
158
+ return {}
159
+
160
+
161
+ __all__ = [
162
+ "track",
163
+ "agent",
164
+ "init",
165
+ "require_approval",
166
+ "get_passport_header",
167
+ "PROVNTracker",
168
+ "PROVNClient",
169
+ "AgentRun",
170
+ "TraceStep",
171
+ "StepType",
172
+ "KillSwitchTriggered",
173
+ "ComplianceViolation",
174
+ "ApprovalRejectedError",
175
+ "ApprovalTimeoutError",
176
+ "generate_keypair",
177
+ "get_public_key_pem",
178
+ "sign_run",
179
+ "verify_run",
180
+ ]