Skip to main content

Pluggable reasoning-trace observability for LLM applications

Project description

opexia-trace

Pluggable reasoning-trace observability for LLM applications.

opexia-trace is the client SDK for the OpexIA Observability Layer. It captures reasoning-altitude spans — the decisions an agent made, the sources it used, what each step cost, and the inputs to a reliability score — and ships them to an OpexIA backend over OTLP. Unlike raw LLM logging, the unit of observation is the reasoning step, not the HTTP call.

Install

pip install opexia-trace

Quickstart

Call init() once at process startup:

from opexia.trace import init

init(
    org_id="pwc",
    workspace_id="chatpwc",
    project_id="due-diligence",
    backend_url="https://opexia.internal.example.com",
    api_key="opx_live_...",          # your workspace API key
)

With auto_instrument=True (the default), every LLM call made through litellm / anthropic / openai is now traced. No other code changes required.

The three integration patterns

Pattern A — Auto-instrument (zero code changes)

init(auto_instrument=True) monkey-patches the litellm / anthropic / openai client methods at startup. Every completion call emits a gen_ai.* span carrying the model, token usage, and computed USD cost. This is the default; you get it just by calling init().

Pattern B — the @observe decorator

Wrap any function — sync or async — to emit a reasoning span for it:

from opexia.trace import observe

@observe(reasoning_role="decomposer", node_type="decomposer", name="plan.decompose")
async def decompose(query: str) -> list[str]:
    ...

Nested @observe calls auto-parent via OpenTelemetry context — a decorated function called inside another decorated function becomes its child span, so the reasoning tree falls out of normal call structure.

Pattern C — the ReasoningTrace context manager

For explicit, structured traces — when you want to record decisions, sources, and costs by hand:

from opexia.trace import ReasoningTrace

with ReasoningTrace(name="answer.query", reasoning_role="synthesis") as trace:
    trace.record_cost(model="claude-opus-4-6", input_tokens=1200, output_tokens=400)
    trace.record_sources(used=[...], consulted=[...], dropped=[...])
    trace.record_decision(selected="opt_a", rules_fired=[...], scores={...})
    with trace.subnode(name="retrieve", node_type="retriever") as node:
        node.record_sources(...)

Framework adapters

For agent frameworks, one line instruments a whole crew:

from opexia.trace.adapters.microsoft import instrument_microsoft_agents
instrument_microsoft_agents(crew)        # Microsoft Agent Framework

from opexia.trace.adapters.reasonix import instrument_reasonix
instrument_reasonix(orchestrator)        # Reasonix orchestrator

Adapters are duck-typed — they import nothing from the framework, so they never pin you to a version.

Configuration — init() parameters

Parameter Default Meaning
org_id / workspace_id / project_id required Tenancy identity stamped on every span.
backend_url required The OpexIA backend base URL.
api_key required Workspace API key (opx_live_… / opx_test_…).
collector_endpoint http://localhost:4317 OTLP collector endpoint.
wal_path .opexia-wal/spans.jsonl Write-ahead-log path (see Durability).
auto_instrument True Patch litellm/anthropic/openai at startup.
fail_open False See "fail_open scope" in the FAQ.
sampler_rate 1.0 Fraction of traces sampled.

Durability — the write-ahead log

Spans are written to a local WAL (wal_path) before they are exported, so a process crash or an unreachable collector does not lose spans — the next init() replays any WAL left by a previous run. The WAL is why a dropped span is treated as a bug, not an expected failure mode.

Troubleshooting

  • No spans appear in the backend. Check backend_url / collector_endpoint reachability and that api_key is a live (not revoked) workspace key.
  • init() has not been called. A @observe / ReasoningTrace ran before init(). Call init() once at process startup, before any traced code.
  • Auto-instrument patched 0 clients. None of litellm/anthropic/openai are importable in the process — Pattern A has nothing to patch. Use Pattern B/C.

FAQ

Does opexia-trace import my agent framework? No. The adapters are duck-typed and import nothing from the framework or from the OpexIA backend.

What does fail_open actually cover? fail_open=True only suppresses a failure of auto-instrument registration during init() — it does NOT wrap the whole init() body. A bad collector_endpoint or a WAL-path I/O error still raises. Treat fail_open as "don't let auto-instrument break my startup," not "make init() never raise." (Tracked as deferred note B2-N5; a future release may widen the scope.)

Can I emit spans during process shutdown? No. Do not start new spans after your shutdown hook runs — a span started concurrently with the exporter shutting down can be dropped (this race exists in upstream OpenTelemetry's BatchSpanProcessor too). Finish traced work before tearing the process down. (Tracked as deferred note B2-N7.)

Is the SDK safe in production? Yes — span export is buffered and WAL-backed, and a traced function never fails because tracing failed: attribute-extraction errors are caught and recorded on the span, and the original return value passes through untouched.

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

opexia_trace-0.1.0a1.tar.gz (19.7 kB view details)

Uploaded Source

Built Distribution

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

opexia_trace-0.1.0a1-py3-none-any.whl (21.7 kB view details)

Uploaded Python 3

File details

Details for the file opexia_trace-0.1.0a1.tar.gz.

File metadata

  • Download URL: opexia_trace-0.1.0a1.tar.gz
  • Upload date:
  • Size: 19.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opexia_trace-0.1.0a1.tar.gz
Algorithm Hash digest
SHA256 a6c18d88e3056a327936d52b55d9d2bff35b2ede51cd5f366d949fc3f5f2045a
MD5 efd90e413e880b86b2964612e75ffab3
BLAKE2b-256 28f080d35c849b9896881316d43b19047510005163dc2d1e4f8bc995ab5591c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for opexia_trace-0.1.0a1.tar.gz:

Publisher: publish-opexia-trace.yml on star-56/deep_reasoning

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

File details

Details for the file opexia_trace-0.1.0a1-py3-none-any.whl.

File metadata

  • Download URL: opexia_trace-0.1.0a1-py3-none-any.whl
  • Upload date:
  • Size: 21.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for opexia_trace-0.1.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 c882cce17f5ac401f9967185d7443b1bb3e9c43d79ee94f9af2cff2604998228
MD5 f2beb7e495fdf0c5dc7f3d60abb35641
BLAKE2b-256 e08e69b9f12497859c303c59aa2bf88fc09c9c89db08730b1739689e29e38235

See more details on using hashes here.

Provenance

The following attestation bundles were made for opexia_trace-0.1.0a1-py3-none-any.whl:

Publisher: publish-opexia-trace.yml on star-56/deep_reasoning

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

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