An SDK for building reliable AI agents
Project description
Simulate → Evaluate → Optimize AI Agents
RELAI is a platform for building reliable AI agents. It streamlines the hardest parts of agent development—simulation, evaluation, and optimization—so you can iterate quickly with confidence.
What you get
- Agent Simulation — Create full/partial environments, define LLM personas, mock MCP servers & tools, and generate synthetic data. Optionally condition simulation on real samples to better match production.
- Agent Evaluation — Mix code-based and LLM-based custom evaluators or use RELAI platform evaluators. Turn human reviews into benchmarks you can re-run.
- Agent Optimization (Maestro) — Holistic optimizer that uses evaluator signals & feedback to improve prompts/configs and suggest graph-level changes. Maestro selects best model/tool/graph based on observed performance.
Works with: OpenAI Agents SDK, Google ADK, LangGraph, and other agent frameworks.
Quickstart
Create a free account and get a RELAI API key: platform.relai.ai/settings/access/api-keys
Installation and Setup
pip install relai
# or
uv add relai
export RELAI_API_KEY="<RELAI_API_KEY>"
Example: A simple Stock Assistant Agent (Simulate → Evaluate → Optimize)
Notebook version of the example below: stock-assistant (simulate->evaluate->optimize).ipynb
Prerequisites: Needs an OpenAI API key and openai-agents installed to run the base agent.
To use Maestro graph optimizer, save the following in a file called stock-assistant.py (or change the code_paths argument to maestro.optimize_structure).
# ============================================================================
# STEP 0 — Prerequisites
# ============================================================================
# export OPENAI_API_KEY="sk-..."
# `uv add openai-agents`
# export RELAI_API_KEY="relai-..."
# Save as `stock-assistant.py`
import asyncio
from agents import Agent, Runner
from relai import (
AgentOutputs,
AsyncRELAI,
AsyncSimulator,
SimulationTape,
random_env_generator,
)
from relai.critico import Critico
from relai.critico.evaluate import RELAIFormatEvaluator
from relai.maestro import Maestro, params, register_param
from relai.mocker import Persona
from relai.simulator import simulated
# ============================================================================
# STEP 1.1 — Decorate inputs/tools that will be simulated
# ============================================================================
@simulated
async def get_user_query() -> str:
"""Get user's query about stock prices."""
# In a real agent, this function might get input from a chat interface.
return input("Enter you stock query: ")
# ============================================================================
# STEP 1.2 — Register parameters for optimization
# ============================================================================
register_param(
"prompt",
type="prompt",
init_value="You are a helpful assistant for stock price questions.",
desc="system prompt for the agent",
)
# ============================================================================
# STEP 2 — Your agent core
# ============================================================================
async def agent_fn(tape: SimulationTape) -> AgentOutputs:
# It is good practice to catch exceptions in agent function
# especially if the agent might raise errors with different configs
try:
question = await get_user_query()
agent = Agent(
name="Stock assistant",
instructions=params.prompt, # access registered parameter
model="gpt-5-mini",
)
result = await Runner.run(agent, question)
tape.extras["format_rubrics"] = {"Prices must include cents (eg: $XXX.XX)": 1.0}
tape.agent_inputs["question"] = question # trace inputs for later auditing
return {"summary": result.final_output}
except Exception as e:
return {"summary": str(e)}
async def main() -> None:
# Set up your simulation environment
# Bind Personas/MockTools to fully-qualified function names
env_generator = random_env_generator(
config_set={
"__main__.get_user_query": [Persona(user_persona="A polite and curious user.")],
}
)
async with AsyncRELAI() as client:
# ============================================================================
# STEP 3 — Simulate
# ============================================================================
simulator = AsyncSimulator(agent_fn=agent_fn, env_generator=env_generator, client=client)
agent_logs = await simulator.run(num_runs=1)
# ============================================================================
# STEP 4 — Evaluate with Critico
# ============================================================================
critico = Critico(client=client)
format_evaluator = RELAIFormatEvaluator(client=client)
critico.add_evaluators({format_evaluator: 1.0})
critico_logs = await critico.evaluate(agent_logs)
# Submit evaluation results to the RELAI platform (https://platform.relai.ai/results/runs)
await critico.report(critico_logs)
# Submit an aggregate report to RELAI platform (https://platform.relai.ai/results/critico)
await critico.report_aggregate(critico_logs, title="Stock assistant evaluation")
maestro = Maestro(client=client, agent_fn=agent_fn, log_to_platform=True, name="Stock assistant")
maestro.add_setup(simulator=simulator, critico=critico)
# ============================================================================
# STEP 5.1 — Optimize configs with Maestro (the parameters registered earlier in STEP 2)
# ============================================================================
# params.load("saved_config.json") # load previous params if available
await maestro.optimize_config(
total_rollouts=20, # Total number of rollouts to use for optimization.
batch_size=2, # Base batch size to use for individual optimization steps. Defaults to 4.
explore_radius=1, # A positive integer controlling the aggressiveness of exploration during optimization.
explore_factor=0.5, # A float between 0 to 1 controlling the exploration-exploitation trade-off.
verbose=True, # If True, additional information will be printed during the optimization step.
)
params.save("saved_config.json") # save optimized params for future usage
# ============================================================================
# STEP 5.2 — Optimize agent structure with Maestro (changes that cannot be achieved by setting parameters alone)
# ============================================================================
await maestro.optimize_structure(
total_rollouts=10, # Total number of rollouts to use for optimization.
code_paths=["stock-assistant.py"], # A list of paths corresponding to code implementations of the agent.
verbose=True, # If True, additional information will be printed during the optimization step.
)
if __name__ == "__main__":
asyncio.run(main())
Simulation
Create controlled environments where agents interact and generate traces. Compose LLM personas, mock MCP tools/servers, and synthetic data; optionally condition on real events to align simulation ⇄ production.
➡️ Learn more: Simulator
Evaluation (Critico)
Use code-based or LLM-based evaluators—or RELAI platform evaluators—and convert human reviews into benchmarks you can re-run in Simuation/CI pipeline.
➡️ Learn more: Evaluator
Optimization (Maestro)
Maestro is a holistic agent optimizer. It consumes evaluator/user feedback to improve prompts, configs, and even graph structure when prompt tuning isn’t enough. It can also select the best model, best tool, and best graph based on observed performance.
➡️ Learn more: Maestro
Links
- 📘 Documentation: docs.relai.ai
- 🧪 Examples: relai-sdk/examples
- 📓 Notebooks: relai-sdk/notebooks
- 📖 Tutorials: docs.relai.ai/tutorials/index.html
- 🌐 Website: relai.ai
- 📰 Maestro Technical Report: ArXiV
- 🌐 Join the Community: Discord
License
Apache 2.0
Citation
If you use the SDK in your research, please consider citing our work:
@misc{relai_sdk,
author = {RELAI, Inc.,},
title = {relai-sdk},
year = {2025},
howpublished = {\url{https://github.com/relai-ai/relai-sdk}},
note = {GitHub repository},
urldate = {2025-10-20}
}
@misc{wang2025maestrojointgraph,
title={Maestro: Joint Graph & Config Optimization for Reliable AI Agents},
author={Wenxiao Wang and Priyatham Kattakinda and Soheil Feizi},
year={2025},
eprint={2509.04642},
archivePrefix={arXiv},
primaryClass={cs.AI},
url={https://arxiv.org/abs/2509.04642},
}
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 relai-0.3.15.tar.gz.
File metadata
- Download URL: relai-0.3.15.tar.gz
- Upload date:
- Size: 59.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
984a81c68cad3d2fe4e88b1ad5b6db90b245769652e940522bf175b2e0a7cfe1
|
|
| MD5 |
5909877d35bbe41e50a6ddae0ef85c6a
|
|
| BLAKE2b-256 |
f8938be15638494ea4db2ccd320095ba045e1adbd89f29bda57917d3f48c81b1
|
Provenance
The following attestation bundles were made for relai-0.3.15.tar.gz:
Publisher:
upload-to-package-index.yml on relai-ai/relai-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
relai-0.3.15.tar.gz -
Subject digest:
984a81c68cad3d2fe4e88b1ad5b6db90b245769652e940522bf175b2e0a7cfe1 - Sigstore transparency entry: 772863363
- Sigstore integration time:
-
Permalink:
relai-ai/relai-sdk@a55c6658ca410cfc3fb05e03765a38db015b2612 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/relai-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
upload-to-package-index.yml@a55c6658ca410cfc3fb05e03765a38db015b2612 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file relai-0.3.15-py3-none-any.whl.
File metadata
- Download URL: relai-0.3.15-py3-none-any.whl
- Upload date:
- Size: 62.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b845a0f64d74f05ec1542b9c8a80903757025a8a0d3a9771b5c3a32aec911848
|
|
| MD5 |
6606c65f29e631f67ecae02e7e2446e5
|
|
| BLAKE2b-256 |
90aa4d9ea5e114986f70e26be96bc7ca00086ee22bfc68281f01944170b5f25c
|
Provenance
The following attestation bundles were made for relai-0.3.15-py3-none-any.whl:
Publisher:
upload-to-package-index.yml on relai-ai/relai-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
relai-0.3.15-py3-none-any.whl -
Subject digest:
b845a0f64d74f05ec1542b9c8a80903757025a8a0d3a9771b5c3a32aec911848 - Sigstore transparency entry: 772863396
- Sigstore integration time:
-
Permalink:
relai-ai/relai-sdk@a55c6658ca410cfc3fb05e03765a38db015b2612 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/relai-ai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
upload-to-package-index.yml@a55c6658ca410cfc3fb05e03765a38db015b2612 -
Trigger Event:
workflow_dispatch
-
Statement type: