Skip to main content

Staso Python SDK

Trace explicitly instrumented agent runs and evaluate proposed tool calls before your code executes them.

Supported launch configuration

  • Python 3.11+
  • OpenAI Chat Completions or Anthropic Messages
  • Synchronous or asynchronous, non-streaming calls
  • An explicit @st.agent root and @st.tool on executed Python tools
  • Claude Code and Codex through one-command CLI setup
  • Observe plus configured Guard policies in Audit or Enforce mode

Copy-paste launch sample

Use the canonical launch quickstart at https://staso.ai/docs/quickstart/launch. If you have a repository checkout, you can run the pinned copy in examples/launch_quickstart/:

pip install -r examples/launch_quickstart/requirements.txt

requirements.txt pins:

staso[openai]==0.5.15
openai==3.6.0

Set STASO_API_KEY, OPENAI_API_KEY, STASO_AGENT_NAME, STASO_ENVIRONMENT, STASO_WORKSPACE_SLUG, and STASO_SESSION_ID=launch-quickstart-first-trace, then run:

python examples/launch_quickstart/openai_guard_quickstart.py

The sample checks SDK delivery. Onboarding should wait for the dashboard/backend trace query before marking the first trace visible.

OpenAI quickstart

pip install "staso[openai]"
import json

import staso as st
from openai import OpenAI

st.init(api_key="ak_...", agent_name="weather-agent")
client = OpenAI()

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the weather for a city.",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        },
    }
]


@st.tool
def get_weather(city: str) -> dict:
    return {"city": city, "temperature_c": 18}


@st.agent
def answer(question: str) -> dict | str:
    try:
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{"role": "user", "content": question}],
            tools=TOOLS,
        )
    except st.GuardBlocked as blocked:
        return f"Blocked: {blocked.reason}"

    tool_call = response.choices[0].message.tool_calls[0]
    arguments = json.loads(tool_call.function.arguments)
    return get_weather(**arguments)


print(answer("What is the weather in London?"))
delivery = st.shutdown(timeout=5)
if not delivery.ok:
    raise RuntimeError(f"Trace delivery incomplete: {delivery.last_failure}")

st.init() patches an installed OpenAI SDK. The explicit decorators define the supported trace shape: @st.agent creates the root and @st.tool records the real tool duration, status, input, output, and error.

Guard evaluates tool proposals returned by the patched provider before the normal dispatch loop receives them. An audit finding records a would-block and lets the proposal continue. A block raises st.GuardBlocked.

@st.tool observes a Python function. It does not run Guard by itself. Check a direct tool call explicitly when it needs enforcement:

decision = st.guard("delete_record", {"record_id": "r_42"})
if decision.action == "block":
    raise RuntimeError(decision.reason)
delete_record("r_42")

Anthropic

Install staso[anthropic] and use a non-streaming messages.create call under the same explicit decorators. See the Anthropic quickstart.

CLI agents

Connect Claude Code or Codex without changing application code:

pip install staso
staso setup --target claude-code  # or codex

See the Claude Code quickstart, Codex quickstart, or CLI reference.

Pricing

Team starts at $39 USD per month for one unit. Each unit includes 10,000 monthly traces and 5,000 monthly Guard LLM-judge evaluations. Team includes unlimited static Guard evaluations.

Choose 1 to 50 Team units. See current pricing and limits for volume discounts and the final signed-in quote, currency, and included capacity. Spans do not add plan usage, but monthly allowances, request limits, and service rate limits still apply.

Capture boundaries

  • requested_model records the request. model records the provider-resolved ID when the response supplies one, and otherwise falls back to the request. provider records the provider identity.
  • usage_available=True means the provider returned usage, including valid zero-token values. False means the compatibility token counters are not evidence of known zero.
  • Cost is estimated by the Staso service for recognized models. Unknown usage or an unrecognized model stays unknown instead of becoming $0.
  • Five independent categories default on: request, system_prompt, tool_schema, tool_arguments, and output. Configure them with st.init(capture_<category>=...) or STASO_CAPTURE_<CATEGORY>.
  • Suppression removes governed values before SDK payload serialization. Enabled content can still be redacted by the backend before storage; these are different states.
  • The deprecated capture_messages=False fallback suppresses request and system_prompt only. Explicit category controls win.
  • Span delivery is asynchronous. Call st.flush() to wait for events accepted before that call, or st.shutdown() when the process is done. Both return a DeliveryReport; check report.ok when delivery is required. report.rejected and report.last_rejection expose local queue drops that happened during automatic decorator cleanup.
  • Guard fails open when no policy decision is available by default. Use fail_closed=True or STASO_GUARD_FAIL_CLOSED=true for calls that must block on explicit degradation.

For a warm serverless worker, flush after each invocation without stopping the shared client:

def handler(event, context):
    result = answer(event["question"])
    report = st.flush(timeout=2)
    if not report.ok:
        logger.warning("Staso delivery incomplete: %s", report.last_failure)
    return result

Calling st.init() again retires the previous client. Inspect new_client.previous_shutdown_report to verify that drain without making initialization throw by default.

Documentation

Python 3.11+ | Apache 2.0

Download files

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

Source Distribution

staso-0.5.17.tar.gz (126.4 kB view details)

Uploaded Source

Built Distribution

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

staso-0.5.17-py3-none-any.whl (160.2 kB view details)

Uploaded Python 3

File details

Details for the file staso-0.5.17.tar.gz.

File metadata

  • Download URL: staso-0.5.17.tar.gz
  • Upload date:
  • Size: 126.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for staso-0.5.17.tar.gz
Algorithm Hash digest
SHA256 d82283b392913a5d33bbb990e3213cd9f33ae762036a72f2cbc71a81b4efb5d1
MD5 80cad8bb67c7bc1cf7a89fec8a23d3cb
BLAKE2b-256 749b9765bb988fa1c560e84fb845d5ec6ea2619a103dab756c924e3917f021a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for staso-0.5.17.tar.gz:

Publisher: build_deploy_pip_registry.yml on StasoAI/sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file staso-0.5.17-py3-none-any.whl.

File metadata

  • Download URL: staso-0.5.17-py3-none-any.whl
  • Upload date:
  • Size: 160.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for staso-0.5.17-py3-none-any.whl
Algorithm Hash digest
SHA256 583cd14b47c6da565285e3fa6c6574c9de67c88e76c532ae46a8427f155badeb
MD5 e1c5f9049f9b533071aabf52c04f7e48
BLAKE2b-256 b5ebd1a1ae3351a683ea210b32b2c9ffbddc16ff46e9d710ff93c9c6fdf63c32

See more details on using hashes here.

Provenance

The following attestation bundles were made for staso-0.5.17-py3-none-any.whl:

Publisher: build_deploy_pip_registry.yml on StasoAI/sdk-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.5.20

2 files

0.5.19

2 files

0.5.18

2 files

This release

0.5.17 This release

2 files

0.5.16

2 files

0.5.15

2 files

0.5.14

2 files

0.5.13

2 files

0.5.12

2 files

0.5.11

2 files

0.5.10

2 files

0.5.9

2 files

0.5.8

2 files

0.5.7

2 files

0.5.6

2 files

0.5.5

2 files

0.5.4

2 files

0.5.3

2 files

0.5.2

2 files

0.5.1

2 files

0.5.0

2 files

0.2.0

2 files

0.1.41

2 files

0.1.40

2 files

0.1.38

2 files

0.1.37

2 files

0.1.36

2 files

0.1.35

2 files

0.1.34

2 files

0.1.33

2 files

0.1.32

2 files

0.1.31

2 files

0.1.30

2 files

0.1.28

2 files

0.1.27

2 files

0.1.25

2 files

0.1.24

2 files

0.1.21

2 files

0.1.20

2 files

0.1.19

2 files

0.1.18

2 files

0.1.17

2 files

0.1.16

2 files

0.1.15

2 files

0.1.14

2 files

0.1.13

2 files

0.1.12

2 files

0.1.10

2 files

0.1.9

2 files

0.1.2

2 files

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