Skip to main content

Sepurux Python SDK

PyPI Python CI

Record agent traces, run reliability campaigns, and instrument OpenAI or LangChain workflows — all from Python.

Install

pip install -e sdk

Quick start

import os

from sepurux import SepuruxClient

os.environ["SEPURUX_API_BASE_URL"] = "http://localhost:8000"
os.environ["SEPURUX_API_KEY"] = "sepurux-dev-key"
os.environ["SEPURUX_PROJECT_ID"] = "22222222-2222-2222-2222-222222222222"

with SepuruxClient.from_env() as client:
    with client.trace("example_task", {"user_id": "u-123"}) as trace:
        trace.model_step("plan", {"goal": "create issue"}, output={"ok": True})
        trace.tool_call("jira.create_issue(commit)", {"summary": "SDK test"})
        trace.tool_result("jira.create_issue(commit)", {"issue_id": "OPS-123"})

    print("trace_id:", trace.trace_id)

This is the intended ergonomic path:

  • SepuruxClient.from_env() reads SEPURUX_API_BASE_URL, SEPURUX_API_KEY, and SEPURUX_PROJECT_ID
  • client.trace(...) records and uploads automatically on exit
  • trace.trace_id and trace.run_id are available after the context closes

LangSmith-style ergonomics

Auto-upload trace context

from sepurux import SepuruxClient

client = SepuruxClient.from_env()

with client.trace(
    "checkout_refund",
    {"ticket_id": "t-123"},
    campaign_id="refund_reliability",
    mutation_pack="sepurux.core.reliability",
) as trace:
    trace.model_step("triage", {"text": "Refund the duplicate charge"})
    trace.tool_call("payments.refund", {"payment_id": "pay_123", "amount": 4200})
    trace.tool_result("payments.refund", {"refund_id": "rf_123", "status": "queued"})

print(trace.trace_id)
print(trace.run_id)

@traceable decorator

Works with both sync and async def functions:

from sepurux import SepuruxClient

client = SepuruxClient.from_env()

# Sync function
@client.traceable(campaign_id="refund_reliability")
def score_refund_risk(amount: int, currency: str) -> dict:
    return {"risk": "medium", "approve": amount < 10000, "currency": currency}

result = score_refund_risk(4200, "usd")

# Async function — same decorator, awaitable result
@client.traceable(campaign_id="refund_reliability")
async def fetch_risk_score(payment_id: str) -> dict:
    data = await some_async_api(payment_id)
    return {"risk": data["score"]}

result = await fetch_risk_score("pay_123")

Global configuration

from sepurux import configure, trace, traceable

configure()

@traceable()
def classify_ticket(text: str) -> dict:
    return {"label": "bug", "priority": "p2"}

with trace("support_session", {"channel": "email"}) as rec:
    rec.model_step("classify", {"text": "checkout timed out"})

API

SepuruxClient

SepuruxClient(base_url, api_key=None, project_id=None, timeout=30, sdk_header=None)
SepuruxClient.from_env(...)

The SDK automatically sends X-Sepurux-SDK: py/<version> on requests. Use sdk_header only if you need to override it manually.

Methods:

  • trace(task_name, task_input=None, campaign_id=None, mutation_pack=None) -> recorder
  • traceable(name=None, campaign_id=None, mutation_pack=None) -> decorator
  • upload_trace(trace: dict) -> str
  • list_traces(limit=50, offset=0) -> list[dict]
  • get_trace(trace_id, include_payload=False) -> dict
  • get_trace_timeline(trace_id) -> list[dict]
  • bootstrap_trace(trace_id) -> dict
  • create_campaign(name, mutation_set, eval_set, mutation_pack_id=None) -> str
  • preflight_run_inputs(trace_id, campaign_id) -> None
  • start_run(trace_id, campaign_id, thresholds=None, preflight=False) -> str
  • run_pack(campaign_id, mutation_pack) -> str
  • get_run(run_id) -> dict
  • get_ci_run(run_id) -> dict
  • get_campaign_failures(campaign_id, run_id=None) -> list[dict]
  • get_campaign_reliability(campaign_id, run_id=None) -> dict

TraceBuilder

TraceBuilder outputs backend-compatible traces:

{
  "trace_version": "0.1",
  "source": "sdk",
  "task": {"name": "...", "input": {}},
  "events": []
}

Recommended tracing flow

Use client.trace(...), client.traceable(...), or the global trace(...) / traceable(...) helpers as the default integration path. Legacy helpers like sepurux_trace(...) and record_trace(...) remain available for compatibility, but they are deprecated and no longer the documented path.

Server-side pack execution

result = client.run_campaign("demo_campaign", mutation_pack="core.reliability")
print(result["run_id"])
print(result["reliability_score"])
print([failure["type"] for failure in result["failures"]])

Integrations

OpenAI

instrument_openai wraps any openai.OpenAI (or AsyncOpenAI) client and automatically records every chat.completions.create call as an llm_call event. Tool calls present in the response are also recorded. No manual instrumentation required.

pip install sepurux openai
import openai
from sepurux import SepuruxClient
from sepurux.integrations.openai import instrument_openai

client = SepuruxClient.from_env()
openai_client = openai.OpenAI()

with client.trace(
    "customer_refund_flow",
    {"ticket_id": "t-101"},
    campaign_id=os.environ["SEPURUX_CAMPAIGN_ID"],
) as trace:
    ai = instrument_openai(openai_client, recorder=trace)
    response = ai.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Classify this support ticket"}],
    )

print(trace.trace_id)
print(trace.run_id)

What gets recorded automatically:

  • llm_call event with model name, messages input, full response output, and latency
  • tool_call events for any function calls returned by the model
  • failure event if the API call raises an exception

For async usage, call await ai.chat.completions.acreate(...) — the wrapper detects the async path automatically.

LangChain

SepuruxCallbackHandler automatically records LLM calls, tool calls, and agent outputs from any LangChain chain or agent. Requires langchain-core:

pip install sepurux langchain-core
import os
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from sepurux.integrations.langchain import SepuruxCallbackHandler

handler = SepuruxCallbackHandler(
    "customer_refund_flow",
    {"ticket_id": "t-101"},
    campaign_id=os.environ["SEPURUX_CAMPAIGN_ID"],
)

# Works with chains, agents, or any LangChain runnable
result = agent_executor.invoke(
    {"input": "Process refund for ticket t-101"},
    config={"callbacks": [handler]},
)

# Upload trace + start reliability run
handler.finish()
print(handler.trace_id)
print(handler.run_id)

Or use it as a context manager — finish() is called automatically on exit:

with SepuruxCallbackHandler("refund_flow", campaign_id="...") as handler:
    result = chain.invoke(inputs, config={"callbacks": [handler]})

print(handler.trace_id)

What gets recorded automatically:

  • LLM calls with model name, prompt input, generated output, and latency
  • Tool calls with name and parsed arguments
  • Tool results
  • Agent final output

Optional environment variables:

  • SEPURUX_API_BASE_URL (default http://localhost:8000)
  • SEPURUX_UI_BASE_URL (default http://localhost:3000)
  • SEPURUX_API_KEY
  • SEPURUX_PROJECT_ID
  • SEPURUX_CAMPAIGN_ID (if provided, script starts a run)

Metadata

Release files for sepurux 0.7.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 sepurux 0.7.0
File Size Uploaded Provenance
sepurux-0.7.0.tar.gz 26.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sepurux 0.7.0
File Interpreter ABI Platform
sepurux-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 46.9 kB

Release files / sepurux-0.7.0.tar.gz

Download URL sepurux-0.7.0.tar.gz
Size 26.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3e96ac78c37c3a8aeda4e5e8663686407ba391cf4fd969a5b95e8c39f2bc9836
BLAKE2b-256 checksum
How to use checksums
01cadf79bd6118309e309a261e8f2f23e127a9062ec2705c7bba2c84c65360c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / sepurux-0.7.0-py3-none-any.whl

Download URL sepurux-0.7.0-py3-none-any.whl
Size 20.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
df049e95c56ece45ff8e5fa5baa5834757b77f9a8c8221dad4d80a85da8a7ab8
BLAKE2b-256 checksum
How to use checksums
681fbe5d07648c9c027c543effc319db4d551a767139b45c1c3689915a51c7ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Security for sepurux 0.7.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