Skip to main content

The open-source testing framework for AI agents.

Project description

TrajAI

The open-source testing framework for AI agents.

PyPI version CI License: MIT Python 3.10+

TrajAI lets you write deterministic tests for non-deterministic AI agents. Mock tools, capture execution trajectories, and assert on what your agent did — not just what it said.


Quick Start

pip install trajai
# test_agent.py
from trajai.mock import MockToolkit

def my_agent(input: str, tools: dict):
    order = tools["lookup_order"]({"order_id": "123"})
    if order["status"] == "delivered":
        refund = tools["process_refund"]({"order_id": "123", "amount": 50.0})
        return f"Refund processed: {refund['confirmation']}"
    return "Order not yet delivered"

def test_refund_flow():
    toolkit = MockToolkit()
    toolkit.mock("lookup_order", return_value={"status": "delivered"})
    toolkit.mock("process_refund", return_value={"confirmation": "RF-456", "success": True})

    result = toolkit.run_callable(my_agent, "Refund order 123")

    assert result.tool_was_called("lookup_order")
    assert result.tool_called_before("lookup_order", "process_refund")
    assert result.output_contains("RF-456")
pytest test_agent.py -v

Why TrajAI?

Testing AI agents is hard. LLMs are non-deterministic, tool calls have side effects, and there's no standard way to assert on agent behavior. Teams end up with fragile integration tests that hit real APIs, cost money, and break randomly.

TrajAI fixes this:

  • Mock tools, not LLMs. Your agent runs with real LLM calls but mocked tools. No side effects, deterministic tool responses.
  • Assert on behavior. Test what the agent did (which tools it called, in what order, with what arguments) — not just its final text output.
  • Handle non-determinism. Run tests N times and assert on pass rates. "This agent calls the right tools 95% of the time" is a valid, useful test.
  • Framework support. Works with LangGraph, CrewAI, OpenAI Agents SDK, or any Python callable.

Core Concepts

MockToolkit

The central API. Register mock tools, run your agent, get results.

toolkit = MockToolkit()
toolkit.mock("search", return_value={"results": [...]})
toolkit.mock("send_email", return_value={"sent": True})

Assertions

Both boolean and assert-style APIs for testing agent behavior:

result = toolkit.run_callable(agent, "Find and email the report")

# Boolean API — use with assert
assert result.tool_was_called("search")
assert result.tool_called_before("search", "send_email")
assert result.tool_call_count("search", 1)

# Assert API — raises TrajAIAssertionError with formatted trajectory on failure
result.assert_tool_was_called("search")
result.assert_output_contains("report")

Trajectory

Every agent run produces a Trajectory — a chronological record of all tool calls, LLM calls, and state changes. When assertions fail, the full trajectory is pretty-printed in the error message.

Statistical Testing

Handle LLM non-determinism by running tests multiple times:

from trajai.runner import statistical

@statistical(n=10, threshold=0.9)
def test_agent_uses_correct_tools():
    toolkit = MockToolkit()
    toolkit.mock("lookup", return_value={"id": "123"})
    result = toolkit.run_callable(agent, "Look up order 123")
    assert result.tool_was_called("lookup")

Framework Support

Framework Install Status
Any Python callable pip install trajai Stable
LangGraph pip install trajai[langgraph] Stable
CrewAI pip install trajai[crewai] Stable
OpenAI Agents SDK pip install trajai[openai-agents] Stable

Framework-specific adapters handle tool injection and trajectory collection automatically:

# LangGraph — auto-detects and injects mocks
result = toolkit.run(my_langgraph_agent, "Refund order 123")

# Generic callable — you wire the tools
result = toolkit.run_callable(my_function, "Refund order 123")

Mock Strategies

# Static return value
toolkit.mock("get_weather", return_value={"temp": 72, "unit": "F"})

# Sequence — different value on each call
toolkit.mock("check_status", sequence=[
    {"status": "pending"},
    {"status": "shipped"},
    {"status": "delivered"},
])

# Side effect — custom function
toolkit.mock("calculate", side_effect=lambda args: args["a"] + args["b"])

# Error — simulate failures
toolkit.mock("flaky_api", side_effect=ConnectionError("timeout"))

# Conditional — return based on arguments
toolkit.mock("lookup", conditional={
    lambda args: args.get("id") == "1": {"name": "Alice"},
    lambda args: args.get("id") == "2": {"name": "Bob"},
})

Documentation


Examples

Self-contained example projects in the examples/ directory:


Contributing

See CONTRIBUTING.md for development setup, coding standards, and how to submit changes.


License

MIT License. See LICENSE.

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

trajai-0.1.0.tar.gz (120.4 kB view details)

Uploaded Source

Built Distribution

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

trajai-0.1.0-py3-none-any.whl (43.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: trajai-0.1.0.tar.gz
  • Upload date:
  • Size: 120.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for trajai-0.1.0.tar.gz
Algorithm Hash digest
SHA256 22e3610340969c63d0ca6a40e6b6d696bd40842452cd175c0d03d32ea5ba78b1
MD5 76988e4112b464569d37fcc732508c5a
BLAKE2b-256 8965b4485c3d56af23ac5134bc90f73c8cc7bb8af1fe2b9b071ea4cce771b8dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for trajai-0.1.0.tar.gz:

Publisher: release.yml on Kaboom2025/TrajAI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: trajai-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 43.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for trajai-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 67a3f36c85ef15d6bf1d97176a47e0f9f6d42c4168cb4e3a4e82b73632996558
MD5 ad27f31efc8bcb500f8e08396e87b767
BLAKE2b-256 cf651047dac28b7ea3ab1eb7a25ec4b0a354d6fc208b15373bfc78d796c6b482

See more details on using hashes here.

Provenance

The following attestation bundles were made for trajai-0.1.0-py3-none-any.whl:

Publisher: release.yml on Kaboom2025/TrajAI

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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