Skip to main content

Python SDK for Sepurux trace recording and uploads

Project description

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)

Project details


Download files

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

Source Distribution

sepurux-0.7.0.tar.gz (26.1 kB view details)

Uploaded Source

Built Distribution

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

sepurux-0.7.0-py3-none-any.whl (20.8 kB view details)

Uploaded Python 3

File details

Details for the file sepurux-0.7.0.tar.gz.

File metadata

  • Download URL: sepurux-0.7.0.tar.gz
  • Upload date:
  • Size: 26.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sepurux-0.7.0.tar.gz
Algorithm Hash digest
SHA256 3e96ac78c37c3a8aeda4e5e8663686407ba391cf4fd969a5b95e8c39f2bc9836
MD5 c0968f42c89936b57cadfeb5e6c32358
BLAKE2b-256 01cadf79bd6118309e309a261e8f2f23e127a9062ec2705c7bba2c84c65360c1

See more details on using hashes here.

File details

Details for the file sepurux-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: sepurux-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 20.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for sepurux-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 df049e95c56ece45ff8e5fa5baa5834757b77f9a8c8221dad4d80a85da8a7ab8
MD5 4cfb3b5053cd60d03dcb32f96a2bb7f0
BLAKE2b-256 681fbe5d07648c9c027c543effc319db4d551a767139b45c1c3689915a51c7ac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page