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.0a2.tar.gz (20.0 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.0a2-py3-none-any.whl (21.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: opexia_trace-0.1.0a2.tar.gz
  • Upload date:
  • Size: 20.0 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.0a2.tar.gz
Algorithm Hash digest
SHA256 02e03e5ef189712bc719d80cf72c8fde72c354c0408435657ffe57f882604bca
MD5 2f661e6ff5d20576fedc62fa1ea1822f
BLAKE2b-256 1abc398cba04f84a2562e41bd148385546331da824b7e0847b5f61f96901da1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for opexia_trace-0.1.0a2.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.0a2-py3-none-any.whl.

File metadata

  • Download URL: opexia_trace-0.1.0a2-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.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 2663e491f2523c93b44e691f9493a0943c582be9968397e936cac999f32caeee
MD5 9daeb23af36f95f9a47a614230cc325c
BLAKE2b-256 0f6537d81fc804ef68aea343a1922e3f2d30a524cd719070578271992b196322

See more details on using hashes here.

Provenance

The following attestation bundles were made for opexia_trace-0.1.0a2-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