relai 0.3.2__tar.gz → 0.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of relai might be problematic. Click here for more details.

Files changed (34) hide show
  1. {relai-0.3.2/relai.egg-info → relai-0.3.3}/PKG-INFO +186 -8
  2. relai-0.3.3/README.md +217 -0
  3. {relai-0.3.2 → relai-0.3.3}/pyproject.toml +4 -3
  4. {relai-0.3.2 → relai-0.3.3}/relai/logger.py +5 -2
  5. {relai-0.3.2 → relai-0.3.3}/relai/maestro/optimizer.py +109 -79
  6. {relai-0.3.2 → relai-0.3.3}/relai/mocker/persona.py +6 -2
  7. {relai-0.3.2 → relai-0.3.3}/relai/simulator.py +16 -8
  8. {relai-0.3.2 → relai-0.3.3}/relai/utils.py +37 -0
  9. {relai-0.3.2 → relai-0.3.3/relai.egg-info}/PKG-INFO +186 -8
  10. relai-0.3.2/README.md +0 -38
  11. {relai-0.3.2 → relai-0.3.3}/LICENSE.md +0 -0
  12. {relai-0.3.2 → relai-0.3.3}/relai/__init__.py +0 -0
  13. {relai-0.3.2 → relai-0.3.3}/relai/_client.py +0 -0
  14. {relai-0.3.2 → relai-0.3.3}/relai/_exceptions.py +0 -0
  15. {relai-0.3.2 → relai-0.3.3}/relai/benchmark.py +0 -0
  16. {relai-0.3.2 → relai-0.3.3}/relai/critico/__init__.py +0 -0
  17. {relai-0.3.2 → relai-0.3.3}/relai/critico/critico.py +0 -0
  18. {relai-0.3.2 → relai-0.3.3}/relai/critico/evaluate.py +0 -0
  19. {relai-0.3.2 → relai-0.3.3}/relai/data.py +0 -0
  20. {relai-0.3.2 → relai-0.3.3}/relai/exporter.py +0 -0
  21. {relai-0.3.2 → relai-0.3.3}/relai/flags.py +0 -0
  22. {relai-0.3.2 → relai-0.3.3}/relai/maestro/__init__.py +0 -0
  23. {relai-0.3.2 → relai-0.3.3}/relai/maestro/graph.py +0 -0
  24. {relai-0.3.2 → relai-0.3.3}/relai/maestro/params.py +0 -0
  25. {relai-0.3.2 → relai-0.3.3}/relai/maestro/utils.py +0 -0
  26. {relai-0.3.2 → relai-0.3.3}/relai/mocker/__init__.py +0 -0
  27. {relai-0.3.2 → relai-0.3.3}/relai/mocker/base_mocker.py +0 -0
  28. {relai-0.3.2 → relai-0.3.3}/relai/mocker/tool.py +0 -0
  29. {relai-0.3.2 → relai-0.3.3}/relai/schema/visual.py +0 -0
  30. {relai-0.3.2 → relai-0.3.3}/relai.egg-info/SOURCES.txt +0 -0
  31. {relai-0.3.2 → relai-0.3.3}/relai.egg-info/dependency_links.txt +0 -0
  32. {relai-0.3.2 → relai-0.3.3}/relai.egg-info/requires.txt +0 -0
  33. {relai-0.3.2 → relai-0.3.3}/relai.egg-info/top_level.txt +0 -0
  34. {relai-0.3.2 → relai-0.3.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: relai
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: An SDK for building reliable AI agents
5
5
  Author-email: RELAI <priyatham@relai.ai>, RELAI <wwx@relai.ai>
6
6
  License: Apache License
@@ -205,12 +205,11 @@ License: Apache License
205
205
  See the License for the specific language governing permissions and
206
206
  limitations under the License.
207
207
  Classifier: License :: OSI Approved :: Apache Software License
208
- Classifier: Programming Language :: Python :: 3.9
209
208
  Classifier: Programming Language :: Python :: 3.10
210
209
  Classifier: Programming Language :: Python :: 3.11
211
210
  Classifier: Programming Language :: Python :: 3.12
212
211
  Classifier: Programming Language :: Python :: 3.13
213
- Requires-Python: >=3.9
212
+ Requires-Python: >=3.10
214
213
  Description-Content-Type: text/markdown
215
214
  License-File: LICENSE.md
216
215
  Requires-Dist: pydantic>=2.11.5
@@ -226,14 +225,22 @@ Dynamic: license-file
226
225
  <img align="center" src="docs/assets/relai-logo.png" width="460px" />
227
226
  </p>
228
227
  <p align="left">
229
- <h1 align="center">RELAI: Simulate → Evaluate → Optimize AI Agents</h1>
228
+ <h1 align="center">Simulate → Evaluate → Optimize AI Agents</h1>
229
+ <p align="center">
230
+ <a href="https://pypi.org/project/relai/"><img alt="PyPI" src="https://img.shields.io/pypi/v/relai.svg"></a>
231
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/relai.svg">
232
+ <a href="LICENSE.md"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
233
+ <a href="http://docs.relai.ai"><img alt="Docs" src="https://img.shields.io/badge/docs-online-brightgreen.svg"></a>
234
+ <a href="https://github.com/relai-ai/relai-sdk/actions/workflows/upload-to-package-index.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/relai-ai/relai-sdk/upload-to-package-index.yml?branch=main"></a>
235
+ </p>
236
+
230
237
 
231
238
  **RELAI** is an SDK for building **reliable AI agents**. It streamlines the hardest parts of agent development—**simulation**, **evaluation**, and **optimization**—so you can iterate quickly with confidence.
232
239
 
233
240
  **What you get**
234
- - **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.
235
- - **Agent Evaluation** — Mix **code-based** and **LLM-based** custom evaluators or use **RELAI platform evaluators**. Turn human reviews into **benchmarks** you can re-run.
236
- - **Agent Optimization (Maestro)** — Holistic optimizer that uses evaluator signals & feedback to improve prompts/configs **and** suggest **graph-level** changes. Also selects **best model/tool/graph** based on observed performance.
241
+ - **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.
242
+ - **Agent Evaluation** — Mix code-based and LLM-based custom evaluators or use RELAI platform evaluators. Turn human reviews into benchmarks you can re-run.
243
+ - **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.
237
244
 
238
245
  ## Quickstart
239
246
 
@@ -249,9 +256,153 @@ uv add relai
249
256
  export RELAI_API_KEY="<RELAI_API_KEY>"
250
257
  ```
251
258
 
259
+ ### Example: A simple Stock Assistant Agent (Simulate → Evaluate → Optimize)
260
+ Prerequisites: Needs an OpenAI API key and `openai-agents` installed to run the base agent.
261
+ 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`).
262
+ ```python
263
+ # ============================================================================
264
+ # STEP 0 — Prerequisites
265
+ # ============================================================================
266
+ # export OPENAI_API_KEY="sk-..."
267
+ # `uv add openai-agents`
268
+ # export RELAI_API_KEY="relai-..."
269
+ # Save as `stock-assistant.py`
270
+
271
+ import asyncio
272
+
273
+ from agents import Agent, Runner
274
+
275
+ from relai import (
276
+ AgentOutputs,
277
+ AsyncRELAI,
278
+ AsyncSimulator,
279
+ SimulationTape,
280
+ random_env_generator,
281
+ )
282
+ from relai.critico import Critico
283
+ from relai.critico.evaluate import RELAIFormatEvaluator
284
+ from relai.maestro import Maestro, params, register_param
285
+ from relai.mocker import Persona
286
+ from relai.simulator import simulated
287
+
288
+ # ============================================================================
289
+ # STEP 1.1 — Decorate inputs/tools that will be simulated
290
+ # ============================================================================
291
+
292
+
293
+ @simulated
294
+ async def get_user_query() -> str:
295
+ """Get user's query about stock prices."""
296
+ # In a real agent, this function might get input from a chat interface.
297
+ return input("Enter you stock query: ")
298
+
299
+
300
+ # ============================================================================
301
+ # STEP 1.2 — Register parameters for optimization
302
+ # ============================================================================
303
+
304
+ register_param(
305
+ "prompt",
306
+ type="prompt",
307
+ init_value="You are a helpful assistant for stock price questions.",
308
+ desc="system prompt for the agent",
309
+ )
310
+
311
+ # ============================================================================
312
+ # STEP 2 — Your agent core
313
+ # ============================================================================
314
+
315
+
316
+ async def agent_fn(tape: SimulationTape) -> AgentOutputs:
317
+ question = await get_user_query()
318
+ agent = Agent(
319
+ name="Stock assistant",
320
+ instructions=params.prompt, # access registered parameter
321
+ model="gpt-5-mini",
322
+ )
323
+ result = await Runner.run(agent, question)
324
+ tape.extras["format_rubrics"] = {"Prices must include cents (eg: $XXX.XX)": 1.0}
325
+ tape.agent_inputs["question"] = question # trace inputs for later auditing
326
+ return {"summary": result.final_output}
327
+
328
+
329
+ async def main() -> None:
330
+ # Set up your simulation environment
331
+ # Bind Personas/MockTools to fully-qualified function names
332
+ env_generator = random_env_generator(
333
+ config_set={
334
+ "__main__.get_user_query": [Persona(user_persona="A polite and curious user.")],
335
+ }
336
+ )
337
+
338
+ async with AsyncRELAI() as client:
339
+ # ============================================================================
340
+ # STEP 3 — Simulate
341
+ # ============================================================================
342
+ simulator = AsyncSimulator(agent_fn=agent_fn, env_generator=env_generator, client=client)
343
+ agent_logs = await simulator.run(num_runs=1)
344
+
345
+ # ============================================================================
346
+ # STEP 4 — Evaluate with Critico
347
+ # ============================================================================
348
+ critico = Critico(client=client)
349
+ format_evaluator = RELAIFormatEvaluator(client=client)
350
+ critico.add_evaluators({format_evaluator: 1.0})
351
+ critico_logs = await critico.evaluate(agent_logs)
352
+
353
+ # Publish evaluation report to the RELAI platform
354
+ await critico.report(critico_logs)
355
+
356
+ maestro = Maestro(client=client, agent_fn=agent_fn, log_to_platform=True, name="Stock assistant")
357
+ maestro.add_setup(simulator=simulator, critico=critico)
358
+
359
+ # ============================================================================
360
+ # STEP 5.1 — Optimize configs with Maestro (the parameters registered earlier in STEP 2)
361
+ # ============================================================================
362
+
363
+ # params.load("saved_config.json") # load previous params if available
364
+ await maestro.optimize_config(
365
+ total_rollouts=20, # Total number of rollouts to use for optimization.
366
+ batch_size=1, # Base batch size to use for individual optimization steps. Defaults to 4.
367
+ explore_radius=1, # A positive integer controlling the aggressiveness of exploration during optimization.
368
+ explore_factor=0.5, # A float between 0 to 1 controlling the exploration-exploitation trade-off.
369
+ verbose=True, # If True, related information will be printed during the optimization step.
370
+ )
371
+ params.save("saved_config.json") # save optimized params for future usage
372
+
373
+ # ============================================================================
374
+ # STEP 5.2 — Optimize agent structure with Maestro (changes that cannot be achieved by setting parameters alone)
375
+ # ============================================================================
376
+
377
+ await maestro.optimize_structure(
378
+ total_rollouts=10, # Total number of rollouts to use for optimization.
379
+ code_paths=["stock-assistant.py"], # A list of paths corresponding to code implementations of the agent.
380
+ verbose=True, # If True, related information will be printed during the optimization step.
381
+ )
382
+
383
+
384
+ if __name__ == "__main__":
385
+ asyncio.run(main())
386
+
387
+ ```
388
+ ## Simulation
389
+ 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.
390
+
391
+ ➡️ Learn more: [Simulator](https://docs.relai.ai/simulator.html)
392
+
393
+ ## Evaluation (Critico)
394
+ 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.
395
+
396
+ ➡️ Learn more: [Evaluator](https://docs.relai.ai/evaluator.html)
397
+
398
+ ## Optimization (Maestro)
399
+ 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.
400
+
401
+ ➡️ Learn more: [Maestro](https://docs.relai.ai/maestro.html)
402
+
252
403
  ## Links
253
404
 
254
- - 📘 **Documentation:** [docs.relai.ai](#)
405
+ - 📘 **Documentation:** [docs.relai.ai](http://docs.relai.ai)
255
406
  - 🧪 **Examples:** [relai-sdk/examples](examples)
256
407
  - 🌐 **Website:** [relai.ai](https://relai.ai)
257
408
  - 📰 **Maestro Technical Report:** [ArXiV](https://arxiv.org/abs/2509.04642)
@@ -260,3 +411,30 @@ export RELAI_API_KEY="<RELAI_API_KEY>"
260
411
  ## License
261
412
 
262
413
  Apache 2.0
414
+
415
+ ## Citation
416
+ If you use the SDK in your research, please consider citing our work:
417
+
418
+ ```
419
+ @misc{relai_sdk,
420
+ author = {RELAI, Inc.,},
421
+ title = {relai-sdk},
422
+ year = {2025},
423
+ howpublished = {\url{https://github.com/relai-ai/relai-sdk}},
424
+ note = {GitHub repository},
425
+ urldate = {2025-10-20}
426
+ }
427
+
428
+ @misc{wang2025maestrojointgraph,
429
+ title={Maestro: Joint Graph & Config Optimization for Reliable AI Agents},
430
+ author={Wenxiao Wang and Priyatham Kattakinda and Soheil Feizi},
431
+ year={2025},
432
+ eprint={2509.04642},
433
+ archivePrefix={arXiv},
434
+ primaryClass={cs.AI},
435
+ url={https://arxiv.org/abs/2509.04642},
436
+ }
437
+ ```
438
+
439
+ <p align="center"> <sub>Made with ❤️ by the RELAI team — <a href="https://relai.ai">relai.ai</a> • <a href="https://discord.gg/sjaHJ34YYE">Community</a></sub> </p>
440
+
relai-0.3.3/README.md ADDED
@@ -0,0 +1,217 @@
1
+ <p align="center">
2
+ <img align="center" src="docs/assets/relai-logo.png" width="460px" />
3
+ </p>
4
+ <p align="left">
5
+ <h1 align="center">Simulate → Evaluate → Optimize AI Agents</h1>
6
+ <p align="center">
7
+ <a href="https://pypi.org/project/relai/"><img alt="PyPI" src="https://img.shields.io/pypi/v/relai.svg"></a>
8
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/relai.svg">
9
+ <a href="LICENSE.md"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg"></a>
10
+ <a href="http://docs.relai.ai"><img alt="Docs" src="https://img.shields.io/badge/docs-online-brightgreen.svg"></a>
11
+ <a href="https://github.com/relai-ai/relai-sdk/actions/workflows/upload-to-package-index.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/relai-ai/relai-sdk/upload-to-package-index.yml?branch=main"></a>
12
+ </p>
13
+
14
+
15
+ **RELAI** is an SDK for building **reliable AI agents**. It streamlines the hardest parts of agent development—**simulation**, **evaluation**, and **optimization**—so you can iterate quickly with confidence.
16
+
17
+ **What you get**
18
+ - **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.
19
+ - **Agent Evaluation** — Mix code-based and LLM-based custom evaluators or use RELAI platform evaluators. Turn human reviews into benchmarks you can re-run.
20
+ - **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.
21
+
22
+ ## Quickstart
23
+
24
+ Create a free account and get a RELAI API key: [platform.relai.ai/settings/access/api-keys](https://platform.relai.ai/settings/access/api-keys)
25
+
26
+ ### Installation and Setup
27
+
28
+ ```bash
29
+ pip install relai
30
+ # or
31
+ uv add relai
32
+
33
+ export RELAI_API_KEY="<RELAI_API_KEY>"
34
+ ```
35
+
36
+ ### Example: A simple Stock Assistant Agent (Simulate → Evaluate → Optimize)
37
+ Prerequisites: Needs an OpenAI API key and `openai-agents` installed to run the base agent.
38
+ 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`).
39
+ ```python
40
+ # ============================================================================
41
+ # STEP 0 — Prerequisites
42
+ # ============================================================================
43
+ # export OPENAI_API_KEY="sk-..."
44
+ # `uv add openai-agents`
45
+ # export RELAI_API_KEY="relai-..."
46
+ # Save as `stock-assistant.py`
47
+
48
+ import asyncio
49
+
50
+ from agents import Agent, Runner
51
+
52
+ from relai import (
53
+ AgentOutputs,
54
+ AsyncRELAI,
55
+ AsyncSimulator,
56
+ SimulationTape,
57
+ random_env_generator,
58
+ )
59
+ from relai.critico import Critico
60
+ from relai.critico.evaluate import RELAIFormatEvaluator
61
+ from relai.maestro import Maestro, params, register_param
62
+ from relai.mocker import Persona
63
+ from relai.simulator import simulated
64
+
65
+ # ============================================================================
66
+ # STEP 1.1 — Decorate inputs/tools that will be simulated
67
+ # ============================================================================
68
+
69
+
70
+ @simulated
71
+ async def get_user_query() -> str:
72
+ """Get user's query about stock prices."""
73
+ # In a real agent, this function might get input from a chat interface.
74
+ return input("Enter you stock query: ")
75
+
76
+
77
+ # ============================================================================
78
+ # STEP 1.2 — Register parameters for optimization
79
+ # ============================================================================
80
+
81
+ register_param(
82
+ "prompt",
83
+ type="prompt",
84
+ init_value="You are a helpful assistant for stock price questions.",
85
+ desc="system prompt for the agent",
86
+ )
87
+
88
+ # ============================================================================
89
+ # STEP 2 — Your agent core
90
+ # ============================================================================
91
+
92
+
93
+ async def agent_fn(tape: SimulationTape) -> AgentOutputs:
94
+ question = await get_user_query()
95
+ agent = Agent(
96
+ name="Stock assistant",
97
+ instructions=params.prompt, # access registered parameter
98
+ model="gpt-5-mini",
99
+ )
100
+ result = await Runner.run(agent, question)
101
+ tape.extras["format_rubrics"] = {"Prices must include cents (eg: $XXX.XX)": 1.0}
102
+ tape.agent_inputs["question"] = question # trace inputs for later auditing
103
+ return {"summary": result.final_output}
104
+
105
+
106
+ async def main() -> None:
107
+ # Set up your simulation environment
108
+ # Bind Personas/MockTools to fully-qualified function names
109
+ env_generator = random_env_generator(
110
+ config_set={
111
+ "__main__.get_user_query": [Persona(user_persona="A polite and curious user.")],
112
+ }
113
+ )
114
+
115
+ async with AsyncRELAI() as client:
116
+ # ============================================================================
117
+ # STEP 3 — Simulate
118
+ # ============================================================================
119
+ simulator = AsyncSimulator(agent_fn=agent_fn, env_generator=env_generator, client=client)
120
+ agent_logs = await simulator.run(num_runs=1)
121
+
122
+ # ============================================================================
123
+ # STEP 4 — Evaluate with Critico
124
+ # ============================================================================
125
+ critico = Critico(client=client)
126
+ format_evaluator = RELAIFormatEvaluator(client=client)
127
+ critico.add_evaluators({format_evaluator: 1.0})
128
+ critico_logs = await critico.evaluate(agent_logs)
129
+
130
+ # Publish evaluation report to the RELAI platform
131
+ await critico.report(critico_logs)
132
+
133
+ maestro = Maestro(client=client, agent_fn=agent_fn, log_to_platform=True, name="Stock assistant")
134
+ maestro.add_setup(simulator=simulator, critico=critico)
135
+
136
+ # ============================================================================
137
+ # STEP 5.1 — Optimize configs with Maestro (the parameters registered earlier in STEP 2)
138
+ # ============================================================================
139
+
140
+ # params.load("saved_config.json") # load previous params if available
141
+ await maestro.optimize_config(
142
+ total_rollouts=20, # Total number of rollouts to use for optimization.
143
+ batch_size=1, # Base batch size to use for individual optimization steps. Defaults to 4.
144
+ explore_radius=1, # A positive integer controlling the aggressiveness of exploration during optimization.
145
+ explore_factor=0.5, # A float between 0 to 1 controlling the exploration-exploitation trade-off.
146
+ verbose=True, # If True, related information will be printed during the optimization step.
147
+ )
148
+ params.save("saved_config.json") # save optimized params for future usage
149
+
150
+ # ============================================================================
151
+ # STEP 5.2 — Optimize agent structure with Maestro (changes that cannot be achieved by setting parameters alone)
152
+ # ============================================================================
153
+
154
+ await maestro.optimize_structure(
155
+ total_rollouts=10, # Total number of rollouts to use for optimization.
156
+ code_paths=["stock-assistant.py"], # A list of paths corresponding to code implementations of the agent.
157
+ verbose=True, # If True, related information will be printed during the optimization step.
158
+ )
159
+
160
+
161
+ if __name__ == "__main__":
162
+ asyncio.run(main())
163
+
164
+ ```
165
+ ## Simulation
166
+ 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.
167
+
168
+ ➡️ Learn more: [Simulator](https://docs.relai.ai/simulator.html)
169
+
170
+ ## Evaluation (Critico)
171
+ 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.
172
+
173
+ ➡️ Learn more: [Evaluator](https://docs.relai.ai/evaluator.html)
174
+
175
+ ## Optimization (Maestro)
176
+ 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.
177
+
178
+ ➡️ Learn more: [Maestro](https://docs.relai.ai/maestro.html)
179
+
180
+ ## Links
181
+
182
+ - 📘 **Documentation:** [docs.relai.ai](http://docs.relai.ai)
183
+ - 🧪 **Examples:** [relai-sdk/examples](examples)
184
+ - 🌐 **Website:** [relai.ai](https://relai.ai)
185
+ - 📰 **Maestro Technical Report:** [ArXiV](https://arxiv.org/abs/2509.04642)
186
+ - 🌐 **Join the Community:** [Discord](https://discord.gg/sjaHJ34YYE)
187
+
188
+ ## License
189
+
190
+ Apache 2.0
191
+
192
+ ## Citation
193
+ If you use the SDK in your research, please consider citing our work:
194
+
195
+ ```
196
+ @misc{relai_sdk,
197
+ author = {RELAI, Inc.,},
198
+ title = {relai-sdk},
199
+ year = {2025},
200
+ howpublished = {\url{https://github.com/relai-ai/relai-sdk}},
201
+ note = {GitHub repository},
202
+ urldate = {2025-10-20}
203
+ }
204
+
205
+ @misc{wang2025maestrojointgraph,
206
+ title={Maestro: Joint Graph & Config Optimization for Reliable AI Agents},
207
+ author={Wenxiao Wang and Priyatham Kattakinda and Soheil Feizi},
208
+ year={2025},
209
+ eprint={2509.04642},
210
+ archivePrefix={arXiv},
211
+ primaryClass={cs.AI},
212
+ url={https://arxiv.org/abs/2509.04642},
213
+ }
214
+ ```
215
+
216
+ <p align="center"> <sub>Made with ❤️ by the RELAI team — <a href="https://relai.ai">relai.ai</a> • <a href="https://discord.gg/sjaHJ34YYE">Community</a></sub> </p>
217
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "relai"
7
- requires-python = ">=3.9"
7
+ requires-python = ">=3.10"
8
8
  authors = [
9
9
  {name = "RELAI", email = "priyatham@relai.ai"},
10
10
  {name = "RELAI", email = "wwx@relai.ai"},
@@ -14,7 +14,6 @@ readme = "README.md"
14
14
  license = {file = "LICENSE.md" }
15
15
  classifiers = [
16
16
  "License :: OSI Approved :: Apache Software License",
17
- "Programming Language :: Python :: 3.9",
18
17
  "Programming Language :: Python :: 3.10",
19
18
  "Programming Language :: Python :: 3.11",
20
19
  "Programming Language :: Python :: 3.12",
@@ -30,7 +29,7 @@ dependencies = [
30
29
  "opentelemetry-instrumentation>=0.58b0",
31
30
  "openinference-instrumentation>=0.1.38",
32
31
  ]
33
- version = "0.3.2"
32
+ version = "0.3.3"
34
33
 
35
34
  [tool.setuptools.packages.find]
36
35
  where = ["."]
@@ -40,6 +39,8 @@ include = ["relai*"]
40
39
  dev = [
41
40
  "build>=1.3.0",
42
41
  "google-genai>=1.45.0",
42
+ "langchain>=1.0.1",
43
+ "langgraph>=1.0.1",
43
44
  "mkdocs>=1.6.1",
44
45
  "mkdocs-material>=9.6.14",
45
46
  "mkdocstrings[python]>=0.29.1",
@@ -31,8 +31,11 @@ def flatten(mapping: Mapping[str, Any]) -> Iterator[tuple[str, AttributeValue]]:
31
31
  yield f"{key}.{sub_key}", sub_value
32
32
  elif isinstance(value, list) and any(isinstance(item, Mapping) for item in value):
33
33
  for index, sub_mapping in enumerate(value):
34
- for sub_key, sub_value in flatten(sub_mapping):
35
- yield f"{key}.{index}.{sub_key}", sub_value
34
+ if isinstance(sub_mapping, Mapping):
35
+ for sub_key, sub_value in flatten(sub_mapping):
36
+ yield f"{key}.{index}.{sub_key}", sub_value
37
+ else:
38
+ yield f"{key}.{index}", sub_mapping
36
39
  else:
37
40
  if isinstance(value, Enum):
38
41
  value = value.value