Skip to main content

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.

PyPI version Python 3.8+ License: MIT

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-tracking
  • anthropic_wrapper_example.py - Anthropic auto-tracking
  • google_wrapper_example.py - Gemini auto-tracking
  • decorator_example.py - Using @tool and @session
  • fastapi_agent.py - Full FastAPI integration
  • fastapi_with_decorators.py - FastAPI with decorators
  • langchain_agent.py - LangChain callback handler
  • crewai_research_team.py - CrewAI multi-agent example
  • crewai_content_pipeline.py - CrewAI content creation
  • autogen_code_review.py - AutoGen code review team
  • autogen_debate_agents.py - AutoGen debate system
  • otel_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

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sentrial-0.5.2.tar.gz (78.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sentrial-0.5.2-py3-none-any.whl (79.2 kB view details)

Uploaded Python 3

File details

Details for the file sentrial-0.5.2.tar.gz.

File metadata

  • Download URL: sentrial-0.5.2.tar.gz
  • Upload date:
  • Size: 78.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for sentrial-0.5.2.tar.gz
Algorithm Hash digest
SHA256 1e3eaf491f0325303d4ad9c3bb24e6b978ad15369261e2c64fb3ecb4419d43f4
MD5 48de952c66278087ea6404678169e769
BLAKE2b-256 c53909286c97627bbd4337d214ea36bdfb28a1dc2e919b5efe50e28c9e6748ff

See more details on using hashes here.

File details

Details for the file sentrial-0.5.2-py3-none-any.whl.

File metadata

  • Download URL: sentrial-0.5.2-py3-none-any.whl
  • Upload date:
  • Size: 79.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for sentrial-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f7da09392cf00039e1e4cd7a64640e3f96ab4bcd6944eb6f6d88368bd65ec1b0
MD5 109330189cf0b1bd2a76290f19b5f0b9
BLAKE2b-256 cdd9f6001f8553ad2e44f05c7b45e1b08a0615be7041ba024a20a95a914a6233

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page