Skip to main content

An observable production-ready open-source AI agent framework.

Project description

Tantra

A simple, minimal, observable, production-ready AI agent framework.

Tantra is designed for developers who build AI agents for production. It combines simplicity with powerful features including first-class observability, integrated evaluation, and extensible provider support.

Features

  • Minimal by Default - Optional modules for advanced features
  • Observable by Design - Every operation produces structured logs with cost tracking
  • Testable First - Integrated evaluation framework as easy as writing unit tests
  • Type-Safe - Full type hints with Pydantic models
  • Extensible - Plugin architecture for custom LLM providers

Installation

pip install tantra

Or install from source:

git clone https://github.com/tantra-run/tantra-py.git
cd tantra
pip install -e ".[dev]"

Quick Start

Simple Agent

import asyncio
from tantra import Agent

async def main():
    agent = Agent(
        "openai:gpt-4o",
        system_prompt="You are a helpful assistant."
    )

    result = await agent.run("Hello!")
    print(result.output)
    print(f"Cost: ${result.metadata.estimated_cost:.4f}")

asyncio.run(main())

Agent with Tools

import asyncio
from tantra import Agent, tool, ToolSet

@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city.

    Args:
        city: The name of the city.
    """
    return f"Weather in {city}: Sunny, 72F"

async def main():
    agent = Agent(
        "openai:gpt-4o",
        tools=ToolSet([get_weather]),
        system_prompt="You can check weather for users."
    )

    result = await agent.run("What's the weather in Tokyo?")
    print(result.output)

asyncio.run(main())

Evaluation

import asyncio
from tantra import Agent, TestCase, EvaluationSuite, contains, tool_called

async def main():
    agent = Agent("openai:gpt-4o-mini")

    suite = EvaluationSuite()
    suite.add_test(TestCase(
        input="What is 2 + 2?",
        matchers=[contains("4")]
    ))

    results = await suite.run(agent)
    print(f"Passed: {results.passed}/{results.metrics.total_tests}")

asyncio.run(main())

Core Concepts

Agent

The Agent class is the main entry point. It wraps an LLM provider, tools, and memory.

agent = Agent(
    provider="openai:gpt-4o",  # or a ModelProvider instance
    tools=ToolSet([...]),      # optional tools
    system_prompt="...",       # agent behavior
    memory=ConversationMemory(), # conversation history
    max_iterations=10,         # prevent infinite loops
)

Tools

Tools are defined using the @tool decorator. Type hints and docstrings are automatically converted to OpenAI-compatible schemas.

@tool
def calculate(expression: str) -> str:
    """Evaluate a math expression.

    Args:
        expression: A mathematical expression like "2 + 2".
    """
    return str(eval(expression))

Memory

Memory stores conversation history. The built-in ConversationMemory keeps messages in memory.

from tantra import ConversationMemory, WindowedMemory

# Keep all messages
memory = ConversationMemory()

# Keep only last N messages
memory = WindowedMemory(window_size=10)

Observability

Every agent run produces a trace of LogEntry objects with full visibility into:

  • Prompts sent to the LLM
  • LLM responses
  • Tool calls and results
  • Token usage and cost
result = await agent.run("Hello!")

for entry in result.trace:
    print(f"[{entry.type}] {entry.data}")

print(f"Total cost: ${result.metadata.estimated_cost:.4f}")

Evaluation

The evaluation framework makes testing agents as easy as unit tests:

suite = EvaluationSuite()
suite.add_test(TestCase(
    input="What's the capital of France?",
    matchers=[
        contains("Paris"),
        cost_under(0.01),
    ]
))

results = await suite.run(agent)

Built-in matchers:

  • contains(text) - Output contains substring
  • not_contains(text) - Output does not contain substring
  • matches_regex(pattern) - Output matches regex
  • json_valid() - Output is valid JSON
  • json_schema(schema) - Output matches JSON schema
  • tool_called(name) - Tool was called
  • tool_not_called(name) - Tool was not called
  • cost_under(amount) - Cost below threshold
  • tokens_under(count) - Tokens below threshold

Custom Providers

Create custom providers by implementing the ModelProvider interface:

from tantra import ModelProvider, Message, ProviderResponse

class MyProvider(ModelProvider):
    async def complete(self, messages, tools=None, **kwargs):
        # Call your LLM API
        return ProviderResponse(content="Hello!")

    def count_tokens(self, messages):
        return len(str(messages))

    @property
    def model_name(self):
        return "my-model"

    @property
    def cost_per_1k_input(self):
        return 0.001

    @property
    def cost_per_1k_output(self):
        return 0.002

Examples

See the examples/ directory for complete examples:

  • 01_simple_agent.py - Basic agent without tools
  • 02_tool_agent.py - Agent with tools
  • 03_streaming.py - Streaming execution
  • 04_evaluation.py - Testing agents
  • 05_custom_provider.py - Custom LLM provider

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
ruff format .

# Lint
ruff check .

License

MIT

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

tantra-0.1.0.tar.gz (187.4 kB view details)

Uploaded Source

Built Distribution

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

tantra-0.1.0-py3-none-any.whl (160.6 kB view details)

Uploaded Python 3

File details

Details for the file tantra-0.1.0.tar.gz.

File metadata

  • Download URL: tantra-0.1.0.tar.gz
  • Upload date:
  • Size: 187.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for tantra-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2c0308bacf63d90e9c5c249c32462c43f37bcce08a71b5a4ee5f062f7901d16d
MD5 0bc07fb04fc4843076c6fe9bfc9d93cb
BLAKE2b-256 b5a023036c405675701dbf3374a6977f236287315f149e9b7be5ed342fb64dbd

See more details on using hashes here.

File details

Details for the file tantra-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tantra-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 160.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for tantra-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 44cbfaafdff01687fe1048648911e38923ad45de26c4232cfc75a93612ea90cb
MD5 234f0d90f92da7d53b42d542e002244a
BLAKE2b-256 5b48da00320552b4c5e9c5767d761645329ef0c4a8a7695d409c3341c29a7a65

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