Staso Docs
Python SDK

SDK setup

Install

pip install "staso[openai]"
# or
pip install "staso[anthropic]"

The supported launch path requires Python 3.11 or later and uses non-streaming OpenAI Chat Completions or Anthropic Messages. Native streaming remains beta and outside the supported launch configuration.

Initialize

import staso as st

st.init(api_key="ak_...", agent_name="support-agent")

You can provide the credentials through environment variables:

export STASO_API_KEY=ak_...
export STASO_AGENT_NAME=support-agent

For onboarding, set STASO_ENVIRONMENT and STASO_WORKSPACE_SLUG to the selected dashboard workspace. Call st.init() before constructing OpenAI or Anthropic clients so installed native SDKs are patched. Set STASO_AUTO_PATCH=false only when you plan to patch manually. st.flush() and st.shutdown() report delivery and ingest acceptance; the first-trace milestone should wait for dashboard/backend trace query visibility.

Signature

st.init(
    *,
    api_key: str | None = None,
    agent_name: str | None = None,
    agent_version: str | None = None,
    base_url: str | None = None,
    batch_size: int = 100,
    flush_interval: float = 0.5,
    max_queue_size: int = 10_000,
    enabled: bool = True,
    debug: bool | None = None,
    environment: str | None = None,
    workspace_slug: str | None = None,
    capture_messages: bool | None = None,
    capture_request: bool | None = None,
    capture_system_prompt: bool | None = None,
    capture_tool_schema: bool | None = None,
    capture_tool_arguments: bool | None = None,
    capture_output: bool | None = None,
    capture_git: bool = True,
) -> Client
NameDefaultPurpose
api_keySTASO_API_KEYRequired Staso API key.
agent_nameSTASO_AGENT_NAMERequired process-level agent name.
agent_versionSTASO_AGENT_VERSION or ""Free-form version label on emitted spans.
base_urlSTASO_BASE_URL or https://api.staso.aiStaso service endpoint override.
batch_size100Maximum spans grouped before a flush.
flush_interval0.5Seconds between background flush attempts.
max_queue_size10_000In-memory queue limit; spans beyond it are rejected locally and surfaced in delivery reports.
enabledTrueFalse makes tracing a no-op.
debugSTASO_DEBUG or FalseSDK debug logging.
environmentSTASO_ENVIRONMENT or defaultEnvironment label.
workspace_slugSTASO_WORKSPACE_SLUG or defaultTarget workspace.
capture_messagesNoneDeprecated compatibility control for request messages and system prompts.
capture_requestNoneOverride request-content capture.
capture_system_promptNoneOverride standalone system-prompt capture.
capture_tool_schemaNoneOverride tool and structured-response schema capture.
capture_tool_argumentsNoneOverride proposed and executed tool-argument capture.
capture_outputNoneOverride assistant and tool-result capture.
capture_gitTrueAttempt to attach detected VCS metadata to roots.

See environment variables for the full mapping.

Define the supported root and tools

@st.tool
def search(query: str) -> list[str]:
    return index.search(query)


@st.agent
def answer(question: str) -> str:
    results = search(question)
    return summarize(results)

Use explicit decorators even though st.init() patches installed OpenAI and Anthropic SDKs. The decorators define the supported agent root and actual tool execution boundary.

Capture suppression

All five capture categories default to enabled:

CategoryControls
requestAgent arguments, user/request messages, request-derived labels, and caller metadata.
system_promptOpenAI system/developer messages and Anthropic system.
tool_schemaTool definitions and structured-response schemas.
tool_argumentsProposed or executed tool arguments, including arguments sent for Guard evaluation.
outputAssistant content, tool results, return values, and Guard reason prose.

Configure categories independently:

st.init(
    api_key="ak_...",
    agent_name="support-agent",
    capture_request=False,
    capture_tool_arguments=False,
    capture_output=True,
)

Resolution is deterministic: an explicit capture_<category> argument wins, then its STASO_CAPTURE_<CATEGORY> environment variable, then the deprecated capture_messages argument or STASO_CAPTURE_MESSAGES for request and system_prompt only, then True. An explicit category setting always wins over the compatibility control.

Suppression removes the governed value before SDK payload serialization. It does not add hashes, excerpts, lengths, or placeholders. Enabled content may be redacted by the backend before storage; redacted is a backend storage state, not a setting or state emitted by this SDK.

Guard respects the same controls before sending an evaluation request. A rule that needs suppressed arguments, schemas, or history cannot use that missing evidence to produce a finding. See Guard evidence and capture.

When a value crosses categories, each relevant category must be enabled. For example, tool-call arguments embedded in an assistant response require both tool_arguments and output.

Use decorator controls for a function payload:

@st.tool(capture_input=False, capture_output=False)
def read_secret(secret_id: str) -> str:
    return vault.read(secret_id)

Decorator capture is the global category setting and its local flag. With input capture disabled, the decorator does not build an argument payload.

Delivery lifecycle

report = st.shutdown(timeout=5)
if not report.ok:
    raise RuntimeError(f"Trace delivery incomplete: {report.last_failure}")

Call st.shutdown() when a short-lived process is done. It stops the client, attempts to drain within the timeout, and returns a DeliveryReport. report.ok is false for failed or pending delivery, a timeout, or a local queue rejection; inspect last_failure, rejected, and last_rejection for safe failure categories.

Use st.flush(timeout=5) in a warm serverless worker. It waits for events accepted before the call and keeps the client ready for the next invocation.

Calling st.init() again retires the previous client and attempts its bounded drain. Inspect new_client.previous_shutdown_report; it is None on the first initialization.

Next