Sentrial - Performance monitoring and observability for AI agents
Project description
Sentrial Python SDK
Observability for AI agents — with automated root cause analysis and fix suggestions.
Track LLM calls, tool executions, costs, and latency. When things go wrong, Sentrial tells you WHY and suggests how to fix it.
Why Sentrial?
| Feature | Sentrial | Others |
|---|---|---|
| Root Cause Analysis | ✔️ Understand WHY agents fail | Just shows logs |
| Fix Suggestions | ✔️ AI-suggested fixes + GitHub PRs | Manual debugging |
| Signal Detection | ✔️ Auto-detect patterns/anomalies | Build it yourself |
| Setup time | 1 line | Hours of config |
| Auto-tracking | ✔️ LLM calls, tools, costs | Manual instrumentation |
Installation
# Core (works with any framework)
pip install sentrial
# With specific providers
pip install sentrial[openai] # OpenAI auto-tracking
pip install sentrial[anthropic] # Anthropic auto-tracking
pip install sentrial[google] # Google/Gemini auto-tracking
pip install sentrial[langchain] # LangChain callback handler
pip install sentrial[otel] # OpenTelemetry integration
# Everything
pip install sentrial[all]
Quick Start (30 seconds)
Option 1: Wrap your LLM client (Recommended)
OpenAI:
from sentrial import wrap_openai, configure, begin
from openai import OpenAI
configure(api_key="sentrial_live_xxx")
client = wrap_openai(OpenAI()) # ← That's it!
with begin(user_id="user_123", event="chat", input=user_message) as session:
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": user_message}]
)
# ✔️ Automatically tracked: model, tokens, cost, latency
session.set_output(response.choices[0].message.content)
Anthropic:
from sentrial import wrap_anthropic, configure, begin
from anthropic import Anthropic
configure(api_key="sentrial_live_xxx")
client = wrap_anthropic(Anthropic())
with begin(user_id="user_123", event="chat", input=user_message) as session:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": user_message}]
)
session.set_output(response.content[0].text)
Google Gemini:
from sentrial import wrap_google, configure, begin
import google.generativeai as genai
configure(api_key="sentrial_live_xxx")
genai.configure(api_key="your_google_key")
model = wrap_google(genai.GenerativeModel("gemini-2.5-pro"))
with begin(user_id="user_123", event="chat", input=prompt) as session:
response = model.generate_content(prompt)
session.set_output(response.text)
Option 2: Use decorators (Simplest)
from sentrial import tool, session, configure
configure(api_key="sentrial_live_xxx")
@tool("search_web")
def search_web(query: str) -> dict:
"""Tool calls are automatically tracked"""
return {"results": [...]}
@tool("get_weather")
def get_weather(city: str) -> dict:
return {"temp": 72, "condition": "sunny"}
@session("my-agent")
def run_agent(user_id: str, message: str) -> str:
"""Session boundary - tracks input/output automatically"""
results = search_web(message)
weather = get_weather("San Francisco")
return f"Found {len(results)} results. Weather: {weather}"
# Run it - everything is tracked!
run_agent(user_id="user_123", message="What's happening today?")
Option 3: FastAPI / Async
from fastapi import FastAPI
from sentrial import AsyncSentrialClient
from contextlib import asynccontextmanager
sentrial = AsyncSentrialClient(
api_key="sentrial_live_xxx",
api_url="http://localhost:3001"
)
@asynccontextmanager
async def lifespan(app):
yield
await sentrial.close()
app = FastAPI(lifespan=lifespan)
@app.post("/chat")
async def chat(request: ChatRequest):
async with await sentrial.begin(
user_id=request.user_id,
event="chat",
input=request.message,
) as session:
# Your agent logic here
result = await call_llm(request.message)
await session.track_tool_call(
tool_name="llm_call",
tool_input={"prompt": request.message},
tool_output={"response": result}
)
session.set_output(result)
return {"response": result}
Option 4: LangChain (ALL versions!)
Works with LangChain 0.x AND 1.x - our SDK handles version differences automatically.
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from sentrial import SentrialClient, create_agent_with_sentrial
client = SentrialClient(api_key="sentrial_live_xxx")
llm = ChatOpenAI(model="gpt-4o")
@tool
def my_tool(query: str) -> str:
"""Search for information."""
return f"Results for: {query}"
# create_agent_with_sentrial handles ALL LangChain versions!
agent = create_agent_with_sentrial(
llm=llm,
tools=[my_tool],
client=client,
agent_name="support-agent",
user_id="user_123",
)
result = agent("How do I reset my password?")
print(result)
Manual setup (for more control)
LangChain 1.0+ (uses LangGraph):
from langgraph.prebuilt import create_react_agent
from sentrial.langchain import SentrialCallbackHandler
agent = create_react_agent(llm, tools)
handler = SentrialCallbackHandler(client, session_id)
result = agent.invoke(
{"messages": [("user", query)]},
config={"callbacks": [handler]}
)
LangChain < 1.0 (uses AgentExecutor):
from langchain.agents import AgentExecutor, create_openai_tools_agent
from sentrial.langchain import SentrialCallbackHandler
agent = create_openai_tools_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools)
handler = SentrialCallbackHandler(client, session_id)
result = executor.invoke(
{"input": query},
config={"callbacks": [handler]}
)
Option 5: CrewAI
from crewai import Agent, Task, Crew
from sentrial import SentrialClient
from sentrial.crewai import SentrialCrewHandler
client = SentrialClient(api_key="sentrial_live_xxx")
session_id = client.create_session(name="Research Crew", agent_name="crewai-research")
handler = SentrialCrewHandler(client, session_id)
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
step_callback=handler.on_step,
task_callback=handler.on_task_complete,
)
result = crew.kickoff(inputs={"topic": "AI agents"})
handler.finish(success=True, output=str(result))
Option 6: AutoGen
from autogen_agentchat.teams import RoundRobinGroupChat
from sentrial import SentrialClient
from sentrial.autogen import SentrialAutogenHandler
client = SentrialClient(api_key="sentrial_live_xxx")
session_id = client.create_session(name="Multi-Agent Chat", agent_name="autogen-team")
handler = SentrialAutogenHandler(client, session_id)
team = RoundRobinGroupChat([agent1, agent2])
result = await handler.run_team(team, task="Analyze this data...")
handler.finish(success=True)
Option 7: OpenTelemetry (Enterprise)
Works with any OTel-instrumented framework (Vercel AI SDK, LangChain, etc.):
from sentrial.otel import setup_otel_tracing
# One line setup
setup_otel_tracing(
api_key="sentrial_live_xxx",
project="my-ai-app"
)
# Now ANY OTel-instrumented library sends traces to Sentrial!
# Works with: opentelemetry-instrumentation-openai, traceloop, etc.
Or add to existing OTel setup:
from opentelemetry.sdk.trace import TracerProvider
from sentrial.otel import SentrialSpanProcessor
provider = TracerProvider()
provider.add_span_processor(SentrialSpanProcessor(
api_key="sentrial_live_xxx",
project="my-ai-app"
))
What Gets Tracked
| Data | Auto-tracked | Manual |
|---|---|---|
| LLM calls (prompt, response) | ✔️ via wrappers | track_decision() |
| Token usage | ✔️ via wrappers | tokens_used param |
| Cost (USD) | ✔️ calculated | estimated_cost param |
| Latency | ✔️ always | - |
| Tool calls | ✔️ via @tool |
track_tool_call() |
| Errors | ✔️ always | track_error() |
| User ID | ✔️ via session | user_id param |
| Custom metrics | - | custom_metrics param |
Environment Variables
export SENTRIAL_API_KEY=sentrial_live_xxx
export SENTRIAL_API_URL=https://api.sentrial.com # or http://localhost:3001 for local
Then just:
from sentrial import configure
configure() # Uses env vars automatically
API Reference
Configuration
from sentrial import configure
configure(
api_key="sentrial_live_xxx", # Or SENTRIAL_API_KEY env var
api_url="https://api.sentrial.com" # Or SENTRIAL_API_URL env var
)
LLM Wrappers
from sentrial import wrap_openai, wrap_anthropic, wrap_google
# Wrap once, use everywhere
openai_client = wrap_openai(OpenAI())
anthropic_client = wrap_anthropic(Anthropic())
google_model = wrap_google(genai.GenerativeModel("gemini-2.5-pro"))
Context Manager
from sentrial import begin
with begin(
user_id="user_123", # Required: for user analytics
event="agent_name", # Required: groups sessions
input="user message", # Optional: captured as session input
) as session:
# Track tool calls
session.track_tool_call(
tool_name="search",
tool_input={"query": "..."},
tool_output={"results": [...]}
)
# Track decisions/reasoning
session.track_decision(
reasoning="Choosing to search because...",
confidence=0.9
)
# Set output
session.set_output("Final response to user")
Decorators
from sentrial import tool, session
@tool("tool_name")
def my_tool(arg1: str) -> dict:
"""Automatically tracked when called within a session"""
return {"result": "..."}
@session("agent_name")
def my_agent(user_id: str, message: str) -> str:
"""Creates session, tracks input/output, handles errors"""
return my_tool(message)
Async Client
from sentrial import AsyncSentrialClient
client = AsyncSentrialClient(api_key="...")
async with await client.begin(user_id="...", event="...") as session:
await session.track_tool_call(...)
session.set_output("...")
# Don't forget to close when done
await client.close()
Framework Compatibility
| Framework | Integration | Status |
|---|---|---|
| Direct OpenAI | wrap_openai() |
✔️ |
| Direct Anthropic | wrap_anthropic() |
✔️ |
| Direct Gemini | wrap_google() |
✔️ |
| FastAPI | AsyncSentrialClient |
✔️ |
| LangChain | SentrialCallbackHandler |
✔️ |
| LlamaIndex | OpenTelemetry | ✔️ |
| CrewAI | SentrialCrewHandler |
✔️ |
| AutoGen | SentrialAutogenHandler |
✔️ |
| Custom agents | Decorators or manual | ✔️ |
Examples
See the examples/ directory:
openai_wrapper_example.py- OpenAI auto-trackinganthropic_wrapper_example.py- Anthropic auto-trackinggoogle_wrapper_example.py- Gemini auto-trackingdecorator_example.py- Using@tooland@sessionfastapi_agent.py- Full FastAPI integrationfastapi_with_decorators.py- FastAPI with decoratorslangchain_agent.py- LangChain callback handlercrewai_research_team.py- CrewAI multi-agent examplecrewai_content_pipeline.py- CrewAI content creationautogen_code_review.py- AutoGen code review teamautogen_debate_agents.py- AutoGen debate systemotel_example.py- OpenTelemetry setup
Dashboard Features
After tracking, view in the web dashboard:
- Sessions: See all agent runs with input/output
- Events: Drill into tool calls, LLM decisions, errors
- Users: Track daily active users, session counts
- Agents: Compare performance across agents
- Analytics: Cost trends, latency percentiles, token usage
Support
- 📚 Documentation
- 💬 Discord
- 🐛 GitHub Issues
License
MIT License - see LICENSE 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 sentrial-0.6.0.tar.gz.
File metadata
- Download URL: sentrial-0.6.0.tar.gz
- Upload date:
- Size: 81.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d72d1724953cd55571cf355374262491252d3f5ffecbff658874fc487eef677
|
|
| MD5 |
0e2fdee06eee2d2cfe109131e183eecb
|
|
| BLAKE2b-256 |
0405c7f6967e1caae68a2ec6eb791520d93324adb9552a217a5057394d7b6475
|
File details
Details for the file sentrial-0.6.0-py3-none-any.whl.
File metadata
- Download URL: sentrial-0.6.0-py3-none-any.whl
- Upload date:
- Size: 81.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61e58903e9f122e7ec4536182c62e82e181875a6bddc324744a6db8c8474a12f
|
|
| MD5 |
a528d58d95d8f45dcda455a3a649181f
|
|
| BLAKE2b-256 |
e017f14492d25b6533f9ae3df2764eb0aba7c70d2d542feeb96a1f543a89fbca
|