Skip to main content

First-party OpenInference-shaped tracing for Python LLM and agent applications on Catalyst by Inference.net.

Project description

catalyst-tracing

First-party OpenInference-shaped tracing for Python LLM and agent applications running on Catalyst by Inference.net.

catalyst-tracing gives you one Python package for instrumenting common model SDKs, agent frameworks, and custom agent work. It emits OpenTelemetry spans with OpenInference-compatible attributes over OTLP/HTTP so Catalyst can display model calls, tool calls, prompts, responses, token usage, and parent-child agent flows.

This package is currently in beta. APIs may change before 1.0, but the package name and import path are intended to remain stable.

Install

Install the base tracing runtime:

pip install catalyst-tracing

Install only the integrations your application uses:

pip install 'catalyst-tracing[openai]'
pip install 'catalyst-tracing[anthropic]'
pip install 'catalyst-tracing[langchain]'
pip install 'catalyst-tracing[langgraph]'
pip install 'catalyst-tracing[langsmith]'
pip install 'catalyst-tracing[openai-agents]'
pip install 'catalyst-tracing[claude-agent-sdk]'
pip install 'catalyst-tracing[pydantic-ai]'
pip install 'catalyst-tracing[elevenlabs]'
pip install 'catalyst-tracing[livekit-agents]'

You can combine extras. For LangChain agents that are already wrapped in LangSmith decorators, install both integrations plus the provider SDKs you use:

pip install 'catalyst-tracing[openai,anthropic,langchain]'
pip install 'catalyst-tracing[openai,langchain,langsmith]'

Quick Start

Set your Catalyst endpoint and token:

export CATALYST_OTLP_ENDPOINT="https://your-catalyst-otlp-endpoint"
export CATALYST_OTLP_TOKEN="your-token"
export CATALYST_SERVICE_NAME="checkout-agent"

Initialize tracing before creating SDK clients:

from catalyst_tracing import setup
from openai import OpenAI

tracing = setup()

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Summarize this order."}],
)

tracing.shutdown()

The OpenAI call is captured as an OpenInference-shaped LLM span and exported to Catalyst through OTLP/HTTP.

What It Instruments

Integration Install extra What is captured
OpenAI openai Chat Completions, Responses, sync clients, and async clients
Anthropic anthropic Messages API calls, sync clients, and async clients
LangChain langchain Callback-manager driven chain, model, tool, and retriever spans
LangGraph langgraph Graph and node spans through the LangChain callback path
LangSmith langsmith LangSmith OpenTelemetry spans bridged into the Catalyst provider
OpenAI Agents openai-agents Agent runs plus nested OpenAI model spans
Claude Agent SDK claude-agent-sdk query() calls and yielded agent messages
Pydantic AI pydantic-ai Pydantic AI's native OpenTelemetry instrumentation
ElevenLabs Agents elevenlabs Conversation sessions, user/agent messages, and client tool calls
LiveKit Agents livekit-agents Native LiveKit OTel spans bridged into Catalyst and enriched as AGENT, LLM, TOOL, and CHAIN spans

The base package includes the tracing runtime. Extras install the upstream SDKs themselves so you can keep production environments narrow.

LangSmith Decorator Integration

Applications that already use LangSmith decorators do not need Catalyst-specific wrappers around those functions. Keep using LangSmith's @traceable decorator and initialize Catalyst once at process startup. The SDK bridges LangSmith's OpenTelemetry context into the Catalyst tracer provider, so provider spans created below a decorated function are parented under that LangSmith run.

import os

from catalyst_tracing import setup
from langsmith import Client, traceable

os.environ["LANGSMITH_TRACING"] = "true"

tracing = setup(service_name="support-agent")
client = Client()

@traceable(name="lookup_order", run_type="tool", client=client, enabled=True)
def lookup_order(order_id: str) -> str:
    return f"order {order_id} is shipped"

lookup_order("ABC-123")
client.flush()
tracing.shutdown()

When LANGSMITH_TRACING=true is set and no LangSmith OTel mode is configured, Catalyst defaults LangSmith to hybrid mode. LangSmith still receives its own traces, and Catalyst receives the OpenTelemetry spans from the same decorators. Set LANGSMITH_TRACING_MODE=otel when you want LangSmith to emit only OTel spans for this process. The SDK also enables the LangSmith OTel context flags needed by older LangSmith clients, including LANGSMITH_OTEL_ENABLED, so the active decorator span becomes the parent for nested LangChain and provider spans.

The SDK enriches LangSmith spans before export so Catalyst can render them like the rest of your agent trace:

LangSmith signal Catalyst/OpenInference attribute
run_type / langsmith.span.kind openinference.span.kind
gen_ai.prompt input.value with input.mime_type=application/json
gen_ai.completion output.value with output.mime_type=application/json
tool trace name tool.name
agent trace name agent.name
LangSmith model metadata llm.model_name, llm.provider

This also works with LangChain or LangGraph spans emitted under a LangSmith decorated root span. Catalyst captures LangChain chain/tool/retriever spans through its LangChain callback integration, captures provider spans through the provider integrations, and preserves the LangSmith decorator spans in the same trace tree.

For a LangChain agent with LangSmith tracing, the customer application should look like normal LangSmith and LangChain code:

import os

from catalyst_tracing import setup
from langchain.agents import create_agent
from langsmith import Client, traceable

os.environ["LANGSMITH_TRACING"] = "true"

tracing = setup(service_name="question-gen-agent")
langsmith_client = Client()

agent = create_agent(...)

@traceable(name="question_generation_agent", run_type="chain", client=langsmith_client)
def run_agent(payload: dict) -> dict:
    return agent.invoke(payload)

run_agent({"messages": [{"role": "user", "content": "Generate one question."}]})
langsmith_client.flush()
tracing.shutdown()

Do not add a separate customer-owned Catalyst wrapper around the decorated entry point just to make grouping work. If every model span appears as a root span, check that the process installed the langsmith extra, initialized Catalyst before invoking the agent, and did not override LangSmith's OTel mode after setup.

Public API

Most applications only need setup():

from catalyst_tracing import setup

tracing = setup(
    service_name="support-agent",
    service_version="0.4.0",
)

setup() returns a CatalystTracing handle with:

Attribute Purpose
provider OpenTelemetry TracerProvider configured for Catalyst export
tracer Tracer for manual spans
install_results Per-integration install results
shutdown() Flush and close tracing before process exit

You can also import integration installers directly:

from catalyst_tracing import setup
from catalyst_tracing.openai import install_openai

tracing = setup()
install_openai(tracing.provider)

Available entry-point modules:

Import Export
catalyst_tracing.openai install_openai
catalyst_tracing.anthropic install_anthropic
catalyst_tracing.langchain install_langchain
catalyst_tracing.langgraph install_langgraph
catalyst_tracing.langsmith install_langsmith
catalyst_tracing.openai_agents install_openai_agents
catalyst_tracing.claude_agent_sdk install_claude_agent_sdk
catalyst_tracing.pydantic_ai install_pydantic_ai
catalyst_tracing.elevenlabs install_elevenlabs
catalyst_tracing.livekit_agents install_livekit_agents

Manual Agent Spans

Use manual_span() when work does not go through a supported SDK, such as a custom router, planner, evaluator, provider-failover step, or tool executor. It accepts OpenInference span kinds, provider-shaped usage payloads, structured inputs/outputs, and OTel-safe custom attributes.

from catalyst_tracing import SpanKindValues, manual_span, setup

tracing = setup()

with manual_span(
    tracing.tracer,
    name="question_generation/bloom",
    span_kind=SpanKindValues.CHAIN,
    system="fireworks",
    input={"template_id": "bloom", "total_questions": 10},
    model="accounts/fireworks/models/gpt-oss-120b",
    metadata={"deck_id": "deck_123"},
    tags=["question-gen-agent", "template:bloom"],
) as span:
    result = run_question_generation()
    span.set_output({"question_count": len(result.questions)})
    span.record_usage(result.usage)

tracing.shutdown()

agent_span() remains available as a focused convenience wrapper for AGENT spans:

from catalyst_tracing import agent_span, setup

tracing = setup()

with agent_span(
    tracing.tracer,
    agent_id="refund-review-agent",
    agent_name="Refund Review Agent",
    span_name="refund-review.run",
    session_id="conversation-1842",
    agent_role="refunds",
    system="internal",
) as span:
    span.set_input("Review refund request #1842")
    decision = run_refund_review()
    span.set_output(decision.summary)
    span.record_tokens(prompt=820, completion=160)

tracing.shutdown()

agent_id becomes the agent.id span attribute. Use a stable value that survives display-name changes so Catalyst can group executions correctly in the agent dashboard. agent_name is optional and becomes agent.name when you want a human-readable display label. session_id is optional and should identify one conversation, not the whole process. Any child spans created inside the context automatically parent under the agent span and supported SDK wrappers copy the active agent.id and optional agent.name / agent.role onto their child spans.

When you already have an active span, reusable helpers are exported for common manual instrumentation tasks:

from catalyst_tracing import record_span_usage, set_span_attributes

record_span_usage(span, {"prompt_tokens": "820", "completion_tokens": 160})
set_span_attributes(span, {"metadata": {"deck_id": "deck_123"}})

Configuration

You can configure tracing with keyword arguments or environment variables.

Option Environment variable Default
endpoint CATALYST_OTLP_ENDPOINT http://localhost:8799
token CATALYST_OTLP_TOKEN unset
service_name CATALYST_SERVICE_NAME generated catalyst-app-* name
service_version CATALYST_SERVICE_VERSION 0.0.6
debug CATALYST_DEBUG false
batching none "batch"

Legacy OTLP_ENDPOINT, OTLP_INGEST_TOKEN, and SERVICE_NAME variables are also accepted for compatibility.

Span Shape

Spans use OpenInference-style semantic attributes so LLM-aware viewers can understand them without custom adapters:

Attribute family Examples
Span kind openinference.span.kind
Inputs and outputs input.value, output.value
Messages llm.input_messages.*, llm.output_messages.*
Model metadata llm.model_name, llm.invocation_parameters
Token counts llm.token_count.prompt, llm.token_count.completion, llm.token_count.total
Provider/system gen_ai.system

Constants are exported for custom spans:

from catalyst_tracing import Attr, SpanKindValues

span.set_attribute(Attr.SPAN_KIND, SpanKindValues.LLM.value)
span.set_attribute(Attr.MODEL_NAME, "gpt-4o-mini")

Error Handling

The package raises typed errors for misuse and returns structured install results for optional integrations:

from catalyst_tracing import CatalystTracingError, InvalidTracerProviderError
from catalyst_tracing.openai import install_openai

try:
    result = install_openai(provider)
except InvalidTracerProviderError as exc:
    print(exc.code)
except CatalystTracingError:
    raise

Each installer returns an InstrumentResult with:

Field Meaning
name Integration name
installed Whether instrumentation was installed
code Stable status code such as INSTALLED or SDK_NOT_INSTALLED
reason Human-readable detail when installation is skipped

Package Names

The primary package is catalyst-tracing and the primary import path is catalyst_tracing.

Inference also publishes inference-catalyst-tracing as a company-qualified install name. It depends on this package and re-exports the same public API from the inference_catalyst_tracing import path.

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

catalyst_tracing-0.0.19.tar.gz (46.8 kB view details)

Uploaded Source

Built Distribution

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

catalyst_tracing-0.0.19-py3-none-any.whl (67.2 kB view details)

Uploaded Python 3

File details

Details for the file catalyst_tracing-0.0.19.tar.gz.

File metadata

  • Download URL: catalyst_tracing-0.0.19.tar.gz
  • Upload date:
  • Size: 46.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for catalyst_tracing-0.0.19.tar.gz
Algorithm Hash digest
SHA256 1932bc52223426833fa9b00922e1bcd3aba1108242e4a74ab59f6db8202c82b9
MD5 38cf14121e0349e92fcb2fd38b8cd2f4
BLAKE2b-256 7cd2327faf141a44ed2eb583dce1411eda4a26ef57b5e5cc7c0080266cc75a95

See more details on using hashes here.

File details

Details for the file catalyst_tracing-0.0.19-py3-none-any.whl.

File metadata

  • Download URL: catalyst_tracing-0.0.19-py3-none-any.whl
  • Upload date:
  • Size: 67.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for catalyst_tracing-0.0.19-py3-none-any.whl
Algorithm Hash digest
SHA256 8a95269d41c8c3495ccff1d9c4b86fef8f2eff75854916a4cf0d09b96b1c8eac
MD5 c16550d838ed3ed3e77a5c6218b94993
BLAKE2b-256 67379f02c8acc8e9ce8bee04cf876a411f5f5499ac643dfe44bfceb741dd2ccf

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