API reference

API reference

Everything in import tracely_sdk as tracely. The default path is automatic — init() plus trace()/@observe. Span helpers (the manual escape hatch) are context managers (with … as span:); annotators take a span.

init(...)

tracely.init(endpoint="http://localhost:8000", api_key="tracely_dev_key",
             service_name="agent", env="prod", instrument="auto") -> Tracer

Configure the OTLP/HTTP exporter pointing at Tracely, register the context-stamping span processor, and activate auto-instrumentors. Call once at startup; idempotent. env (prod | staging | ci | dev) is stamped on every span — the gating axis. instrument"auto" (activate every importable provider instrumentor) · a list like ["openai", "anthropic", "litellm"] · False (export only). If you skip init, the first span call initializes with defaults.

Automatic instrumentation

trace(agent=None, *, conversation=None, turn=None, user=None, trace_name=None, env=None, **metadata)

A run context — a context manager or (sync/async) decorator. Sets tracely.* run hints once; a span processor stamps them onto every span started inside (auto-instrumentor spans included), so agent/conversation/turn/user/trace_name/env + metadata flow down with no per-span code. Sets context only (opens no span); nested trace()s merge over the enclosing one.

observe(fn=None, *, name=None, as_type="span", capture_input=True, capture_output=True)

Decorator (@observe or @observe(...)) that turns any sync/async function into a span: args → tracely.input, return → tracely.output, latency, and exceptions → level=ERROR, captured automatically and auto-nested via OTel context. as_type (span | generation | agent | tool | chain | retriever | embedding | guardrail | …) → tracely.observation.type.

run_in_thread(fn, *args, **kwargs)Thread

Run fn on a new thread that inherits the current span + trace() context (auto-nesting is in-process), so spans it creates nest correctly. Returns the started thread; join() it and read .result (or .exc).

tracely_sdk.openai / tracely_sdk.anthropic — non-patching drop-ins (R13)

from tracely_sdk.openai import OpenAI, AsyncOpenAI, wrap_openai, openai (and the identical tracely_sdk.anthropic surface: Anthropic, AsyncAnthropic, wrap_anthropic, anthropic). wrap_openai(client) / wrap_anthropic(client) trace a client instance (no global patching); OpenAI(...)/Anthropic(...) are pre-wrapped constructors; the openai/anthropic proxies mirror the module with traced constructors. Captures model · messages · output · usage · tool calls for non-streaming sync/async calls.

Span context managers

Each opens a span of the given observation type and yields the OpenTelemetry Span.

agent(slug, *, version=None, run_id=None, role=None, conversation=None, turn=None, user=None, trace_name=None, handoff_from=None, edge="delegate")AGENT

The run root. Sets tracely.agent.id/.version/.run_id/.role, tracely.env; conversationtracely.conversation.id + session.id (threads turns); turntracely.turn.index; usertracely.user.id; trace_nametracely.trace.name. handoff_from records a delegation edge (caller → this agent, with edge.type = edge) — open the sub-agent inside its caller’s span.

llm(model, *, agent=None, temperature=None, top_p=None, max_tokens=None, frequency_penalty=None, presence_penalty=None, seed=None, tool_calls=None, metadata=None)GENERATION

A model call. Sets gen_ai.request.model + each provided sampling param as gen_ai.request.*. tool_calls (a list of names) → tracely.tool_calls (tools the model requested). metadata (a dict) → tracely.metadata.*.

tool(name, *, agent=None)TOOL

A tool / function execution. Sets gen_ai.operation.name=execute_tool, gen_ai.tool.name.

thinking(name="thinking", *, agent=None, model=None)THINKING

Reasoning as its own span. Optional model records which model produced it.

retriever(name="retrieve", *, agent=None)RETRIEVER

A retrieval step. Query in set_io(input=...), hits in set_io(output=...).

embedding(model, *, agent=None)EMBEDDING

An embedding call. Sets gen_ai.request.model; record tokens with set_usage(input_tokens=...).

guardrail(name="guardrail", *, agent=None)GUARDRAIL

A safety / policy check. Verdict in set_io(output={"action": "allow" | "block", ...}).

chain(name, *, agent=None)CHAIN

A grouping span (a named sub-pipeline, e.g. a RAG pipeline). Nest other spans inside it.

turn(turn_id, *, index=None) · step(name, *, step_id=None)

A turn marker (tracely.turn.id/.index) and a generic step (tracely.step.name/.id).

Annotators

CallEffect
set_io(span, *, input=None, output=None)tracely.input / tracely.output (objects JSON-encoded).
set_usage(span, *, input_tokens=None, output_tokens=None, thinking_tokens=None)gen_ai.usage.input_tokens / output_tokens / reasoning_tokens.
set_metadata(span, **kv)tracely.metadata.<key> — arbitrary tags (scalars kept; others JSON-encoded).
error(span, message="")Marks the span StatusCode.ERRORlevel=ERROR. The failure signal.
flush()Force-flush the OTLP exporter — call before the process exits.

Hermetic replay

call_tool(name, fn, *, args=None, agent=None), call_llm(model, fn, *, input=None, usage=None, agent=None), with fixtures(bundle): …, fixture(kind, name), and the ToolError exception — see Hermetic replay.

What Tracely reads

Beyond standard gen_ai.* / OpenInference attributes, these tracely.* hints become indexed columns on the span row:

tracely.agent.id · .version · .role · tracely.user.id · tracely.trace.name · tracely.conversation.id · tracely.turn.id / .index · tracely.step.id / .name · tracely.observation.type · tracely.tool_calls · tracely.handoff.caller_agent_id / .callee_agent_id · tracely.edge.type · the gen_ai.request.* sampling params · tracely.env.

Agent slug + version are auto-registered into the Postgres registry on ingest. Input/output are stored in dedicated columns (and shown in Input/Output tabs), so they’re excluded from the attributes list to avoid duplication.