Skip to content
Pyrula
Pre-release: the packages are not on PyPI yet, so pip install does not resolve. Build from source to try it today.

Logfire and other OTLP backends

A Pyrula runtime emits OpenTelemetry spans for every turn, model call, tool call and durable step (Observability). configure() sends them to any backend that accepts OTLP over HTTP. configure_langfuse, configure_langsmith and configure_datadog are shortcuts that fill in the endpoint and authentication for those three; for any other backend, Logfire included, you give configure() the endpoint and headers yourself.

There is no Logfire shortcut. Take the OTLP endpoint and the write token from Logfire’s own documentation; this page does not carry them, and none of its snippets has been sent to Logfire.

Install the extra: pip install "pyrula[agents,otel]". Call configure() once, before the worker starts.

from pyrula.agents.observability import configure
configure(
service_name="invoice-agent",
endpoint="https://otlp.example.com", # the OTLP/HTTP base URL; /v1/traces is appended
headers={"Authorization": "write-token-from-your-backend"},
metrics=False, # leave True if the backend also takes metrics
capture_content=False, # True records prompts and completions on spans
)

The same through the standard variables, with no arguments in code:

Terminal window
export OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.example.com
export OTEL_EXPORTER_OTLP_HEADERS="authorization=write-token-from-your-backend"
  • OTLP over HTTP only. The exporter is the http/protobuf one. A backend that offers only gRPC cannot be reached this way; put an OpenTelemetry Collector between them.
  • Content is off unless you turn it on. Prompts, completions and tool arguments reach the backend only with capture_content=True or OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT. What is captured is secret-redacted and cut at 32 KB first (Prompt and completion content).
  • Metrics are on by default (gen_ai.client.token.usage, gen_ai.client.operation.duration). Pass metrics=False for a backend that ingests traces only.

When the app already sets up OpenTelemetry

Section titled “When the app already sets up OpenTelemetry”

If your application registers a tracer provider before Pyrula starts, do not call configure(): Pyrula’s spans go through the global provider and arrive wherever it exports (Setup). Logfire’s SDK is built on OpenTelemetry; if logfire.configure() registers the global provider in your version (confirm in its documentation), an app that uses Logfire makes that call and none from Pyrula.

import logfire
logfire.configure() # Logfire's own setup; Pyrula's spans use the provider it registers
# no pyrula.agents.observability.configure() call

Which of the two you want depends on who owns the provider. A Pyrula worker started with configure() owns it; an app that already has one keeps it.

BackendCall
Langfuseconfigure_langfuse() reads LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_HOST; content on, metrics off
LangSmithconfigure_langsmith() reads LANGSMITH_API_KEY and LANGSMITH_PROJECT
Datadogconfigure_datadog() exports to the local Agent’s OTLP intake
Logfire or any other OTLP/HTTP backendconfigure(endpoint=..., headers=...) or the OTEL variables
Your own spans on the consoleconfigure(console=True)

Pointing this exporter at Pyrula Cloud’s intake is possible and is usually wrong for a Pyrula runtime: the runtime already reports its runs to Cloud through its connector, and importing the same work as traces would count each run twice. Traces carrying a Pyrula run id are skipped for that reason. The Cloud intake is for apps that have OpenTelemetry and no Pyrula runtime; see Observe-only frameworks.

View this page as Markdown