blackwall-sdk
Python client for BLACK_WALL. Pre-action risk gate for AI agents. Call forecast() before any irreversible action; observe() after to close the loop. Decision receipts are Ed25519-signed and verifiable offline.
Zero dependencies. Stdlib only — small install footprint, safe to depend on from anywhere.
Install
pip install blackwall-sdk
# env (or pass explicitly as kwargs)
export BLACKWALL_API_KEY=bw_live_xxx
Free tier: ~100 forecasts/month, no card. Get a key at blackwalltier.com/dashboard/keys.
Usage
from blackwall_sdk import forecast, observe
verdict = forecast(
action="run_sql",
inputs={"statement": "DELETE FROM users"},
context={
"agent_role": "data cleanup bot",
"user_intent": "archive inactive customers",
},
)
if verdict["recommendation"] == "STOP":
raise RuntimeError(
f"BLACK_WALL blocked: {[f['code'] for f in verdict['red_flags']]}"
)
# ... run the action ...
observe(
forecast_id=verdict["id"],
outcome_class="matched", # matched | over_scope | under_scope | no_op | diverged | aborted
details="1 row deleted",
)
What you get back per forecast
recommendation:"GO"/"CAUTION"/"STOP"risk_score: 0–100reversibility:{"class": "REVERSIBLE" | "RECOVERABLE" | "IRREVERSIBLE", ...}red_flags: named codes — e.g.SQL_NO_WHERE,PROMPT_INJECTION_LIKELY,IRREVERSIBLE_NO_BACKUPreceipt: Ed25519 signature over canonical hashes of (request, response). Verifiable offline against the public key at blackwalltier.com/.well-known/blackwall-signing-keys.json.
Latency: ~4–8 seconds.
Errors
from blackwall_sdk import (
BlackwallError, # base class for all SDK errors
BlackwallConfigError, # missing api_key, bad base_url
BlackwallNetworkError, # transport failed (DNS, connect, timeout)
BlackwallHTTPError, # non-2xx response; carries .status and .body
)
try:
forecast(action="...", inputs={...})
except BlackwallHTTPError as e:
if e.status == 429:
# back off
...
except BlackwallError:
# broad catch — anything BLACK_WALL-related
...
Testing — injecting a custom transport
For unit tests, pass url_opener= to avoid touching the network. Same signature as the stdlib opener:
def my_opener(url, method, headers, body_bytes, timeout):
return 200, b'{"id": "fc_fake", "recommendation": "GO"}'
forecast(action="...", inputs={}, url_opener=my_opener)
Same hook works for proxies, retries, mTLS, or async wrappers — pass whatever returns (status, body_bytes).
Architecture
┌──────────────────────────────────────────────┐
│ BLACK_WALL HTTP API (stable, versioned) │
└──────────────────────────────────────────────┘
▲
┌──────────────────────────────────────────────┐
│ blackwall-sdk (this package) │
│ - forecast() │
│ - observe() │
└──────────────────────────────────────────────┘
▲
┌──────────┴──────────┐
│ │
blackwall-hermes-plugin your Python agent
(and future plugins) (LangChain, AutoGen,
CrewAI, Pydantic AI…)
When the API changes, the SDK absorbs it. Downstream plugins and agents stay on the same import.
Receipt verification (offline)
Receipts are Ed25519 over canonical SHA-256 hashes of (request, response). To verify locally without trusting the server:
- Fetch the public keys (stable URL, cache it):
GET https://blackwalltier.com/.well-known/blackwall-signing-keys.json - Pick the key whose
key_idmatchesreceipt["key_id"]. - Canonicalize the request/response bodies (stable key ordering, no extra whitespace).
- SHA-256 each; compare to
receipt["request_hash"]/receipt["response_hash"]. - Verify
receipt["signature"](base64url) overrequest_hash + response_hashwith the public key.
A verifier helper is on the roadmap for a future SDK version. For now, see the JS reference implementation or use the hosted endpoint:
POST https://blackwalltier.com/api/v1/receipts/verify
Links
- Site & docs: https://blackwalltier.com
- LLM reference: https://blackwalltier.com/llms-full.txt
- Failure-mode taxonomy (28 named red-flag codes): https://blackwalltier.com/failure-modes
- Free API key: https://blackwalltier.com/dashboard/keys
- Source: https://github.com/bluetieroperations-create/blackwall-sdk
- Sibling plugins:
blackwall-hermes-plugin(Python) ·blackwall-eliza-guardrail(npm) ·blackwall-openclaw-plugin(npm)
License
MIT
Metadata
Release files for blackwall-sdk 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| blackwall_sdk-0.1.0.tar.gz | 10.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| blackwall_sdk-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.3 kB
Release files / blackwall_sdk-0.1.0.tar.gz
| Download URL | blackwall_sdk-0.1.0.tar.gz |
|---|---|
| Size | 10.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cae01b58979d927e292256d7f23a7bb869eef4a789a6dc4182355d9222f4ad43
|
|
BLAKE2b-256 checksum How to use checksums |
1f4ef9d76fc3f5fdb6288e2e2f21df45c255e211ce5caa17c9ca903af5b46d74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.8
|
Release files / blackwall_sdk-0.1.0-py3-none-any.whl
| Download URL | blackwall_sdk-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7ada2e51621f0af348ab5dbee4c6a0cfce4430158c153442f74addb2b219b998
|
|
BLAKE2b-256 checksum How to use checksums |
6afccce50b15aeb67df2ab9be9a87d9e36f6462d8b50e37af557484f85fe7436
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.8
|
Security for blackwall-sdk 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.