Skip to main content

blankstate-sdk

Python client for the Blankstate API (import package blankstate_sdk; PyPI distribution blankstate-sdk).

Measure interactions against behavioral protocols — get a score, per-metamarker resonance, signal analysis, and fidelity assessment. The engine runs server-side; this package handles auth, request formatting, and typed responses.

Install

pip install blankstate-sdk

Requires Python >= 3.10. Uses httpx for async HTTP and pydantic for typed responses.


Quick Start

import asyncio
from blankstate_sdk import Blankstate

bks = Blankstate(token="your_api_token")

async def main():
    result = await bks.sense("proto-xxx:1.0", "The agent resolved the issue promptly.")

    print(result.score)             # 0.82
    print(result.resonance)         # {"Solution-Oriented": 0.96, "Empathy": 0.41}
    print(result.fidelity)          # index=0.74 sufficient=True
    print(result.ics.consumed)      # 2

asyncio.run(main())

Or set your token via environment variable:

macOS / Linux:

export BLANKSTATE_API_TOKEN=bks_your_token

Windows:

$env:BLANKSTATE_API_TOKEN = "bks_your_token"
import os
from blankstate_sdk import Blankstate

bks = Blankstate(token=os.environ["BLANKSTATE_API_TOKEN"])

API

Blankstate(token, *, api_url=..., user_agent=...)

Parameter Type Default Description
token str | BlankstateOptions — API token (required), or pass BlankstateOptions as the only positional argument
api_url str https://api.blankstate.ai API base URL (BLANKSTATE_API_URL if omitted)
user_agent str blankstate-sdk User-Agent header sent with every request (including healthy())

Equivalent to the JS options object:

from blankstate_sdk import Blankstate, BlankstateOptions

bks = Blankstate(BlankstateOptions(token="...", api_url="https://api.blankstate.ai"))

Response models live in blankstate_sdk.models (import types from there for annotations).


Sense

Measure content against a protocol. The measurement engine version is set by the protocol definition — not by the caller.

result = await bks.sense(
    "proto-xxx:1.0",
    content,
    language="en",          # default: "en"
    profile="detailed",     # "raw" | "detailed" | "discovery"
    depth="full",           # "measure" | "full"
)

result.score          # overall alignment (0.0–1.0)
result.resonance      # {"Empathy": 0.91, "Solution-Oriented": 0.76}
result.signal         # spread, coherence, dominant_mode (v1.5 protocols)
result.actant_flow    # entity influence direction (v1.5 protocols)
result.temporal       # temporal trend analysis (v1.5 protocols)
result.fidelity       # index, sufficient
result.ics            # consumed, cost_usd, sgm_version, pool

Measure against multiple protocols in parallel:

results = await bks.sense_multiple(
    ["proto-aaa:1.0", "proto-bbb:2.0"],
    content,
)
# returns dict[protocol_id, SenseResponse]
# failed protocols are silently dropped

Fidelity Check — 0 ICS

Pre-check whether content has enough signal for measurement before spending ICS:

check = await bks.fidelity_check("proto-xxx:1.0", content)

check.fidelity.sufficient     # True | False
check.fidelity.index          # 0.74
check.estimated_ics           # ICSRange(min=1, max=3, typical=2)

Status and Usage

status = await bks.status()
# status.authenticated
# status.sgm_versions       — {"1.0": "stable", "1.5": "extended"}
# status.ics.remaining
# status.ics.member         — member-level cap if set

usage = await bks.usage()
# usage.ics_used, usage.ics_remaining, usage.ics_total

estimate = await bks.usage_estimate(content_length=500, modality="text")
# estimate.estimated_ics, estimate.will_exceed_quota

Protocols

# List protocols in your account
protocols = await bks.protocols()
# [ProtocolSummary(id=..., name=..., versions=[...], sgm_version=...)]

# Get a protocol's full definition
definition = await bks.protocol("proto-xxx:1.0")
# definition.id, definition.name, definition.version, definition.sgm_version
# definition.metamarkers  — [ProtocolMetamarker(label=..., description=...)]
# definition.taxonomy, definition.supported_modalities

Programmatic Dive

opened = await bks.dive.open({"stage_id": "stg_…", "agent": {"id": "my-agent", "version": "1"}})
await bks.dive.act(opened.dive_id, {"action": "Inspect the records", "turn": opened.observation.turn or 0})
await bks.dive.status(opened.dive_id)
await bks.dive.close(opened.dive_id, {"summary": "done"})

Stages

A Stage is the situation you author and version; a World is one run of it. Writes are applied whole or refused whole: a BlankstateAPIError carries issues (422, 423) or the current rev (409).

made = await bks.stages.create({
    "world": "proxy",
    "premise": "Claims appeals in the UK: members contest decisions, assessors review.",
    "ops": {"actants": [{"label": "Member", "kind": "group"}, {"label": "Assessor", "kind": "person"}]},
})
rev = (await bks.stages.get(made.id)).rev
await bks.stages.edit(made.id, {
    "if_rev": rev,
    "ops": {"links": [{"from": "Member", "to": "Assessor", "surface": "chat", "relation": "files the appeal"}]},
})
checked = await bks.stages.check(made.id)
stages = await bks.stages.list()
estimated = await bks.stages.estimate(made.id, {"span": 20})
started = await bks.stages.start_world(made.id)
await bks.stages.set_world(made.id, started.world_id, "paused")
world = await bks.stages.world(made.id, started.world_id, {"trajectories": True})
Method Arguments Does
stages.list() — Your Stages: id, title, world, rev, Worlds run
stages.create(params) world ("proxy"), premise, scale?, ops? A Stage from a premise, with typed operations. Applied whole or refused whole
stages.get(stage_id) The outline and rev
stages.edit(stage_id, params) if_rev, ops Typed operations against the rev you read. A stale rev is a BlankstateAPIError carrying the current rev (409)
stages.check(stage_id) What is thin, each with a question, and the gaps
stages.estimate(stage_id, params) span, seed? What span days (or turns) ask on a seed: interactions, agents, minutes / minutes_max, ICS range, and what each objective read on events would count (expect). Spends nothing
stages.start_world(stage_id, run=None) budget_ics?, minutes?, until_day?, pauses?, target?, seed? Start a World. Answers at once; follow it with world
stages.set_world(stage_id, world_id, state, run=None) state: "running" | "paused" | "stopped" Pause, stop, or carry on. Run options go only with "running"
stages.worlds(stage_id) The Stage's Worlds, newest first
stages.world(stage_id, world_id, opts=None) trajectories? Status and outcome: day, objectives, spread, levers, proposals, ICS, next_steps
stages.review(stage_id, world_id, params) keep?, discard? Keep or discard proposals by id
stages.rename_world(stage_id, world_id, name) Rename a World
stages.delete_world(stage_id, world_id) Delete a World. One still running stops first
stages.versions(stage_id, opts=None) from?, to? Kept versions, and what changed between two
stages.restore(stage_id, params) if_rev, version Make a kept version the Stage again
stages.create_variant(params) stage, world, label, varies, question? A Variant on the version that World ran on. varies is one or more of system, population, environment, clock

The token needs stages:read and stages:write to create or edit, and runs:dry to estimate, start, pause, and carry on Worlds.


Health

ok = await bks.healthy()  # True | False — 0 ICS, no auth required

Error Handling

from blankstate_sdk import BlankstateAPIError

try:
    result = await bks.sense("proto-xxx:1.0", content)
except BlankstateAPIError as err:
    print(err.status_code)      # HTTP status code
    print(err.error_message)    # human-readable message
    print(err.code)             # machine-readable error code

    if err.is_auth_error():     # 401/403 — check your token
        ...
    if err.is_quota_error():    # 429 — ICS quota exceeded
        print(err.ics_info)     # {"quota": 50, "used": 50, "remaining": 0}
    if err.is_server_error():   # 5xx — retryable
        ...

Development

This package has its own pyproject.toml. From the repo root:

git clone https://github.com/blankstate-ai/blankstate-py.git
cd blankstate-py

python3 -m pip install -e "./packages/sdk[dev]"
pytest packages/sdk/tests

Or from packages/sdk/:

cd packages/sdk
pip install -e ".[dev]"
pytest

Concepts

Term Description
Protocol A behavioral sensor — defines metamarkers that characterize an interaction pattern
Metamarker A named behavioral signal (e.g., "Empathy", "Escalation Risk")
Resonance Activation strength of each metamarker (0.0–1.0)
Score Aggregate alignment between content and the protocol
Fidelity Signal quality — whether content has enough substance for reliable measurement
ICS Interaction Computed Signal — billing unit per measurement
SGM Blankstate measurement engine — v1.0 (stable), v1.5 (extended signal analysis)

Requirements

  • Atlas — Dashboard, API tokens, protocol management
  • API Reference — Full REST API documentation
  • Issues — Bug reports and feature requests

License

MIT — blankstate.ai

Metadata

Release files for blankstate-sdk 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for blankstate-sdk 0.5.0
File Size Uploaded Provenance Actions
blankstate_sdk-0.5.0.tar.gz 22.1 kB Without provenance Details for blankstate_sdk-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for blankstate-sdk 0.5.0
File Interpreter ABI Platform Actions
blankstate_sdk-0.5.0-py3-none-any.whl Python 3 none any Details for blankstate_sdk-0.5.0-py3-none-any.whl

Total release size: 41.2 kB

Release files / blankstate_sdk-0.5.0.tar.gz

Download URL blankstate_sdk-0.5.0.tar.gz
Size 22.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6fc9a168ea95b92f36b52b8ecba1374f1df7db68ce30e2b7d0b7cf59083ebd96
BLAKE2b-256 checksum
How to use checksums
91c0930d95a45d9549e7f6498dca95dcb9c27402af099e2e17628349a60a4aed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / blankstate_sdk-0.5.0-py3-none-any.whl

Download URL blankstate_sdk-0.5.0-py3-none-any.whl
Size 19.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
09c2348b3bbd1ba18ec0b5f92b9e6b73298df8a967eb400a70396cfbb427da93
BLAKE2b-256 checksum
How to use checksums
9c7fa0b3496d3042eb4c8238e97edfb7cf8bd56ca93c6673044120505b10d8ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Security for blankstate-sdk 0.5.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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page