stateweave Docs
Reference

Python SDK

The stateweave package: one client for everything the workspace does by API key. It uses only the standard library and needs Python 3.10 or later.

Shell
pip install stateweave-sdk
Python
import stateweave

client = stateweave.Client()
with client.start("t-bde537", agent="my-agent@0.1") as run:
    result = run.finish(my_agent(run.prompt, run.apps))

Client

Python
stateweave.Client(url=None, api_key=None, timeout=300)
ParameterDescription
urlYour workspace's address. Default: STATEWEAVE_URL, then what sw login kept, then http://127.0.0.1:8700.
api_keyAn API key, sw_…. Default: STATEWEAVE_API_KEY, then what sw login kept. Without one, Client() raises ValueError.
timeoutSeconds to wait for each request. Starting a run and grading one each take a few seconds.

Requests the workspace rate-limits per key (HTTP 429 rate_limited) are retried after the wait it asks for, up to three times.

stateweave.start(...) and stateweave.tests(...) are shortcuts for the same methods on a default Client().

me()

Returns {"studio", "name", "key": {"id", "name"}}: the workspace's address and name, and the key's.

Runs

tests(project=None)

The tests you can run, every scenario's or one's. Each is a dict with id, project, project_title, title, prompt, kind, apps, answer_format, persona and faults (how many it injects).

start(test, *, agent, project=None, timeout=None, meta=None)

Starts a run and returns a Run once its apps are up.

ParameterDescription
testThe test's id, t-….
agentRequired. The label runs are compared by, up to 80 characters.
projectThe scenario, when the test id is in several.
timeoutSeconds before the run ends unfinished: 60 to 86,400. Default 1,800.
metaA JSON-able dict shown with the run, up to 4,000 characters as JSON.

run(run_id)

A run you started, as it stands now.

next_run(worker, *, agent, meta=None, timeout=None, wait=25)

For a worker of your own: waits up to wait seconds (at most 30) for a run someone queued with Run again, and returns it started, or None. worker is your worker's id (4 to 40 letters, digits, - or _), the same on every call; calling keeps it listed as connected. sw worker is built on this.

leave(worker)

Stops a worker: the workspace no longer lists it or queues runs for it.

Run

A run of a test, returned by start(), run() and next_run(). Use it as a context manager: leaving the with block while the run is still going, because your agent raised or finish() was never called, gives it up.

AttributeDescription
idThe run's id, r-….
testThe test's id.
statusSee Run statuses.
promptThe request to give your agent.
kind"answer" or "action".
answer_formatFor an answer test, an example of the JSON value to answer with.
personaWhom the agent acts for: {"name", "handle", "title"}.
appsPer app: base_url, endpoints, credentials and mcp. See Apps and credentials.
expires_atWhen it times out, in Unix seconds.
urlThe run's page.
dataThe whole run as the API returned it.

credential(app, kind="user")

The first credential of app whose label starts with kind: "user", "bot", "app", "mcp" or "setup". None when there is none.

mcp_servers()

The apps' MCP servers as {app: {"type": "http", "url", "headers"}}, the shape Claude Code and the Claude Agent SDK take. Apps without one are left out.

finish(answer=None)

Hands in the answer (a JSON-able value; nothing for an action test), has the run graded, and returns its Result. Raises RunEnded if the run had already ended.

cancel()

Gives the run up: its apps stop and it is not graded. Returns its Result.

result()

The run's Result as last seen, without a request.

Result

A dataclass describing how a run ended.

FieldTypeDescription
idstrThe run's id.
statusstrpassed, failed, timed_out, cancelled, interrupted or error.
passedbool | NoneThe verdict, once graded.
reasonslist[str]Why it passed or failed.
callsintCalls your agent made to the apps.
urlstrThe run's page.

Scenarios and data

projects()

Every scenario, newest first: id, title, description, apps, status, error, company, steps and envs (per app its counts, summary and state). No credentials.

project(project)

One scenario, the same shape.

create_project(description, apps, *, company=None, people=None, weeks=None, content=None)

Starts generating a scenario and returns it with status generating. content: "auto" (Claude when the workspace has it), "llm" or "templates". See Scenarios.

data(project)

{"kinds": {app: {kind: {"title", "fields", "example"}}}, "additions": [...]}: what each app takes, and what was added so far.

add_data(project, app, kind, items)

Adds a list of items. Returns {"addition", "counts", "stale"}, stale being the number of tests that now need a re-check. A bad item raises StateWeaveError listing every problem, and nothing is added.

Tests

write_tests(project, requests, faults=None, *, noise=None, pinned=None, difficulty=None)

One test per request, its text kept word for word. Each request is a string, or a dict with text and optionally criteria, kind and apps. Returns the job.

suggest_tests(project, count, focus="", faults=None, difficulty="normal", *, noise=None, pinned=None)

count tests (1 to 10) from Claude's ideas. difficulty: "normal" or "hard". Returns the job.

Both take faults one way at most: faults (preset ids), noise (random injection, a dict; {} for the defaults) or pinned (a list of faults at endpoints). See Faults.

job(project, job)

A job writing tests: status (running, then done, or failed with an error) and items, each with status (pending, writing, checking, then ready, failed or rejected), title, request, test_id, detail and suggestion.

recheck(project, tests=None)

Re-checks the scenario's stale tests, or the ones named. Returns the ids being re-checked.

faults(project)

The fault presets: id, app, kind, title, observed (seen on the real service) and evidence.

fault_targets(project)

Where faults can be pinned: {"apps": {app: {"title", "kinds", "endpoints"}}, "kinds", "noise": {"defaults", "limits"}}. Each endpoint has an id, a label such as PUT /api/v2/tickets/{ticket_id}, and the kinds that can happen there.

Errors

ExceptionWhen
stateweave.StateWeaveErrorThe workspace refused a request. status is the HTTP status, body the JSON it answered (error, and message or problems).
stateweave.RunEndedA subclass: the run had already ended (timed out, cancelled, finished). run is the run as it ended.
ConnectionErrorNothing answered at the address. The message names it.
ValueErrorNo API key anywhere, or faults given more than one way.
Python
try:
    result = run.finish(answer)
except stateweave.RunEnded as e:
    print("the run had ended:", e.run["status"])
except stateweave.StateWeaveError as e:
    print(e.status, e.body.get("problems") or e.body.get("message"))

Version

stateweave.__version__, or sw --version.