Skip to main content

Rastir

Rastir

LLM & Agent Observability for Python
One decorator per framework. Full visibility. No monkey-patching.

PyPI Python Docs License GitHub


What is Rastir?

Rastir gives you production observability for LLM agents — token usage, latency percentiles, cost tracking, tool call rates, error categories — as Prometheus metrics with Grafana dashboards.

Add one decorator to your LangGraph, CrewAI, LlamaIndex, ADK, or Strands workflow. Rastir auto-discovers LLMs, tools, and graph nodes inside the framework and wraps them for per-call tracing. No code rewrites. No vendor lock-in.

from rastir import configure, framework_agent

configure(service="my-app", push_url="http://localhost:8080")

@framework_agent
def run(graph_or_agent, prompt):
    return graph_or_agent.invoke(prompt)  # Works with any supported framework

That's it. @framework_agent auto-detects the framework from function arguments and instruments everything inside. Every LLM call, tool invocation, and node execution is now traced with metrics flowing to Prometheus.

You can also use framework-specific decorators for explicit control: @langgraph_agent, @crew_kickoff, @llamaindex_agent, @adk_agent, @strands_agent.


Key Features

Feature Description
One decorator per framework @framework_agent (auto-detect), @langgraph_agent, @crew_kickoff, @llamaindex_agent, @adk_agent, @strands_agent
8 provider adapters OpenAI, Azure OpenAI, Anthropic, Bedrock, Gemini, Cohere, Mistral, Groq — auto-detected from client module paths
Two-phase enrichment Model/provider metadata captured from function args before the call, refined from response after. Survives API failures
MCP distributed tracing wrap(session) propagates trace context across MCP tool boundaries — same trace_id links client and server
Cost observability Per-model USD cost tracking with PricingRegistry, pricing profiles, cost histograms
Streaming TTFT Time-To-First-Token measurement on streaming LLM calls
Guardrail tracking Automatic AWS Bedrock guardrail violation metrics
Error normalisation Exceptions mapped to 6 fixed categories: timeout, rate_limit, validation_error, provider_error, internal_error, unknown
Self-hosted collector FastAPI server you own. Prometheus /metrics, in-memory trace store, OTLP export to Tempo/Jaeger
SRE budgets & burn rates Error and cost budget tracking via Prometheus recording rules — SLO status, burn rates, days-to-exhaustion, all config-driven
7 Grafana dashboards LLM Performance, Agent-Tool, Cost-TTFT, Evaluation, Guardrail, SRE Budgets, System Health
Generic wrap() Instrument any object — Redis, databases, MCP sessions — without decorator access

Framework Support at a Glance

All five frameworks work with @framework_agent (auto-detects the framework) or the dedicated decorator:

LangGraph CrewAI LlamaIndex ADK Strands
Decorator @langgraph_agent @crew_kickoff @llamaindex_agent @adk_agent @strands_agent
Agent span Automatic Automatic Automatic Automatic Automatic
LLM tracing Auto-discovered Auto-discovered Auto-discovered Auto-discovered Auto-discovered
Tool tracing Auto-discovered Auto-discovered Auto-discovered Auto-discovered Auto-discovered
Node tracing Automatic (all nodes) N/A N/A N/A N/A
MCP tools Pass as normal tools Native via mcps=[] MCP tools auto-wrapped Auto-discovered Auto-discovered
User code 1 decorator 1 decorator 1 decorator 1 decorator 1 decorator

LangGraph

@langgraph_agent(agent_name="react_agent")
def run(graph, query):
    return graph.invoke({"messages": [("user", query)]})
react_agent (AGENT)
  ├── node:agent (TRACE)       ← every graph node traced
  │   └── langgraph.llm.gpt-4o.invoke (LLM)
  ├── node:tools (TRACE)
  │   └── langgraph.tool.search.invoke (TOOL)
  └── node:agent (TRACE)
      └── langgraph.llm.gpt-4o.invoke (LLM)

CrewAI

@crew_kickoff(agent_name="research_crew")
def run(crew):
    return crew.kickoff()
research_crew (AGENT)
  ├── crewai.Researcher.llm.call (LLM) — model, provider, tokens, cost
  ├── crewai.Researcher.tool.search (TOOL) — tool.input, tool.output
  │   └── mcpserver:search (TOOL)       ← server span via traceparent
  ├── crewai.Researcher.llm.call (LLM)
  └── crewai.Writer.llm.call (LLM)

LlamaIndex

from rastir import llamaindex_agent
from llama_index.core.agent import ReActAgent

agent = ReActAgent(llm=llm, tools=tools, streaming=False)

@llamaindex_agent(agent_name="qa_agent")
async def run(agent, query):
    return await agent.run(query)
qa_agent (AGENT)
├── llamaindex.ReActAgent.llm.achat (LLM) — model, provider, tokens, cost
├── search.acall (TOOL)                   — tool.input, tool.output
│   └── mcpserver:search (TOOL)           ← server span via traceparent
├── llamaindex.ReActAgent.llm.achat (LLM)
└── llamaindex.ReActAgent.llm.achat (LLM)

ADK

@adk_agent(agent_name="weather_agent")
async def run(runner, prompt):
    events = []
    async for event in runner.run_async(user_id="u1", session_id="s1",
        new_message=types.Content(role="user", parts=[types.Part(text=prompt)])):
        events.append(event)
    return events
weather_agent (AGENT)
├── LLM  gemini-2.0-flash
├── TOOL get_weather
└── LLM  gemini-2.0-flash

Strands

@strands_agent(agent_name="research_agent")
def run(agent, prompt):
    return agent(prompt)
research_agent (AGENT)
├── LLM  us.anthropic.claude-sonnet-4-20250514
├── TOOL search_tool
└── LLM  us.anthropic.claude-sonnet-4-20250514

→ Detailed framework documentation: LangGraph · CrewAI · LlamaIndex · ADK · Strands


Supported Providers

Provider Auto-detection Tokens Model Streaming Request-phase
OpenAI ✅ ✅ ✅ ✅ ✅
Azure OpenAI ✅ ✅ ✅ ✅ ✅
Anthropic ✅ ✅ ✅ ✅ ✅
AWS Bedrock ✅ ✅ ✅ ✅ ✅
Google Gemini ✅ ✅ ✅ ✅ ✅
Cohere ✅ ✅ ✅ — ✅
Mistral ✅ ✅ ✅ ✅ ✅
Groq ✅ ✅ ✅ ✅ ✅

Providers are auto-detected from LLM client module paths — no configuration needed. Each provider adapter extracts model name, token counts, and cost from the provider's native response format.


Installation

pip install rastir              # Client library
pip install rastir[server]      # + Collector server
pip install rastir[all]         # Everything

Quick Start

from rastir import configure, agent, llm, trace

configure(service="my-app", push_url="http://localhost:8080")

@agent(agent_name="qa_bot")
def answer(query):
    return ask_llm(search(query))

@trace
def search(query):
    return vector_db.search(query)

@llm
def ask_llm(context):
    return openai.chat.completions.create(model="gpt-4o", messages=[...])

Start the collector:

rastir-server   # Prometheus metrics at :8080/metrics

What You Get in Prometheus

rastir_llm_calls_total{model="gpt-4o", provider="openai", agent="qa_bot"} 150
rastir_tokens_input_total{model="gpt-4o"} 25000
rastir_tokens_output_total{model="gpt-4o"} 8500
rastir_duration_seconds_bucket{span_type="llm", le="1.0"} 120
rastir_errors_total{span_type="llm", error_type="rate_limit"} 3
rastir_cost_total{model="gpt-4o", pricing_profile="prod"} 12.50
rastir_ttft_seconds_bucket{model="gpt-4o", le="0.5"} 95

Architecture

Your Application                             Rastir Collector
┌────────────────────────────────┐           ┌────────────────────────────┐
│  @framework_agent (auto-detect)│   HTTP    │  FastAPI                   │
│  @langgraph_agent / @adk_agent │  ──────▸  │  ├── Prometheus /metrics   │
│  @crew_kickoff / @strands_agent│   spans   │  ├── Trace store /v1/traces│
│  @llamaindex_agent             │           │  ├── Sampling & backpressure│
│  @agent / @llm / wrap(obj)     │           │  └── OTLP → Tempo/Jaeger  │
└────────────────────────────────┘           └────────────────────────────┘

Deployment

Rastir ships with ready-to-use deployment for local dev, 3 clouds (AWS, Azure, GCP), and Kubernetes:

Target Tool Command
Local Docker Compose cd deploy/docker && ./deploy.sh
AWS Terraform (ECS Fargate) cd deploy/terraform/aws && ./deploy.sh
Azure Terraform (ACI) cd deploy/terraform/azure && ./deploy.sh
GCP Terraform (Cloud Run) cd deploy/terraform/gcp && ./deploy.sh
Kubernetes Helm cd deploy/k8s && ./deploy.sh

Each deployment includes the full stack: Rastir Server + OTel Collector + Prometheus + Grafana. Traces go to Tempo (local/k8s), X-Ray (AWS), Application Insights (Azure), or Cloud Trace (GCP).

See Deployment Guide for details.


Documentation

Full documentation at skamalj.github.io/rastir:

Section Pages
Getting Started Installation & Quick Start
Core Decorators · Adapters · wrap() & MCP · MCP Tracing
Frameworks LangGraph · CrewAI · LlamaIndex · ADK · Strands
Operations Metrics · Dashboards · Server · Configuration
Deployment Docker Compose · AWS · Azure · GCP · Kubernetes
Reference Architecture · Environment Variables · Contributing Adapters

License

MIT — see LICENSE for details.

Metadata

Release files for rastir 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rastir 0.1.3
File Size Uploaded Provenance
rastir-0.1.3.tar.gz 633.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for rastir 0.1.3
File Interpreter ABI Platform
rastir-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 769.6 kB

Release files / rastir-0.1.3.tar.gz

Download URL rastir-0.1.3.tar.gz
Size 633.3 kB
Tags Source
SHA-256 checksum
How to use checksums
16708cd65f32d2e23797573e2c17fc23bc370f566b8a69438e18d30efc185578
BLAKE2b-256 checksum
How to use checksums
f3d0fffdd55c79412cb18f33843fb460703f624016fd816d9cbd75b506a4fd56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Release files / rastir-0.1.3-py3-none-any.whl

Download URL rastir-0.1.3-py3-none-any.whl
Size 136.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c63abd0198b47e247f0ec5d7109cc8e3823f35ad8c42828e08856917a58d8fbb
BLAKE2b-256 checksum
How to use checksums
d3bd31bdc806708d088ca9e0a4f3495ba1ef7dfa5b376af82906715262565413
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.11

Security for rastir 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page