Skip to main content

Python client for BLACK_WALL — pre-action risk gate for AI agents. Call forecast() before any irreversible action; observe() to close the loop. Zero dependencies; stdlib-only.

Project description

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–100
  • reversibility: {"class": "REVERSIBLE" | "RECOVERABLE" | "IRREVERSIBLE", ...}
  • red_flags: named codes — e.g. SQL_NO_WHERE, PROMPT_INJECTION_LIKELY, IRREVERSIBLE_NO_BACKUP
  • receipt: 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:

  1. Fetch the public keys (stable URL, cache it): GET https://blackwalltier.com/.well-known/blackwall-signing-keys.json
  2. Pick the key whose key_id matches receipt["key_id"].
  3. Canonicalize the request/response bodies (stable key ordering, no extra whitespace).
  4. SHA-256 each; compare to receipt["request_hash"] / receipt["response_hash"].
  5. Verify receipt["signature"] (base64url) over request_hash + response_hash with 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

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blackwall_sdk-0.1.0.tar.gz (10.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

blackwall_sdk-0.1.0-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

Details for the file blackwall_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: blackwall_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 10.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for blackwall_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 cae01b58979d927e292256d7f23a7bb869eef4a789a6dc4182355d9222f4ad43
MD5 3a2cea55c52604a23373f57a5132cb18
BLAKE2b-256 1f4ef9d76fc3f5fdb6288e2e2f21df45c255e211ce5caa17c9ca903af5b46d74

See more details on using hashes here.

File details

Details for the file blackwall_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: blackwall_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for blackwall_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7ada2e51621f0af348ab5dbee4c6a0cfce4430158c153442f74addb2b219b998
MD5 cb69e29378d24545f71a4813b96e9fd0
BLAKE2b-256 6afccce50b15aeb67df2ab9be9a87d9e36f6462d8b50e37af557484f85fe7436

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page