Kelet SDK - OpenTelemetry integration for AI observability
Project description
Automated Root Cause Analysis for AI Agents
Agent failures take weeks to diagnose manually. Kelet runs 24/7 deep diagnosis and suggests targeted fixes.
Kelet analyzes production failures 24/7. Each trace takes 15-25 minutes to debug manually—finding patterns requires analyzing hundreds of traces. That's weeks of engineering time per root cause. Kelet does this automatically, surfacing issues like data imbalance, concept drift, prompt poisoning, and model laziness hidden in production noise.
What Kelet Does
Kelet runs 24/7 analyzing every production trace:
- Captures every interaction, user signal, and failure context automatically
- Analyzes hundreds of failures in parallel to detect repeatable patterns
- Identifies root causes (data issues, prompt problems, model behavior)
- Delivers targeted fixes, not just dashboards
Unlike observability tools that show you data, Kelet analyzes it and tells you what to fix.
Not magic: Kelet is in alpha. Won't catch everything yet, needs your guidance sometimes. But it's already doing analysis that would take weeks manually.
Three lines of code to start.
Installation
Using uv (recommended):
uv add kelet
Or using pip:
pip install kelet
Set your API key:
export KELET_API_KEY=your_api_key
export KELET_PROJECT=production # Required — create a project at console.kelet.ai
Or configure in code:
kelet.configure(
api_key="your_api_key",
project="production" # Groups traces by project/environment
)
Quick Start
import kelet
kelet.configure() # Auto-instruments pydantic-ai, Anthropic, OpenAI, LangChain/LangGraph, and LiteLLM; captures Google ADK OTEL spans
# Your agent code works as-is - instrumentation is automatic
result = await agent.run("Book a flight to NYC")
# Optionally capture user feedback
await kelet.signal(
kind=kelet.SignalKind.FEEDBACK,
source=kelet.SignalSource.HUMAN,
score=0.0, # User unhappy? Kelet analyzes why.
# Best-effort by default: request failures warn and return.
# Pass raise_on_failure=True if you want to surface them.
)
That's it. Kelet now runs 24/7 analyzing every trace, clustering failure patterns, and identifying root causes—work that would take weeks manually.
Manual Session Grouping (Optional)
If your framework doesn't support session tracking, or you want custom session IDs:
with kelet.agentic_session(session_id="user-123-request-456"):
result = await agent.run("Book a flight to NYC")
Also works as a decorator:
@kelet.agentic_session(session_id="user-123-request-456")
async def handle_request():
result = await agent.run("Book a flight to NYC")
But most users don't need this—instrumentation captures sessions automatically from pydantic-ai and other supported frameworks.
Using Different Projects Under the Same Application
If your application hosts multiple independent root agent systems that belong to different Kelet projects (for example customer_support_prod and billing_prod), you can override the global project on a per-session basis using the project parameter on agentic_session:
import kelet
kelet.configure(api_key="your_api_key", project="customer_support")
# Spans inside this session are attributed to "customer_support_prod"
async with kelet.agentic_session(session_id="sess-123", user_id="user-1", project="customer_support_prod"):
result = await customer_support_agent.run("How do I return my order?")
# Spans inside this session are attributed to "billing_prod"
async with kelet.agentic_session(session_id="sess-456", user_id="user-2", project="billing_prod"):
result = await billing_agent.run("Show my invoice for last month")
The project override is automatically propagated via W3C Baggage to any downstream services that use the Kelet SDK. Those services will stamp the correct kelet.project, session_id, and user_id on their spans without needing to call agentic_session themselves — the baggage carrier handles it transparently across process boundaries.
Agent Spans (Optional)
Use kelet.agent() to create an explicit OTEL span wrapping a named agent invocation. All LLM calls inside become children of that span, making your trace tree readable.
async with kelet.agentic_session(session_id="sess-123", user_id="user-1"):
async with kelet.agent(name="support-bot"):
result = await anthropic_client.messages.create(...)
Also works as a decorator:
@kelet.agentic_session(session_id="sess-123")
@kelet.agent(name="support-bot")
async def handle(request):
return await anthropic_client.messages.create(...)
Multiple agents in one session are supported — each gets its own labeled span:
async with kelet.agentic_session(session_id="sess-123"):
async with kelet.agent(name="classifier"):
label = await openai_client.chat.completions.create(...)
async with kelet.agent(name="responder"):
reply = await anthropic_client.messages.create(...)
Auto-Instrumentation
kelet.configure() automatically detects supported libraries and configures available integrations — no extra code needed. This works whether Kelet creates the global TracerProvider or attaches to an existing one.
| Library | Install extra | How it works |
|---|---|---|
| Pydantic AI | (included) | Instrumented automatically |
| Anthropic SDK | pip install kelet[anthropic] |
OpenInference instrumentation |
| OpenAI SDK | pip install kelet[openai] |
OpenInference instrumentation |
| LangChain / LangGraph | pip install kelet[langchain] |
OpenInference instrumentation |
| LiteLLM | pip install litellm |
Registers LiteLLM's native OTEL callback automatically and prefers per-request spans |
| Google ADK | pip install google-adk kelet[google-adk] |
Prefers OpenInference instrumentation; falls back to native ADK OTEL spans |
Install all OpenInference extras at once: pip install kelet[all]
If a library isn't installed, Kelet silently skips it — no errors.
Easy Feedback UI for React
Building a React frontend? Use the Kelet Feedback UI component for instant implicit and explicit feedback collection. See the live demo and documentation for full integration guide.
Works with Your Observability Stack
Already using Logfire or another OTEL provider? Kelet integrates seamlessly:
import logfire
import kelet
logfire.configure()
logfire.instrument_pydantic_ai()
kelet.configure() # Adds Kelet's processor and auto-instrumentation to your existing OTEL setup
What Gets Captured
Kelet is built on OpenTelemetry and supports multiple semantic conventions for AI/LLM observability:
| Semantic Convention | Supported Frameworks |
|---|---|
| GenAI Semantic Conventions | Pydantic AI, LiteLLM, Google ADK, Langfuse SDK |
| Vercel AI SDK | Next.js, Vercel AI |
| OpenInference | Arize Phoenix |
| OpenLLMetry / Traceloop | LangChain, LangGraph, LlamaIndex, OpenAI SDK, Anthropic SDK |
Any framework that exports OpenTelemetry traces using the GenAI semantic conventions will work automatically.
Captured data includes:
- LLM calls: Model, provider, tokens, latency, errors
- Agent sessions: Multi-step interactions grouped by user session
- Custom context: User IDs, session metadata, business-specific attributes
All captured automatically when you instrument with kelet.configure().
Configuration
Set via environment variables:
export KELET_API_KEY=your_api_key # Required
export KELET_PROJECT=production # Required — create a project at console.kelet.ai
export KELET_API_URL=https://... # Optional, defaults to api.kelet.ai
Or pass directly to configure():
kelet.configure(
api_key="your_api_key",
project="production",
auto_instrument=True # Auto-instruments pydantic-ai, Anthropic, OpenAI, LangChain/LangGraph, and LiteLLM; captures Google ADK OTEL spans
)
API Reference
Core Functions:
# Initialize SDK
kelet.configure(api_key=None, project=None, auto_instrument=True, span_processor=None)
# Group operations by session for failure correlation
# Works as context manager (sync + async) and decorator
with kelet.agentic_session(session_id="session-id", user_id="user-id", project="project-override", env="production"): # user_id optional; project overrides global config
result = await agent.run(...)
# Wrap a named agent invocation in an explicit OTEL span
# Works as context manager (sync + async) and decorator
async with kelet.agent(name="my-agent"):
result = await llm_client.messages.create(...)
# Capture user feedback
await kelet.signal(
kind=kelet.SignalKind.FEEDBACK, # feedback | edit | event | metric | arbitrary
source=kelet.SignalSource.HUMAN, # human | label | synthetic
score=0.0, # 0.0 to 1.0
# raise_on_failure=True, # Optional: re-raise request failures
)
# Access current context
session_id = kelet.get_session_id()
trace_id = kelet.get_trace_id()
user_id = kelet.get_user_id()
agent_name = kelet.get_agent_name() # Set by kelet.agent()
metadata = kelet.get_metadata_kwargs() # Set by agentic_session(**kwargs)
# Manual shutdown (automatic on exit)
kelet.shutdown()
Production-Ready
The SDK never disrupts your application:
- Async: Telemetry exports in background, zero blocking
- Fail-safe: Telemetry export and
signal()delivery are best-effort by default - Visible: Delivery failures warn in logs; pass
raise_on_failure=Truetosignal()to surface them - Graceful: If Kelet is down, your agent keeps running
- Auto-flush: Spans exported automatically on process exit
Alpha Status
Kelet is in alpha. What this means:
- It works: Already analyzing thousands of production traces for early users
- Not perfect: Won't catch every failure pattern yet, sometimes needs guidance
- Improving fast: The AI learns from more production data every day
- We need feedback: Help us make it better—tell us what it catches and what it misses
Even in alpha, Kelet does analysis that would take your team weeks to do manually.
The alternative? Manually analyzing 15-25 minutes per trace, across hundreds of failures, trying to spot patterns by hand. Most teams just don't do it—and ship broken agents.
Learn More
- Website: kelet.ai
- Early Access: We're onboarding teams with production AI agents
- Support: GitHub Issues
Built for teams shipping mission-critical AI agents.
License
MIT License — see LICENSE.md for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kelet-1.4.0.tar.gz.
File metadata
- Download URL: kelet-1.4.0.tar.gz
- Upload date:
- Size: 312.3 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
594ecbdc6b114196cb67deb146fb0558e88f9236efc9f19267c5e16ed7888c03
|
|
| MD5 |
bc554c3a8883694a4d22475b83edbfe6
|
|
| BLAKE2b-256 |
44aad404f662f65b0f32c75b6be53032428b130abcafec2606966ff742d36971
|
File details
Details for the file kelet-1.4.0-py3-none-any.whl.
File metadata
- Download URL: kelet-1.4.0-py3-none-any.whl
- Upload date:
- Size: 25.8 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf0a5871709592e97e7b99979c441b38e76b6d22d87b01f10a7df51b2077b089
|
|
| MD5 |
d0481dcc1a91c7397a211060a369c42f
|
|
| BLAKE2b-256 |
200fe473006c6797ca6835993778032540722ed0408257a064703e0efc995c4e
|