A simulation harness for testing AI agents
Project description
Tenro — Simulation Harness for Testing AI Agents
Simulate agent workflows and verify behavior without burning tokens.
✨ Features
- Simulate scenarios — Control LLM responses, errors, and tool results
- Verify workflows — Check tool usage, edge cases, and agent behavior
- Run evaluations — Measure agent behavior across test cases
- Agnostic by design — Works across multiple LLM providers and agent frameworks
- Multi-agent support — Test multi-agent workflows
Install
pip install tenro
Quick Start
1. Decorate your tools and agent
Decorate with @link_tool and @link_agent.
# myapp/agent.py
from tenro import link_agent, link_tool
def add_footer(text: str) -> str:
# Post-processing before returning the final reply
return f"{text}\n\nReply in the support portal for faster help."
@link_tool
def lookup_ticket(ticket_id: str) -> dict:
return ticket_api.get(ticket_id)
@link_agent
class SupportAgent:
def run(self, task: str) -> str:
... # LLM calls tools and drafts the reply
return add_footer(llm_response)
2. Simulate your test scenarios
Use the @tenro.simulate pytest decorator to simulate LLM calls and tool results.
# tests/test_agent.py
import tenro
from tenro import Provider, ToolCall
from tenro.simulate import llm, tool
from myapp.agent import lookup_ticket, SupportAgent
@tenro.simulate
def test_agent():
# Simulate the tool result
tool.simulate(
lookup_ticket,
result={"status": "shipped", "eta": "Apr 18"}
)
# Simulate the LLM calls
llm.simulate(
Provider.OPENAI,
responses=[
# 1) call the tool
ToolCall(lookup_ticket, ticket_id="T-123"),
# 2) generate the reply
"Your replacement has shipped and should arrive by Apr 18."
]
)
# Run your agent
SupportAgent().run("What's the status of ticket T-123?")
# Verify the tool was called
tool.verify(lookup_ticket, ticket_id="T-123")
# Verify what the user sees and the footer got added
agent.verify(
SupportAgent,
result="Your replacement has shipped and should arrive by Apr 18.\n\n"
"Reply in the support portal for faster help."
)
Trace Output
Tenro can print a local trace of your agent run so you can see each step of execution, including user input, LLM calls, tool calls, and the final output.
🤖 SupportAgent
├─ → user: "What's the status of ticket T-123?"
│
├─ 🧠 GPT-5.4 [SIM]
│ ├─ → prompt: "What's the status of ticket T-123?"
│ └─ ← tool_call: lookup_ticket(ticket_id='T-123')
│
├─ 🔧 lookup_ticket [SIM]
│ ├─ → ticket_id='T-123'
│ └─ ← {'status': 'shipped', 'eta': 'Apr 18'}
│
├─ 🧠 GPT-5.4
│ ├─ → prompt: "Tool result: {'status': 'shipped', 'eta': 'Apr 18'}"
│ └─ ← "Your replacement has shipped and should arrive by Apr 18."
│
└─ ← "Your replacement has shipped and should arrive by Apr 18.
Reply in the support portal for faster help."
────────────────────────────────────────────────────────────────
Summary: 1 agent | 2 LLM calls | 1 tool call | Total: 355ms
Enable trace output locally:
TENRO_PRINT_TRACE=1
How It Works
Decorate your tools, agents, and model calls with @link_tool, @link_agent, and @link_llm, define the behavior you
want with Tenro’s simulation API, then run your tests normally.
Tenro helps you simulate and validate AI agents in two ways:
1. Test the agent code
Simulate LLM responses and verify that your code handles failures, retries, guardrails, and edge cases correctly.
- Invalid tool inputs
- Repeated or unexpected tool calls
- Retry, fallback, and escalation paths
2. Test the LLM behavior
Simulate tools and environment conditions to see how the model behaves under realistic scenarios.
- Tool choice and sequencing
- Incomplete or invalid tool results
- Ambiguous or inconsistent environments
LLM Provider Support
| Provider | API | Text | Status |
|---|---|---|---|
| OpenAI | Chat Completions API | Yes | Supported |
| Anthropic | Messages API | Yes | Supported |
| Gemini | Generate Content API | Yes | Supported |
| Others | OpenAI-compatible API | Yes | Experimental |
Agent Framework Support
| Framework | Status |
|---|---|
| LangChain | Supported |
| Pydantic AI | Supported |
| AutoGen | Supported |
| LangGraph | Supported |
| LlamaIndex | Supported |
| CrewAI | Supported |
| Custom Agents | Supported |
Support
If Tenro helps you, consider starring the repo to bookmark it and help others discover Tenro.
- Report bugs — include exact steps and logs if possible
- Request features — share the use case and expected behavior
- Ask questions — usage, roadmap, or design decisions
Please use GitHub Issues for bug reports, feature requests, and questions.
Contributing
Thanks for your interest in contributing.
Tenro is evolving quickly, and the current focus is on stabilizing the core API. As a result, pull requests are not being accepted at this time.
License
Contact
- Email: support@tenro.ai
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 tenro-0.2.3.tar.gz.
File metadata
- Download URL: tenro-0.2.3.tar.gz
- Upload date:
- Size: 164.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ecab922805b02b3853c2aec9681c7c0d383f7742b8daea7592d7bf9c698e6cc
|
|
| MD5 |
249d739afc2340ffd9c8f9ef7fe6b379
|
|
| BLAKE2b-256 |
3a72bed73f037b5fa5ca257925c8fa06be7f19a2280661df002b00296e6ed283
|
Provenance
The following attestation bundles were made for tenro-0.2.3.tar.gz:
Publisher:
release.yml on tenro-ai/tenro-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tenro-0.2.3.tar.gz -
Subject digest:
5ecab922805b02b3853c2aec9681c7c0d383f7742b8daea7592d7bf9c698e6cc - Sigstore transparency entry: 1340033354
- Sigstore integration time:
-
Permalink:
tenro-ai/tenro-python@d6c329e12dccdff1288feb1d396a60efc34a459e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tenro-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6c329e12dccdff1288feb1d396a60efc34a459e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file tenro-0.2.3-py3-none-any.whl.
File metadata
- Download URL: tenro-0.2.3-py3-none-any.whl
- Upload date:
- Size: 232.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba226ec78f1a7b68f2d7ce259cf5e98300c06bcac6c80c60a2473c3c1c28c8e2
|
|
| MD5 |
a94f3d7e306343b9806d6310eabdd8e0
|
|
| BLAKE2b-256 |
7191186fab09c520e4be0d0394235fcd129ec72ba9852fede062f47332d9a8f3
|
Provenance
The following attestation bundles were made for tenro-0.2.3-py3-none-any.whl:
Publisher:
release.yml on tenro-ai/tenro-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tenro-0.2.3-py3-none-any.whl -
Subject digest:
ba226ec78f1a7b68f2d7ce259cf5e98300c06bcac6c80c60a2473c3c1c28c8e2 - Sigstore transparency entry: 1340033360
- Sigstore integration time:
-
Permalink:
tenro-ai/tenro-python@d6c329e12dccdff1288feb1d396a60efc34a459e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/tenro-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d6c329e12dccdff1288feb1d396a60efc34a459e -
Trigger Event:
workflow_dispatch
-
Statement type: