blocklog 0.2.5__tar.gz → 0.2.6__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.
- {blocklog-0.2.5 → blocklog-0.2.6}/LICENSE +1 -1
- blocklog-0.2.6/PKG-INFO +332 -0
- blocklog-0.2.6/README.md +278 -0
- blocklog-0.2.6/docs/architecture.md +21 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/async.md +6 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/configuration.md +1 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/decisions.md +3 -12
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/installation.md +2 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/integrations.md +1 -0
- blocklog-0.2.6/docs/low-effort-sdk.md +11 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/migration.md +7 -3
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/production.md +5 -3
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/quickstart.md +5 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/01_quickstart.py +7 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/02_stock_trading_agent.py +16 -8
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/03_multi_agent_workflow.py +27 -10
- blocklog-0.2.6/examples/05_phase1_features.py +368 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/advanced/01_human_approval_workflow.py +14 -7
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/advanced/02_incident_investigation.py +33 -10
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/advanced/03_decision_comparison.py +16 -10
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/advanced/langchain_alert_demo.py +14 -3
- {blocklog-0.2.5 → blocklog-0.2.6}/pyproject.toml +8 -4
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/__init__.py +15 -7
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/_global.py +4 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/_init_fn.py +26 -48
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/approval.py +19 -8
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/auth.py +20 -8
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/compliance.py +40 -45
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/decisions.py +16 -12
- blocklog-0.2.6/src/blocklog/api/execution_gateway.py +541 -0
- blocklog-0.2.6/src/blocklog/api/executions.py +213 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/incidents.py +53 -24
- blocklog-0.2.6/src/blocklog/api/receipt_verification.py +141 -0
- blocklog-0.2.6/src/blocklog/api/receipt_verifier.py +318 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/replay.py +38 -15
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/teams.py +37 -15
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/traces.py +5 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/api/verify.py +5 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/approval.py +12 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/async_client.py +3 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/client.py +76 -28
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/compliance.py +30 -19
- blocklog-0.2.6/src/blocklog/config.py +42 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/context/managers.py +4 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/context/vars.py +3 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/decorators/agent.py +96 -42
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/decorators/tool.py +56 -35
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/exceptions.py +0 -3
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/incident.py +7 -3
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/integrations/langchain.py +52 -10
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/integrations/langgraph.py +4 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/integrations/litellm.py +15 -10
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/integrations/openai_agents.py +120 -36
- blocklog-0.2.6/src/blocklog/managers/__init__.py +3 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/managers/decision.py +96 -54
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/middleware/hooks.py +0 -1
- blocklog-0.2.6/src/blocklog/models/execution.py +46 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/models/responses.py +1 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/replay.py +6 -2
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/signing/ed25519.py +1 -1
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/transport/httpx_async.py +13 -4
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/transport/httpx_sync.py +13 -4
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/transport/retry.py +4 -4
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/verify.py +4 -0
- blocklog-0.2.6/src/blocklog.egg-info/PKG-INFO +332 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog.egg-info/SOURCES.txt +8 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_client.py +36 -49
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_config.py +31 -28
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_decorators.py +31 -19
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_errors_and_health.py +66 -53
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_public_api.py +32 -42
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_transport.py +32 -33
- blocklog-0.2.5/PKG-INFO +0 -356
- blocklog-0.2.5/README.md +0 -302
- blocklog-0.2.5/src/blocklog/config.py +0 -19
- blocklog-0.2.5/src/blocklog/managers/__init__.py +0 -3
- blocklog-0.2.5/src/blocklog.egg-info/PKG-INFO +0 -356
- {blocklog-0.2.5 → blocklog-0.2.6}/MANIFEST.in +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/api-reference.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/changelog.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/concepts.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/decorators.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/error-handling.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/examples.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/index.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/performance.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/tracing.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/docs/troubleshooting.md +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/examples/04_team_management.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/setup.cfg +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/batching/buffer.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/decorators/__init__.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/models/auth.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/models/events.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/models/teams.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/signing/canonical.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/team_utils.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog/transport/auth.py +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog.egg-info/dependency_links.txt +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog.egg-info/requires.txt +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/src/blocklog.egg-info/top_level.txt +0 -0
- {blocklog-0.2.5 → blocklog-0.2.6}/tests/test_context.py +0 -0
blocklog-0.2.6/PKG-INFO
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: blocklog
|
|
3
|
+
Version: 0.2.6
|
|
4
|
+
Summary: Infrastructure for AI Decision-Making — record, replay, verify, and govern AI agent decisions
|
|
5
|
+
Author-email: Blocklog <founder@blocklogsecurity.com>
|
|
6
|
+
Maintainer-email: Blocklog <founder@blocklogsecurity.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://blocklogsecurity.com
|
|
9
|
+
Project-URL: Documentation, https://blocklogsecurity.com/docs
|
|
10
|
+
Project-URL: Repository, https://github.com/blockloglabs/blocklog-python
|
|
11
|
+
Project-URL: Issues, https://github.com/blockloglabs/blocklog-python/issues
|
|
12
|
+
Keywords: ai,agents,observability,governance,security,audit,replay
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Topic :: System :: Monitoring
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: httpx<1.0,>=0.27
|
|
27
|
+
Requires-Dist: pydantic<3.0,>=2.8
|
|
28
|
+
Provides-Extra: requests
|
|
29
|
+
Requires-Dist: requests>=2.32.0; extra == "requests"
|
|
30
|
+
Provides-Extra: langchain
|
|
31
|
+
Requires-Dist: langchain-core>=0.2.0; extra == "langchain"
|
|
32
|
+
Provides-Extra: langgraph
|
|
33
|
+
Requires-Dist: langchain-core>=0.2.0; extra == "langgraph"
|
|
34
|
+
Requires-Dist: langgraph>=0.2.0; extra == "langgraph"
|
|
35
|
+
Provides-Extra: openai
|
|
36
|
+
Requires-Dist: openai>=1.0.0; extra == "openai"
|
|
37
|
+
Provides-Extra: litellm
|
|
38
|
+
Requires-Dist: litellm>=1.40.0; extra == "litellm"
|
|
39
|
+
Provides-Extra: all
|
|
40
|
+
Requires-Dist: langchain-core>=0.2.0; extra == "all"
|
|
41
|
+
Requires-Dist: langgraph>=0.2.0; extra == "all"
|
|
42
|
+
Requires-Dist: openai>=1.0.0; extra == "all"
|
|
43
|
+
Requires-Dist: litellm>=1.40.0; extra == "all"
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
47
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: langchain-core>=0.2.0; extra == "dev"
|
|
50
|
+
Requires-Dist: langgraph>=0.2.0; extra == "dev"
|
|
51
|
+
Requires-Dist: openai>=1.0.0; extra == "dev"
|
|
52
|
+
Requires-Dist: litellm>=1.40.0; extra == "dev"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
<div align="center">
|
|
56
|
+
<h1>Official Python SDK for Blocklog</h1>
|
|
57
|
+
<p><strong>Typed Python SDK for integrating Blocklog into AI applications with structured audit logging, execution tracing, and cryptographic verification.
|
|
58
|
+
</strong></p>
|
|
59
|
+
|
|
60
|
+
[](https://www.python.org/downloads/)
|
|
61
|
+

|
|
62
|
+
[](https://pypi.org/project/blocklog/)
|
|
63
|
+
[](https://opensource.org/licenses/MIT)
|
|
64
|
+
[](docs/index.md)
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
Blocklog Python SDK is the official Python client for Blocklog. It enables Python applications to record AI execution traces, manage decision records, verify audit integrity, and interact with Blocklog's APIs through a clean, typed, and developer-friendly interface.
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
- **Client & Transport**: Synchronous and asynchronous (`AsyncBlocklogClient`) support, connection pooling, exponential backoff retries, and background event batching.
|
|
74
|
+
- **Observability**: Decorator-based tracing for agents (`@blocklog.agent`) and tools (`@blocklog.tool`).
|
|
75
|
+
- **Governance**: Human-in-the-loop (HITL) approval workflows and incident management.
|
|
76
|
+
- **Security & Compliance**: Ed25519 cryptographic payload signing, timeline verification, and automated SOC2/GDPR compliance reports.
|
|
77
|
+
- **Integrations**: Auto-instrumentation for LangChain, LangGraph, OpenAI, and LiteLLM.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
The SDK requires **Python 3.10+**.
|
|
84
|
+
|
|
85
|
+
### pip
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pip install blocklog
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
*(Optional)* Install with all integrations (LangChain, LangGraph, OpenAI, LiteLLM):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install blocklog[all]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### uv
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
uv pip install blocklog
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### poetry
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
poetry add blocklog
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Quick Start
|
|
112
|
+
|
|
113
|
+
The fastest way to get started is to initialize the client and record a single decision.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import os
|
|
117
|
+
from blocklog import BlocklogClient
|
|
118
|
+
|
|
119
|
+
# 1. Initialize the client
|
|
120
|
+
client = BlocklogClient(api_key=os.environ.get("BLOCKLOG_API_KEY"))
|
|
121
|
+
|
|
122
|
+
# 2. Record an AI decision
|
|
123
|
+
response = client.decisions.create(
|
|
124
|
+
decision_type="BUY_ORDER",
|
|
125
|
+
asset="TSLA",
|
|
126
|
+
confidence=0.91,
|
|
127
|
+
inputs={"price": 412.50, "signals": ["momentum"]},
|
|
128
|
+
outputs={"order_id": "ord_123984"},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
print(f"Decision recorded: {response.get('id')}")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
For advanced tracing, Blocklog provides decorators (`@blocklog.agent`, `@blocklog.tool`) to automatically capture inputs and outputs within a shared execution context.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Authentication
|
|
139
|
+
|
|
140
|
+
Blocklog primarily authenticates using API Keys for server-to-server communication. For user-specific or dashboard actions, an Access Token is used.
|
|
141
|
+
|
|
142
|
+
### API Keys (Server-to-Server)
|
|
143
|
+
|
|
144
|
+
API keys are required to record logs, decisions, and traces. Set it via environment variable:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
export BLOCKLOG_API_KEY="blk_..."
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Then instantiate the client:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from blocklog import BlocklogClient
|
|
154
|
+
|
|
155
|
+
# Automatically loads from BLOCKLOG_API_KEY
|
|
156
|
+
client = BlocklogClient()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Access Tokens (User Context)
|
|
160
|
+
|
|
161
|
+
If you are interacting with team management or dashboard APIs on behalf of a specific user, provide an access token:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
client.set_access_token("user_access_token_here")
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Examples
|
|
170
|
+
|
|
171
|
+
### Human-in-the-Loop (HITL) Approval
|
|
172
|
+
|
|
173
|
+
Flag a high-stakes decision for human review before allowing the system to proceed.
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
# Request approval (non-blocking in the SDK, triggers webhook in backend)
|
|
177
|
+
response = client.approval.request(
|
|
178
|
+
decision_id="dec_abc123",
|
|
179
|
+
reason="Trade exceeds $500k automated threshold",
|
|
180
|
+
reviewer="risk-team@fund.com",
|
|
181
|
+
)
|
|
182
|
+
print("Approval requested successfully.")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Cryptographic Verification
|
|
186
|
+
|
|
187
|
+
Verify that an agent's decision and its underlying evidence have not been tampered with.
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
verification = client.verify.decision("dec_abc123")
|
|
191
|
+
|
|
192
|
+
if verification["status"] == "verified":
|
|
193
|
+
print("Decision integrity mathematically proven.")
|
|
194
|
+
else:
|
|
195
|
+
print("WARNING: Tampering detected!")
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Incident Management
|
|
199
|
+
|
|
200
|
+
Create an incident based on an anomalous trace and assign it to an investigator.
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
incident = client.incidents.create(
|
|
204
|
+
title="Unexpected SELL order for AAPL", trace_id="trace-xyz", severity="high"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
incident.assign("alice@fund.com", notes="Please investigate this immediately.")
|
|
208
|
+
incident.resolve(summary="False positive - corrected upstream model weights.")
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Export Compliance Evidence
|
|
212
|
+
|
|
213
|
+
Generate a SOC2 compliance report scoped to a specific AI trace.
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
report = client.compliance.generate(trace_id="trace-xyz", framework="SOC2")
|
|
217
|
+
|
|
218
|
+
# Create a secure shareable link valid for 24 hours
|
|
219
|
+
link = client.compliance.share(report["id"], expires_in=86400)
|
|
220
|
+
print(f"Compliance report available at: {link['share_url']}")
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## SDK Architecture
|
|
226
|
+
|
|
227
|
+
The SDK is organized into intuitive, domain-specific resource layers accessible directly from the `BlocklogClient`:
|
|
228
|
+
|
|
229
|
+
- `client.decisions`: Manage AI decision records and evidence timelines.
|
|
230
|
+
- `client.approval`: Human-in-the-Loop (HITL) workflow management.
|
|
231
|
+
- `client.incidents`: Incident response lifecycle (assign, annotate, resolve).
|
|
232
|
+
- `client.replay`: Forensic replay sessions and root-cause analysis.
|
|
233
|
+
- `client.compliance`: Compliance dashboard and report generation.
|
|
234
|
+
- `client.verify`: Cryptographic verification of logs and batches.
|
|
235
|
+
- `client.traces`: Query trace and session execution paths.
|
|
236
|
+
- `client.teams`: Manage organizations, users, and SLA rules.
|
|
237
|
+
- `client.auth`: User signups and authentication flows.
|
|
238
|
+
|
|
239
|
+
For modern asynchronous applications (e.g., FastAPI), use `AsyncBlocklogClient` which provides the exact same architecture but with `async/await` semantics.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Error Handling
|
|
244
|
+
|
|
245
|
+
The SDK raises specific typed exceptions (inheriting from `BlocklogError`) mapped to underlying HTTP status codes, allowing you to gracefully handle failures.
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
from blocklog.exceptions import (
|
|
249
|
+
BlocklogError,
|
|
250
|
+
AuthenticationError,
|
|
251
|
+
RateLimitError,
|
|
252
|
+
ValidationError,
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
client.decisions.get("invalid_id")
|
|
257
|
+
except AuthenticationError:
|
|
258
|
+
print("Invalid API Key provided.")
|
|
259
|
+
except RateLimitError:
|
|
260
|
+
print("Throttled by Blocklog backend. Backing off.")
|
|
261
|
+
except ValidationError as e:
|
|
262
|
+
print(f"Malformed request data: {e}")
|
|
263
|
+
except BlocklogError as e:
|
|
264
|
+
print(f"An unexpected error occurred: {e}")
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Configuration
|
|
270
|
+
|
|
271
|
+
You can customize the SDK's behavior using the `BlocklogConfig` object or via environment variables:
|
|
272
|
+
|
|
273
|
+
| Environment Variable | Description | Default |
|
|
274
|
+
|----------------------|-------------|---------|
|
|
275
|
+
| `BLOCKLOG_API_KEY` | Your Blocklog API key | `""` |
|
|
276
|
+
| `BLOCKLOG_BASE_URL` | API base URL | `https://blocklogsecurity.com/api/v1` |
|
|
277
|
+
| `BLOCKLOG_TIMEOUT` | Request timeout in seconds | `10` |
|
|
278
|
+
| `BLOCKLOG_MAX_RETRIES` | Max exponential backoff retries | `3` |
|
|
279
|
+
| `BLOCKLOG_BATCH_SIZE` | Telemetry event batch size | `100` |
|
|
280
|
+
| `BLOCKLOG_FLUSH_INTERVAL` | Batch flush interval in seconds | `2` |
|
|
281
|
+
| `BLOCKLOG_SDK_SIGNING_KEY` | Optional seed key for Ed25519 signing | `""` |
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## Why Use the Python SDK?
|
|
286
|
+
|
|
287
|
+
While you could interact with the Blocklog API using raw HTTP requests, the SDK provides significant developer experience improvements:
|
|
288
|
+
|
|
289
|
+
1. **Context Propagation**: Leveraging `contextvars`, the SDK automatically propagates `trace_id` and `session_id` across your application boundaries without passing variables manually.
|
|
290
|
+
2. **Background Batching**: High-volume telemetry (logs, tool inputs) are safely buffered in-memory and asynchronously flushed to prevent blocking your application's critical path.
|
|
291
|
+
3. **Resilience**: Built-in exponential backoff and automatic retry logic for transient network failures.
|
|
292
|
+
4. **Auto-Instrumentation**: One-line integrations to automatically trace LangChain, LangGraph, OpenAI SDK, and LiteLLM executions.
|
|
293
|
+
5. **Ed25519 Signing**: The SDK handles the cryptographic signing of payloads natively when `BLOCKLOG_SDK_SIGNING_KEY` is provided.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## API Coverage
|
|
298
|
+
|
|
299
|
+
The SDK implements comprehensive support for the Blocklog REST API:
|
|
300
|
+
|
|
301
|
+
- ✅ **Decisions** (`create`, `list`, `get`, `timeline`, `evidence`)
|
|
302
|
+
- ✅ **Approvals** (`request`, `reject`, `escalate`, `audit_trail`)
|
|
303
|
+
- ✅ **Incidents** (`create`, `assign`, `resolve`, `close`, `report`, `annotate`)
|
|
304
|
+
- ✅ **Forensics & Replay** (`create`, `timeline`, `root_cause`, `causal_graph`, `counterfactual`, `compare`)
|
|
305
|
+
- ✅ **Compliance** (`generate`, `list`, `dashboard`, `share`, `export`)
|
|
306
|
+
- ✅ **Verification** (`log`, `batch`, `decision`)
|
|
307
|
+
- ✅ **Teams & Auth** (`signup`, `login`, `teams.list`, `teams.update`)
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Development & Testing
|
|
312
|
+
|
|
313
|
+
We welcome contributions to the Blocklog Python SDK!
|
|
314
|
+
|
|
315
|
+
1. Clone the repository.
|
|
316
|
+
2. Install the package in editable mode with development dependencies:
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
pip install -e ".[dev]"
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
3. Run the test suite using `pytest`:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
pytest tests/ -v
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
blocklog-0.2.6/README.md
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1>Official Python SDK for Blocklog</h1>
|
|
3
|
+
<p><strong>Typed Python SDK for integrating Blocklog into AI applications with structured audit logging, execution tracing, and cryptographic verification.
|
|
4
|
+
</strong></p>
|
|
5
|
+
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+

|
|
8
|
+
[](https://pypi.org/project/blocklog/)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
[](docs/index.md)
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Blocklog Python SDK is the official Python client for Blocklog. It enables Python applications to record AI execution traces, manage decision records, verify audit integrity, and interact with Blocklog's APIs through a clean, typed, and developer-friendly interface.
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- **Client & Transport**: Synchronous and asynchronous (`AsyncBlocklogClient`) support, connection pooling, exponential backoff retries, and background event batching.
|
|
20
|
+
- **Observability**: Decorator-based tracing for agents (`@blocklog.agent`) and tools (`@blocklog.tool`).
|
|
21
|
+
- **Governance**: Human-in-the-loop (HITL) approval workflows and incident management.
|
|
22
|
+
- **Security & Compliance**: Ed25519 cryptographic payload signing, timeline verification, and automated SOC2/GDPR compliance reports.
|
|
23
|
+
- **Integrations**: Auto-instrumentation for LangChain, LangGraph, OpenAI, and LiteLLM.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
The SDK requires **Python 3.10+**.
|
|
30
|
+
|
|
31
|
+
### pip
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install blocklog
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
*(Optional)* Install with all integrations (LangChain, LangGraph, OpenAI, LiteLLM):
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install blocklog[all]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### uv
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv pip install blocklog
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### poetry
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
poetry add blocklog
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
The fastest way to get started is to initialize the client and record a single decision.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import os
|
|
63
|
+
from blocklog import BlocklogClient
|
|
64
|
+
|
|
65
|
+
# 1. Initialize the client
|
|
66
|
+
client = BlocklogClient(api_key=os.environ.get("BLOCKLOG_API_KEY"))
|
|
67
|
+
|
|
68
|
+
# 2. Record an AI decision
|
|
69
|
+
response = client.decisions.create(
|
|
70
|
+
decision_type="BUY_ORDER",
|
|
71
|
+
asset="TSLA",
|
|
72
|
+
confidence=0.91,
|
|
73
|
+
inputs={"price": 412.50, "signals": ["momentum"]},
|
|
74
|
+
outputs={"order_id": "ord_123984"},
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
print(f"Decision recorded: {response.get('id')}")
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For advanced tracing, Blocklog provides decorators (`@blocklog.agent`, `@blocklog.tool`) to automatically capture inputs and outputs within a shared execution context.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Authentication
|
|
85
|
+
|
|
86
|
+
Blocklog primarily authenticates using API Keys for server-to-server communication. For user-specific or dashboard actions, an Access Token is used.
|
|
87
|
+
|
|
88
|
+
### API Keys (Server-to-Server)
|
|
89
|
+
|
|
90
|
+
API keys are required to record logs, decisions, and traces. Set it via environment variable:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
export BLOCKLOG_API_KEY="blk_..."
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Then instantiate the client:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from blocklog import BlocklogClient
|
|
100
|
+
|
|
101
|
+
# Automatically loads from BLOCKLOG_API_KEY
|
|
102
|
+
client = BlocklogClient()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Access Tokens (User Context)
|
|
106
|
+
|
|
107
|
+
If you are interacting with team management or dashboard APIs on behalf of a specific user, provide an access token:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
client.set_access_token("user_access_token_here")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Examples
|
|
116
|
+
|
|
117
|
+
### Human-in-the-Loop (HITL) Approval
|
|
118
|
+
|
|
119
|
+
Flag a high-stakes decision for human review before allowing the system to proceed.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
# Request approval (non-blocking in the SDK, triggers webhook in backend)
|
|
123
|
+
response = client.approval.request(
|
|
124
|
+
decision_id="dec_abc123",
|
|
125
|
+
reason="Trade exceeds $500k automated threshold",
|
|
126
|
+
reviewer="risk-team@fund.com",
|
|
127
|
+
)
|
|
128
|
+
print("Approval requested successfully.")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Cryptographic Verification
|
|
132
|
+
|
|
133
|
+
Verify that an agent's decision and its underlying evidence have not been tampered with.
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
verification = client.verify.decision("dec_abc123")
|
|
137
|
+
|
|
138
|
+
if verification["status"] == "verified":
|
|
139
|
+
print("Decision integrity mathematically proven.")
|
|
140
|
+
else:
|
|
141
|
+
print("WARNING: Tampering detected!")
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Incident Management
|
|
145
|
+
|
|
146
|
+
Create an incident based on an anomalous trace and assign it to an investigator.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
incident = client.incidents.create(
|
|
150
|
+
title="Unexpected SELL order for AAPL", trace_id="trace-xyz", severity="high"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
incident.assign("alice@fund.com", notes="Please investigate this immediately.")
|
|
154
|
+
incident.resolve(summary="False positive - corrected upstream model weights.")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Export Compliance Evidence
|
|
158
|
+
|
|
159
|
+
Generate a SOC2 compliance report scoped to a specific AI trace.
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
report = client.compliance.generate(trace_id="trace-xyz", framework="SOC2")
|
|
163
|
+
|
|
164
|
+
# Create a secure shareable link valid for 24 hours
|
|
165
|
+
link = client.compliance.share(report["id"], expires_in=86400)
|
|
166
|
+
print(f"Compliance report available at: {link['share_url']}")
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## SDK Architecture
|
|
172
|
+
|
|
173
|
+
The SDK is organized into intuitive, domain-specific resource layers accessible directly from the `BlocklogClient`:
|
|
174
|
+
|
|
175
|
+
- `client.decisions`: Manage AI decision records and evidence timelines.
|
|
176
|
+
- `client.approval`: Human-in-the-Loop (HITL) workflow management.
|
|
177
|
+
- `client.incidents`: Incident response lifecycle (assign, annotate, resolve).
|
|
178
|
+
- `client.replay`: Forensic replay sessions and root-cause analysis.
|
|
179
|
+
- `client.compliance`: Compliance dashboard and report generation.
|
|
180
|
+
- `client.verify`: Cryptographic verification of logs and batches.
|
|
181
|
+
- `client.traces`: Query trace and session execution paths.
|
|
182
|
+
- `client.teams`: Manage organizations, users, and SLA rules.
|
|
183
|
+
- `client.auth`: User signups and authentication flows.
|
|
184
|
+
|
|
185
|
+
For modern asynchronous applications (e.g., FastAPI), use `AsyncBlocklogClient` which provides the exact same architecture but with `async/await` semantics.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Error Handling
|
|
190
|
+
|
|
191
|
+
The SDK raises specific typed exceptions (inheriting from `BlocklogError`) mapped to underlying HTTP status codes, allowing you to gracefully handle failures.
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from blocklog.exceptions import (
|
|
195
|
+
BlocklogError,
|
|
196
|
+
AuthenticationError,
|
|
197
|
+
RateLimitError,
|
|
198
|
+
ValidationError,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
try:
|
|
202
|
+
client.decisions.get("invalid_id")
|
|
203
|
+
except AuthenticationError:
|
|
204
|
+
print("Invalid API Key provided.")
|
|
205
|
+
except RateLimitError:
|
|
206
|
+
print("Throttled by Blocklog backend. Backing off.")
|
|
207
|
+
except ValidationError as e:
|
|
208
|
+
print(f"Malformed request data: {e}")
|
|
209
|
+
except BlocklogError as e:
|
|
210
|
+
print(f"An unexpected error occurred: {e}")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Configuration
|
|
216
|
+
|
|
217
|
+
You can customize the SDK's behavior using the `BlocklogConfig` object or via environment variables:
|
|
218
|
+
|
|
219
|
+
| Environment Variable | Description | Default |
|
|
220
|
+
|----------------------|-------------|---------|
|
|
221
|
+
| `BLOCKLOG_API_KEY` | Your Blocklog API key | `""` |
|
|
222
|
+
| `BLOCKLOG_BASE_URL` | API base URL | `https://blocklogsecurity.com/api/v1` |
|
|
223
|
+
| `BLOCKLOG_TIMEOUT` | Request timeout in seconds | `10` |
|
|
224
|
+
| `BLOCKLOG_MAX_RETRIES` | Max exponential backoff retries | `3` |
|
|
225
|
+
| `BLOCKLOG_BATCH_SIZE` | Telemetry event batch size | `100` |
|
|
226
|
+
| `BLOCKLOG_FLUSH_INTERVAL` | Batch flush interval in seconds | `2` |
|
|
227
|
+
| `BLOCKLOG_SDK_SIGNING_KEY` | Optional seed key for Ed25519 signing | `""` |
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Why Use the Python SDK?
|
|
232
|
+
|
|
233
|
+
While you could interact with the Blocklog API using raw HTTP requests, the SDK provides significant developer experience improvements:
|
|
234
|
+
|
|
235
|
+
1. **Context Propagation**: Leveraging `contextvars`, the SDK automatically propagates `trace_id` and `session_id` across your application boundaries without passing variables manually.
|
|
236
|
+
2. **Background Batching**: High-volume telemetry (logs, tool inputs) are safely buffered in-memory and asynchronously flushed to prevent blocking your application's critical path.
|
|
237
|
+
3. **Resilience**: Built-in exponential backoff and automatic retry logic for transient network failures.
|
|
238
|
+
4. **Auto-Instrumentation**: One-line integrations to automatically trace LangChain, LangGraph, OpenAI SDK, and LiteLLM executions.
|
|
239
|
+
5. **Ed25519 Signing**: The SDK handles the cryptographic signing of payloads natively when `BLOCKLOG_SDK_SIGNING_KEY` is provided.
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## API Coverage
|
|
244
|
+
|
|
245
|
+
The SDK implements comprehensive support for the Blocklog REST API:
|
|
246
|
+
|
|
247
|
+
- ✅ **Decisions** (`create`, `list`, `get`, `timeline`, `evidence`)
|
|
248
|
+
- ✅ **Approvals** (`request`, `reject`, `escalate`, `audit_trail`)
|
|
249
|
+
- ✅ **Incidents** (`create`, `assign`, `resolve`, `close`, `report`, `annotate`)
|
|
250
|
+
- ✅ **Forensics & Replay** (`create`, `timeline`, `root_cause`, `causal_graph`, `counterfactual`, `compare`)
|
|
251
|
+
- ✅ **Compliance** (`generate`, `list`, `dashboard`, `share`, `export`)
|
|
252
|
+
- ✅ **Verification** (`log`, `batch`, `decision`)
|
|
253
|
+
- ✅ **Teams & Auth** (`signup`, `login`, `teams.list`, `teams.update`)
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Development & Testing
|
|
258
|
+
|
|
259
|
+
We welcome contributions to the Blocklog Python SDK!
|
|
260
|
+
|
|
261
|
+
1. Clone the repository.
|
|
262
|
+
2. Install the package in editable mode with development dependencies:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
pip install -e ".[dev]"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
3. Run the test suite using `pytest`:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
pytest tests/ -v
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## License
|
|
277
|
+
|
|
278
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SDK architecture
|
|
2
|
+
|
|
3
|
+
The Python SDK is a context-aware wrapper over the Blocklog HTTP API. It owns
|
|
4
|
+
authentication headers, timeouts, safe read retries, event serialization, and
|
|
5
|
+
optional batching. The backend owns validation, persistence, rate limiting, and
|
|
6
|
+
verification artifacts.
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
Python application -> Python SDK -> HTTP/API -> Blocklog backend
|
|
10
|
+
-> execution/event infrastructure
|
|
11
|
+
-> verification and receipts
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`record_event()` calls the backend-supported `POST /api/v1/logs` route. Batched
|
|
15
|
+
events use `POST /api/v1/logs/batch`. These mutations are not automatically
|
|
16
|
+
retried because the backend's ingestion contract does not document idempotent
|
|
17
|
+
replay behavior. GET operations may be retried for transient errors.
|
|
18
|
+
|
|
19
|
+
The execution-management backend currently exposes `/api/v1/executions` and
|
|
20
|
+
its step/status routes; its request shape is defined by the backend FastAPI
|
|
21
|
+
signatures and remains the source of truth.
|
|
@@ -10,6 +10,7 @@ If you need direct access to the low-level client for async operations (like man
|
|
|
10
10
|
from blocklog.async_client import AsyncBlocklogClient
|
|
11
11
|
from blocklog.config import BlocklogConfig
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
async def setup():
|
|
14
15
|
config = BlocklogConfig(api_key="blk_...")
|
|
15
16
|
client = AsyncBlocklogClient(config)
|
|
@@ -26,23 +27,26 @@ import blocklog
|
|
|
26
27
|
|
|
27
28
|
blocklog.init()
|
|
28
29
|
|
|
30
|
+
|
|
29
31
|
@blocklog.tool
|
|
30
32
|
async def fetch_async_data(url: str) -> dict:
|
|
31
33
|
# Simulate async network request
|
|
32
34
|
await asyncio.sleep(0.5)
|
|
33
35
|
return {"status": 200, "data": "async payload"}
|
|
34
36
|
|
|
37
|
+
|
|
35
38
|
@blocklog.agent(name="async-agent")
|
|
36
39
|
async def main_agent():
|
|
37
40
|
data = await fetch_async_data("https://api.example.com")
|
|
38
|
-
|
|
41
|
+
|
|
39
42
|
# Decisions work perfectly within async contexts
|
|
40
43
|
with blocklog.decision(type="EVALUATE", asset="url") as d:
|
|
41
44
|
d.record_input(data=data)
|
|
42
45
|
d.record_output(valid=True)
|
|
43
|
-
|
|
46
|
+
|
|
44
47
|
return data
|
|
45
48
|
|
|
49
|
+
|
|
46
50
|
if __name__ == "__main__":
|
|
47
51
|
asyncio.run(main_agent())
|
|
48
52
|
```
|