Skip to content
XLinkedIn
Sign Up →
Ask AI

Python SDK

The Kelet Python SDK instruments your agent code to send traces and signals. It wraps LLM calls with OpenTelemetry-compatible spans, handles session context automatically, and exposes a signal() API for capturing user feedback. A single kelet.configure() call at startup is all most frameworks need.

pip install kelet  |  Requires Python ≥3.10

bash pip install kelet

Two keys — never mix them:

  • Secret key (sk_...): server-only. Use this in kelet.configure(). Never expose it in frontend code.
  • Publishable key (pk_...): frontend-safe, for the React SDK only. Cannot send traces.

Get both from Settings → API Keys in the console.

Call once at startup, before any agent code runs. Kelet auto-configures supported integrations whether it creates the global TracerProvider or attaches to one that already exists.

import kelet
kelet.configure(
api_key="...", # or set KELET_API_KEY env var
project="my-agent", # required; can override per session with agentic_session(project=...)
)
ParameterTypeDescription
api_keystrAPI key. Defaults to KELET_API_KEY env var
projectstrRequired. Project name. Set here or via KELET_PROJECT env var.
base_urlstrAPI URL. Defaults to KELET_API_URL env var
auto_instrumentboolAuto-configure detected integrations. Default True
span_processorSpanProcessorOptional. Use this processor instead of Kelet’s default (for wrapping/filtering)
additional_span_processorsSequence[SpanProcessor]Optional. Extra processors to attach when creating a new TracerProvider
strictboolOptional. If True, raise when credentials are missing. Default False (log warning and disable telemetry)

Supported integrations: pydantic-ai, Anthropic SDK, OpenAI SDK, LangChain/LangGraph, LiteLLM, and Google ADK (OpenInference instrumentation preferred, falls back to ADK’s native OTEL spans).

Install extras to pick up instrumentation: kelet[anthropic], kelet[openai], kelet[langchain], kelet[google-adk], or kelet[all] for everything.

If another tool (logfire, custom TracerProvider) owns the global provider, configure() attaches to it automatically. For setups where you build the provider yourself, use create_kelet_processor():

import logfire
import kelet
logfire.configure(additional_span_processors=[kelet.create_kelet_processor()])
logfire.instrument_pydantic_ai()
kelet.configure() # sets config for signal() + auto-instrumentation

Groups all LLM calls and tool uses that belong to one unit of work. Required when you own the orchestration loop. Skip for pydantic-ai, LangChain, or LangGraph — they set sessions automatically.

Works as both a context manager and a decorator (sync and async).

Context manager:

async with kelet.agentic_session(session_id="abc123", user_id="user-1"):
result = await agent.run(...)

Decorator:

@kelet.agentic_session(session_id="abc123")
async def handle_request():
return await agent.run(...)
ParameterTypeDescription
session_idstrRequired. Unique ID for this unit of work
user_idstrOptional. Associates the session with a user
projectstrOptional. Overrides the project set in configure(). Propagates via W3C baggage
**kwargsAnyOptional. Extra metadata stamped as metadata.{key} on every span in the session

Streaming: wrap the entire generator body, including the final sentinel. Trailing spans are silently lost if the session exits before the stream finishes.

async def stream_response(session_id: str):
async with kelet.agentic_session(session_id=session_id):
async for chunk in llm.stream(...):
yield chunk

Names an agent within a session for multi-agent attribution. Use when multiple agents run in one session, or when your framework doesn’t expose agent names (pydantic-ai does; raw OpenAI/Anthropic SDK calls don’t). Creates an explicit OTEL span (gen_ai.operation.name=invoke_agent) — all LLM calls inside become children of that span.

Works as a sync/async context manager and as a decorator.

async with kelet.agent(name="retriever"):
docs = await fetch_docs(query)
@kelet.agent(name="responder")
async def respond(question):
return await anthropic_client.messages.create(...)
ParameterTypeDescription
namestrRequired. Agent name for attribution

Sends a signal. Must be awaited. Call inside agentic_session() — session ID resolves from context automatically.

await kelet.signal(
kind=kelet.SignalKind.FEEDBACK,
source=kelet.SignalSource.HUMAN,
trigger_name="user-vote",
score=1.0,
)
ParameterTypeDescription
kindSignalKindFEEDBACK, EDIT, EVENT, METRIC, or ARBITRARY
sourceSignalSourceHUMAN, LABEL, or SYNTHETIC
trigger_namestrOptional. Use source-action format: user-vote, user-edit
scorefloatOptional. 0.0–1.0. For votes: 1.0 = positive, 0.0 = negative
valueAnyOptional. Feedback text, diff, or any JSON-serializable payload
confidencefloatOptional. 0.0–1.0. How confident the source is in the signal
metadatadict[str, Any]Optional. Arbitrary key/value payload attached to the signal
timestampdatetimeOptional. Event timestamp. Defaults to “now” server-side
session_idstrOptional. Resolved from context if omitted
trace_idstrOptional. Resolved from the active span if omitted
raise_on_failureboolRe-raise transport/HTTP errors after retries. Default False

Transport and HTTP errors are retried with exponential backoff (3 attempts). By default, failures after the final attempt are logged via logging and swallowed — signal() is a telemetry call and won’t crash your code path. Pass raise_on_failure=True to opt into re-raising after retries are exhausted. Validation errors (bad score / confidence ranges, missing identifier) always raise.

Flushes any pending spans and releases SDK resources. Registered automatically via atexit, so most apps never need to call it directly. Use it manually before a hard os._exit(0) or in tests that need to force a drain.

kelet.shutdown()

Errors from individual processors are logged and swallowed (best-effort).

kelet.get_session_id() # current session ID
kelet.get_trace_id() # current trace ID from active span
kelet.get_user_id() # current user ID
kelet.get_agent_name() # current agent name (set by kelet.agent())
kelet.get_metadata_kwargs() # metadata kwargs dict (empty if unset)

Returns None (or {} for get_metadata_kwargs) if called outside agentic_session() / agent().

VariableDescription
KELET_API_KEYAPI key (required if not passed to configure())
KELET_PROJECTRequired project name. SDK throws at startup if missing.
KELET_API_URLAPI base URL