runa-ai 0.1.0__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.
- runa_ai-0.1.0/LICENSE +21 -0
- runa_ai-0.1.0/PKG-INFO +97 -0
- runa_ai-0.1.0/README.md +71 -0
- runa_ai-0.1.0/pyproject.toml +87 -0
- runa_ai-0.1.0/pyproject.toml.orig +76 -0
- runa_ai-0.1.0/src/runa/__init__.py +79 -0
- runa_ai-0.1.0/src/runa/_graph.py +63 -0
- runa_ai-0.1.0/src/runa/_models/__init__.py +33 -0
- runa_ai-0.1.0/src/runa/_models/anthropic.py +284 -0
- runa_ai-0.1.0/src/runa/_models/interface.py +91 -0
- runa_ai-0.1.0/src/runa/_models/multi_provider.py +113 -0
- runa_ai-0.1.0/src/runa/_models/openai_chatcompletions.py +177 -0
- runa_ai-0.1.0/src/runa/_types.py +166 -0
- runa_ai-0.1.0/src/runa/agent.py +493 -0
- runa_ai-0.1.0/src/runa/approval.py +32 -0
- runa_ai-0.1.0/src/runa/cache.py +155 -0
- runa_ai-0.1.0/src/runa/cli/__init__.py +1 -0
- runa_ai-0.1.0/src/runa/cli/_project.py +116 -0
- runa_ai-0.1.0/src/runa/cli/agents.py +82 -0
- runa_ai-0.1.0/src/runa/cli/chat.py +171 -0
- runa_ai-0.1.0/src/runa/cli/eval.py +56 -0
- runa_ai-0.1.0/src/runa/cli/generate.py +426 -0
- runa_ai-0.1.0/src/runa/cli/main.py +345 -0
- runa_ai-0.1.0/src/runa/cli/new.py +121 -0
- runa_ai-0.1.0/src/runa/cli/sessions.py +112 -0
- runa_ai-0.1.0/src/runa/cli/test.py +59 -0
- runa_ai-0.1.0/src/runa/cli/traces.py +43 -0
- runa_ai-0.1.0/src/runa/cli/ui.py +20 -0
- runa_ai-0.1.0/src/runa/compact.py +57 -0
- runa_ai-0.1.0/src/runa/db/__init__.py +5 -0
- runa_ai-0.1.0/src/runa/db/postgres.py +367 -0
- runa_ai-0.1.0/src/runa/db/redis.py +62 -0
- runa_ai-0.1.0/src/runa/db/sqlite.py +40 -0
- runa_ai-0.1.0/src/runa/embeddings.py +63 -0
- runa_ai-0.1.0/src/runa/eval/__init__.py +24 -0
- runa_ai-0.1.0/src/runa/eval/case.py +28 -0
- runa_ai-0.1.0/src/runa/eval/dataset.py +45 -0
- runa_ai-0.1.0/src/runa/eval/evaluate.py +78 -0
- runa_ai-0.1.0/src/runa/eval/evaluation/__init__.py +15 -0
- runa_ai-0.1.0/src/runa/eval/evaluation/core.py +40 -0
- runa_ai-0.1.0/src/runa/eval/evaluation/defaults.py +14 -0
- runa_ai-0.1.0/src/runa/eval/evaluation/deterministic.py +38 -0
- runa_ai-0.1.0/src/runa/eval/evaluation/semantic.py +240 -0
- runa_ai-0.1.0/src/runa/eval/judge.py +74 -0
- runa_ai-0.1.0/src/runa/eval/report.py +110 -0
- runa_ai-0.1.0/src/runa/eval/storage.py +152 -0
- runa_ai-0.1.0/src/runa/eval/tracing/__init__.py +5 -0
- runa_ai-0.1.0/src/runa/eval/tracing/adapter.py +78 -0
- runa_ai-0.1.0/src/runa/exceptions.py +168 -0
- runa_ai-0.1.0/src/runa/guardrail.py +333 -0
- runa_ai-0.1.0/src/runa/handoff.py +88 -0
- runa_ai-0.1.0/src/runa/knowledge.py +270 -0
- runa_ai-0.1.0/src/runa/lifecycle.py +204 -0
- runa_ai-0.1.0/src/runa/mcp.py +139 -0
- runa_ai-0.1.0/src/runa/memory.py +314 -0
- runa_ai-0.1.0/src/runa/result.py +75 -0
- runa_ai-0.1.0/src/runa/run.py +35 -0
- runa_ai-0.1.0/src/runa/run_config.py +29 -0
- runa_ai-0.1.0/src/runa/run_internal/__init__.py +15 -0
- runa_ai-0.1.0/src/runa/run_internal/agent_runner_helpers.py +150 -0
- runa_ai-0.1.0/src/runa/run_internal/guardrails.py +101 -0
- runa_ai-0.1.0/src/runa/run_internal/run_loop.py +477 -0
- runa_ai-0.1.0/src/runa/run_internal/spans.py +56 -0
- runa_ai-0.1.0/src/runa/run_internal/streaming.py +140 -0
- runa_ai-0.1.0/src/runa/run_internal/tool_execution.py +143 -0
- runa_ai-0.1.0/src/runa/run_state.py +293 -0
- runa_ai-0.1.0/src/runa/runner.py +84 -0
- runa_ai-0.1.0/src/runa/session.py +182 -0
- runa_ai-0.1.0/src/runa/stream_events.py +45 -0
- runa_ai-0.1.0/src/runa/this.py +28 -0
- runa_ai-0.1.0/src/runa/tool.py +166 -0
- runa_ai-0.1.0/src/runa/tracing/__init__.py +30 -0
- runa_ai-0.1.0/src/runa/tracing/config.py +178 -0
- runa_ai-0.1.0/src/runa/tracing/manual.py +101 -0
- runa_ai-0.1.0/src/runa/tracing/spans.py +45 -0
- runa_ai-0.1.0/src/runa/tracing/storage.py +175 -0
- runa_ai-0.1.0/src/runa/tracing/traces.py +120 -0
- runa_ai-0.1.0/src/runa/tracing/util.py +16 -0
- runa_ai-0.1.0/src/runa/web/__init__.py +5 -0
- runa_ai-0.1.0/src/runa/web/_html.py +163 -0
- runa_ai-0.1.0/src/runa/web/agents.py +46 -0
- runa_ai-0.1.0/src/runa/web/app.py +80 -0
- runa_ai-0.1.0/src/runa/web/evaluations.py +87 -0
- runa_ai-0.1.0/src/runa/web/sessions.py +50 -0
- runa_ai-0.1.0/src/runa/web/traces.py +141 -0
runa_ai-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Khalil Brahim Benyous
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
runa_ai-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: runa-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The application framework for agentic AI.
|
|
5
|
+
Author: Brahim Benyous
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: anthropic>=0.75.0
|
|
9
|
+
Requires-Dist: graphviz>=0.21
|
|
10
|
+
Requires-Dist: httpx2>=2.12.0
|
|
11
|
+
Requires-Dist: mcp>=2.1.1
|
|
12
|
+
Requires-Dist: mkdocs-material>=9.7.7
|
|
13
|
+
Requires-Dist: pydantic>=2.9.0
|
|
14
|
+
Requires-Dist: pypdf>=6.0.0
|
|
15
|
+
Requires-Dist: sqlite-vec>=0.1.9
|
|
16
|
+
Requires-Dist: asyncpg>=0.30.0 ; extra == 'postgres'
|
|
17
|
+
Requires-Dist: pgvector>=0.3.6 ; extra == 'postgres'
|
|
18
|
+
Requires-Dist: redis>=5.2.0 ; extra == 'redis'
|
|
19
|
+
Requires-Dist: fastapi>=0.121.0 ; extra == 'ui'
|
|
20
|
+
Requires-Dist: uvicorn>=0.38.0 ; extra == 'ui'
|
|
21
|
+
Requires-Python: >=3.14
|
|
22
|
+
Provides-Extra: postgres
|
|
23
|
+
Provides-Extra: redis
|
|
24
|
+
Provides-Extra: ui
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# Runa
|
|
28
|
+
|
|
29
|
+
## What's Runa?
|
|
30
|
+
|
|
31
|
+
Runa is an opinionated Python framework for agentic AI. Instead of a wide
|
|
32
|
+
menu of configuration options, it gives you a small set of primitives,
|
|
33
|
+
with clear conventions:
|
|
34
|
+
|
|
35
|
+
- **Agents:** which are LLMs equipped with instructions and tools
|
|
36
|
+
- **Tools:** the actions an agent can take in the outside world, described clearly enough that the agent knows when and how to use them.
|
|
37
|
+
- **Guardrails:** checks that keep what goes into and comes out of an agent or tool within bounds.
|
|
38
|
+
- **Delegation:** how agents hand off work to each other, either passing a task along completely or asking for help and getting an answer back.
|
|
39
|
+
- **Context management:** what an agent remembers: session, memory, and domain knowledge.
|
|
40
|
+
|
|
41
|
+
Observability and evaluation come built in, not bolted on: every run is
|
|
42
|
+
traced automatically as a span tree, and evaluation grade
|
|
43
|
+
correctness with plain assertions or judged, dataset-driven scoring.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Getting Started
|
|
47
|
+
|
|
48
|
+
1. Install [uv](https://docs.astral.sh/uv/), then Runa:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
uv venv --python 3.14
|
|
52
|
+
source .venv/bin/activate
|
|
53
|
+
uv add git+https://github.com/benybrahim/runa.git
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
2. Scaffold a new application:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
runa new myapp
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
where `myapp` is the application name.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
3. Change directory to `myapp`, generate an agent, and talk to it:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd myapp
|
|
69
|
+
runa generate agent AssistantAgent --model gpt-5.4-nano
|
|
70
|
+
runa chat assistant_agent
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Run any subcommand with `--help` for options.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
4. Fill in the API key for whichever model you use in `.env`, and you're
|
|
77
|
+
running.
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
5. Follow the guides to keep building your application. You may find the following resources handy:
|
|
81
|
+
* [Getting Started with Runa](https://benybrahim.github.io/runa/getting_started/)
|
|
82
|
+
* [Runa Guides](https://benybrahim.github.io/runa/guides/)
|
|
83
|
+
* [CLI Reference](https://benybrahim.github.io/runa/cli/)
|
|
84
|
+
|
|
85
|
+
## Read the Zen of Runa
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python -c "from runa import this"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Contributing
|
|
92
|
+
|
|
93
|
+
We encourage you to contribute to Runa! Check out [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
Runa is released under the [MIT License](./LICENSE).
|
runa_ai-0.1.0/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Runa
|
|
2
|
+
|
|
3
|
+
## What's Runa?
|
|
4
|
+
|
|
5
|
+
Runa is an opinionated Python framework for agentic AI. Instead of a wide
|
|
6
|
+
menu of configuration options, it gives you a small set of primitives,
|
|
7
|
+
with clear conventions:
|
|
8
|
+
|
|
9
|
+
- **Agents:** which are LLMs equipped with instructions and tools
|
|
10
|
+
- **Tools:** the actions an agent can take in the outside world, described clearly enough that the agent knows when and how to use them.
|
|
11
|
+
- **Guardrails:** checks that keep what goes into and comes out of an agent or tool within bounds.
|
|
12
|
+
- **Delegation:** how agents hand off work to each other, either passing a task along completely or asking for help and getting an answer back.
|
|
13
|
+
- **Context management:** what an agent remembers: session, memory, and domain knowledge.
|
|
14
|
+
|
|
15
|
+
Observability and evaluation come built in, not bolted on: every run is
|
|
16
|
+
traced automatically as a span tree, and evaluation grade
|
|
17
|
+
correctness with plain assertions or judged, dataset-driven scoring.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
## Getting Started
|
|
21
|
+
|
|
22
|
+
1. Install [uv](https://docs.astral.sh/uv/), then Runa:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
uv venv --python 3.14
|
|
26
|
+
source .venv/bin/activate
|
|
27
|
+
uv add git+https://github.com/benybrahim/runa.git
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
2. Scaffold a new application:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
runa new myapp
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
where `myapp` is the application name.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
3. Change directory to `myapp`, generate an agent, and talk to it:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd myapp
|
|
43
|
+
runa generate agent AssistantAgent --model gpt-5.4-nano
|
|
44
|
+
runa chat assistant_agent
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Run any subcommand with `--help` for options.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
4. Fill in the API key for whichever model you use in `.env`, and you're
|
|
51
|
+
running.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
5. Follow the guides to keep building your application. You may find the following resources handy:
|
|
55
|
+
* [Getting Started with Runa](https://benybrahim.github.io/runa/getting_started/)
|
|
56
|
+
* [Runa Guides](https://benybrahim.github.io/runa/guides/)
|
|
57
|
+
* [CLI Reference](https://benybrahim.github.io/runa/cli/)
|
|
58
|
+
|
|
59
|
+
## Read the Zen of Runa
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python -c "from runa import this"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Contributing
|
|
66
|
+
|
|
67
|
+
We encourage you to contribute to Runa! Check out [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
Runa is released under the [MIT License](./LICENSE).
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "runa-ai"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "The application framework for agentic AI."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.14"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"anthropic>=0.75.0",
|
|
11
|
+
"graphviz>=0.21",
|
|
12
|
+
"httpx2>=2.12.0",
|
|
13
|
+
"mcp>=2.1.1",
|
|
14
|
+
"mkdocs-material>=9.7.7",
|
|
15
|
+
"pydantic>=2.9.0",
|
|
16
|
+
"pypdf>=6.0.0",
|
|
17
|
+
"sqlite-vec>=0.1.9",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[[project.authors]]
|
|
21
|
+
name = "Brahim Benyous"
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
postgres = [
|
|
25
|
+
"asyncpg>=0.30.0",
|
|
26
|
+
"pgvector>=0.3.6",
|
|
27
|
+
]
|
|
28
|
+
redis = ["redis>=5.2.0"]
|
|
29
|
+
ui = [
|
|
30
|
+
"fastapi>=0.121.0",
|
|
31
|
+
"uvicorn>=0.38.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
runa = "runa.cli.main:main"
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest>=9.1.1",
|
|
40
|
+
"ruff>=0.16.4",
|
|
41
|
+
"pyright>=1.1.400",
|
|
42
|
+
"python-dotenv>=1.2.3",
|
|
43
|
+
"httpx>=0.28.0",
|
|
44
|
+
"runa[postgres,redis,ui]",
|
|
45
|
+
"mkdocs>=1.6.1",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[build-system]
|
|
49
|
+
requires = ["uv_build >= 0.12.10, <0.13.0"]
|
|
50
|
+
build-backend = "uv_build"
|
|
51
|
+
|
|
52
|
+
[tool.uv.build-backend]
|
|
53
|
+
module-name = "runa"
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
testpaths = ["tests"]
|
|
57
|
+
|
|
58
|
+
[tool.ruff]
|
|
59
|
+
line-length = 100
|
|
60
|
+
target-version = "py314"
|
|
61
|
+
|
|
62
|
+
[tool.ruff.lint]
|
|
63
|
+
select = [
|
|
64
|
+
"E",
|
|
65
|
+
"F",
|
|
66
|
+
"I",
|
|
67
|
+
"B",
|
|
68
|
+
"SIM",
|
|
69
|
+
"UP",
|
|
70
|
+
"D",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[tool.ruff.lint.pydocstyle]
|
|
74
|
+
convention = "google"
|
|
75
|
+
|
|
76
|
+
[tool.ruff.format]
|
|
77
|
+
quote-style = "double"
|
|
78
|
+
indent-style = "space"
|
|
79
|
+
line-ending = "auto"
|
|
80
|
+
|
|
81
|
+
[tool.pyright]
|
|
82
|
+
include = [
|
|
83
|
+
"src",
|
|
84
|
+
"tests",
|
|
85
|
+
"examples",
|
|
86
|
+
]
|
|
87
|
+
reportIncompatibleMethodOverride = false
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "runa-ai"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name = "Brahim Benyous" },
|
|
6
|
+
]
|
|
7
|
+
description = "The application framework for agentic AI."
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
license = "MIT"
|
|
10
|
+
license-files = ["LICENSE"]
|
|
11
|
+
requires-python = ">=3.14"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"anthropic>=0.75.0",
|
|
14
|
+
"graphviz>=0.21",
|
|
15
|
+
"httpx2>=2.12.0",
|
|
16
|
+
"mcp>=2.1.1",
|
|
17
|
+
"mkdocs-material>=9.7.7",
|
|
18
|
+
"pydantic>=2.9.0",
|
|
19
|
+
"pypdf>=6.0.0",
|
|
20
|
+
"sqlite-vec>=0.1.9",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
postgres = ["asyncpg>=0.30.0", "pgvector>=0.3.6"]
|
|
25
|
+
redis = ["redis>=5.2.0"]
|
|
26
|
+
ui = ["fastapi>=0.121.0", "uvicorn>=0.38.0"]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
runa = "runa.cli.main:main"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"pytest>=9.1.1",
|
|
34
|
+
"ruff>=0.16.4",
|
|
35
|
+
"pyright>=1.1.400",
|
|
36
|
+
"python-dotenv>=1.2.3",
|
|
37
|
+
"httpx>=0.28.0",
|
|
38
|
+
"runa[postgres,redis,ui]",
|
|
39
|
+
"mkdocs>=1.6.1",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[build-system]
|
|
43
|
+
requires = ["uv_build >= 0.12.10, <0.13.0"]
|
|
44
|
+
build-backend = "uv_build"
|
|
45
|
+
|
|
46
|
+
[tool.uv.build-backend]
|
|
47
|
+
module-name = "runa"
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
testpaths = ["tests"]
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
line-length = 100
|
|
54
|
+
target-version = "py314"
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
select = [
|
|
58
|
+
"E", # pycodestyle errors
|
|
59
|
+
"F", # Pyflakes
|
|
60
|
+
"I", # isort
|
|
61
|
+
"B", # flake8-bugbear
|
|
62
|
+
"SIM", # flake8-simplify
|
|
63
|
+
"UP", # pyupgrade
|
|
64
|
+
"D", # docstring
|
|
65
|
+
]
|
|
66
|
+
[tool.ruff.lint.pydocstyle]
|
|
67
|
+
convention = "google"
|
|
68
|
+
|
|
69
|
+
[tool.ruff.format]
|
|
70
|
+
quote-style = "double"
|
|
71
|
+
indent-style = "space"
|
|
72
|
+
line-ending = "auto"
|
|
73
|
+
|
|
74
|
+
[tool.pyright]
|
|
75
|
+
include = ["src", "tests", "examples"]
|
|
76
|
+
reportIncompatibleMethodOverride = false
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Runa: an opinionated framework for agentic AI."""
|
|
2
|
+
|
|
3
|
+
from runa.agent import Agent
|
|
4
|
+
from runa.approval import approval
|
|
5
|
+
from runa.cache import Cache, MemoryCache, SQLiteCache
|
|
6
|
+
from runa.eval import (
|
|
7
|
+
DEFAULT_THRESHOLDS,
|
|
8
|
+
Case,
|
|
9
|
+
CaseReport,
|
|
10
|
+
Dataset,
|
|
11
|
+
EvaluationResult,
|
|
12
|
+
Report,
|
|
13
|
+
Status,
|
|
14
|
+
)
|
|
15
|
+
from runa.guardrail import guardrail
|
|
16
|
+
from runa.knowledge import Knowledge, KnowledgeMatch
|
|
17
|
+
from runa.lifecycle import AgentHooks, LoggingAgentHooks, LoggingRunHooks, RunHooks
|
|
18
|
+
from runa.mcp import MCPServer, MCPServerStdio, MCPServerStreamableHttp
|
|
19
|
+
from runa.memory import Memory, MemoryMatch
|
|
20
|
+
from runa.result import RunResult, RunResultStreaming
|
|
21
|
+
from runa.run import Run
|
|
22
|
+
from runa.run_config import RunConfig
|
|
23
|
+
from runa.run_state import Interruption, RunState
|
|
24
|
+
from runa.runner import Runner
|
|
25
|
+
from runa.session import SQLiteSession
|
|
26
|
+
from runa.stream_events import (
|
|
27
|
+
AgentUpdatedStreamEvent,
|
|
28
|
+
RawResponsesStreamEvent,
|
|
29
|
+
RunItemStreamEvent,
|
|
30
|
+
StreamEvent,
|
|
31
|
+
)
|
|
32
|
+
from runa.tool import tool
|
|
33
|
+
from runa.tracing import ConsoleExporter, Span, SQLiteExporter, Trace, TraceExporter, observe
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
"DEFAULT_THRESHOLDS",
|
|
37
|
+
"Agent",
|
|
38
|
+
"AgentHooks",
|
|
39
|
+
"AgentUpdatedStreamEvent",
|
|
40
|
+
"Cache",
|
|
41
|
+
"Case",
|
|
42
|
+
"CaseReport",
|
|
43
|
+
"ConsoleExporter",
|
|
44
|
+
"Dataset",
|
|
45
|
+
"EvaluationResult",
|
|
46
|
+
"Interruption",
|
|
47
|
+
"Knowledge",
|
|
48
|
+
"KnowledgeMatch",
|
|
49
|
+
"LoggingAgentHooks",
|
|
50
|
+
"LoggingRunHooks",
|
|
51
|
+
"MCPServer",
|
|
52
|
+
"MCPServerStdio",
|
|
53
|
+
"MCPServerStreamableHttp",
|
|
54
|
+
"Memory",
|
|
55
|
+
"MemoryCache",
|
|
56
|
+
"MemoryMatch",
|
|
57
|
+
"RawResponsesStreamEvent",
|
|
58
|
+
"Report",
|
|
59
|
+
"Run",
|
|
60
|
+
"RunConfig",
|
|
61
|
+
"RunHooks",
|
|
62
|
+
"RunItemStreamEvent",
|
|
63
|
+
"RunResult",
|
|
64
|
+
"RunResultStreaming",
|
|
65
|
+
"RunState",
|
|
66
|
+
"Runner",
|
|
67
|
+
"SQLiteCache",
|
|
68
|
+
"SQLiteExporter",
|
|
69
|
+
"SQLiteSession",
|
|
70
|
+
"Span",
|
|
71
|
+
"Status",
|
|
72
|
+
"StreamEvent",
|
|
73
|
+
"Trace",
|
|
74
|
+
"TraceExporter",
|
|
75
|
+
"approval",
|
|
76
|
+
"guardrail",
|
|
77
|
+
"observe",
|
|
78
|
+
"tool",
|
|
79
|
+
]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""_graph.py: `draw_graph`, a small DOT-graph generator behind `Agent.graph`.
|
|
2
|
+
|
|
3
|
+
Not a port of `agents.extensions.visualization` -- just enough to show an agent's own tools and
|
|
4
|
+
handoffs (recursively) as a Graphviz digraph, since that's all `Agent.graph` ever promised.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from graphviz import Digraph, Source
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _agent_node_id(agent: Any) -> str:
|
|
16
|
+
return f"agent_{id(agent)}"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _add_agent(dot: Digraph, agent: Any, seen: set[int]) -> None:
|
|
20
|
+
if id(agent) in seen:
|
|
21
|
+
return
|
|
22
|
+
seen.add(id(agent))
|
|
23
|
+
node_id = _agent_node_id(agent)
|
|
24
|
+
dot.node(node_id, agent.name, shape="ellipse", style="filled", fillcolor="lightblue")
|
|
25
|
+
|
|
26
|
+
for tool in getattr(agent, "tools", []) or []:
|
|
27
|
+
tool_id = f"tool_{id(tool)}"
|
|
28
|
+
dot.node(
|
|
29
|
+
tool_id,
|
|
30
|
+
getattr(tool, "name", str(tool)),
|
|
31
|
+
shape="box",
|
|
32
|
+
style="filled",
|
|
33
|
+
fillcolor="lightyellow",
|
|
34
|
+
)
|
|
35
|
+
dot.edge(node_id, tool_id)
|
|
36
|
+
|
|
37
|
+
for server in getattr(agent, "mcp_servers", []) or []:
|
|
38
|
+
server_id = f"mcp_{id(server)}"
|
|
39
|
+
dot.node(
|
|
40
|
+
server_id,
|
|
41
|
+
getattr(server, "name", "mcp"),
|
|
42
|
+
shape="box",
|
|
43
|
+
style="filled,dashed",
|
|
44
|
+
fillcolor="lightgrey",
|
|
45
|
+
)
|
|
46
|
+
dot.edge(node_id, server_id)
|
|
47
|
+
|
|
48
|
+
for handoff in getattr(agent, "handoffs", []) or []:
|
|
49
|
+
target = getattr(handoff, "agent", handoff)
|
|
50
|
+
dot.edge(node_id, _agent_node_id(target), style="dashed")
|
|
51
|
+
_add_agent(dot, target, seen)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def draw_graph(agent: Any) -> Source:
|
|
55
|
+
"""Render `agent`, and its tools/handoffs/MCP servers (recursively), as a Graphviz `Source`."""
|
|
56
|
+
from graphviz import Digraph
|
|
57
|
+
|
|
58
|
+
dot = Digraph()
|
|
59
|
+
_add_agent(dot, agent, set())
|
|
60
|
+
return dot.unflatten(stagger=3)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
__all__ = ["draw_graph"]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""`runa._models`: Runa's own model provider — two backends, no `openai-agents`, no `openai` SDK.
|
|
2
|
+
|
|
3
|
+
`ModelProvider.get_model` maps a model name's prefix to a backend. A name starting with `claude`
|
|
4
|
+
goes through `AnthropicModel`, talking to Anthropic's own SDK directly — Anthropic's Messages API
|
|
5
|
+
isn't chat-completions-shaped, so it's the one backend that needs real translation. Everything else
|
|
6
|
+
(`gpt-*`, `gemini-*`, `llama-*`, `deepseek-*`, `qwen-*`, or an unrecognized/bare name) goes through
|
|
7
|
+
`OpenAICompatibleModel`, which speaks the chat-completions wire format that OpenAI, Gemini, Llama,
|
|
8
|
+
DeepSeek, and Qwen all share — over plain HTTP via `httpx2`, not the `openai` package.
|
|
9
|
+
|
|
10
|
+
Conversation items are plain chat-completions-shaped message dicts everywhere in Runa (see
|
|
11
|
+
`runa._types.TResponseInputItem`); `AnthropicModel` is the only place that ever converts away from
|
|
12
|
+
that shape. Tools/handoffs are read structurally here (`.name`/`.description`/`.params_json_schema`
|
|
13
|
+
for a tool, `.tool_name`/`.tool_description` for a handoff) rather than importing their concrete
|
|
14
|
+
types, so this package has no dependency on `runa.tool`/`runa.handoff`.
|
|
15
|
+
|
|
16
|
+
Split by concern: `interface` (the `Model` protocol, `StreamDelta`, shared wire-format helpers),
|
|
17
|
+
`openai_chatcompletions` (the chat-completions backend), `anthropic` (the Claude backend), and
|
|
18
|
+
`multi_provider` (`ModelProvider`, routing a model name to one of the two).
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from runa._models.anthropic import AnthropicModel
|
|
22
|
+
from runa._models.anthropic import _anthropic_deltas as _anthropic_deltas
|
|
23
|
+
from runa._models.anthropic import _check_plain_text_output as _check_plain_text_output
|
|
24
|
+
from runa._models.anthropic import _to_anthropic_messages as _to_anthropic_messages
|
|
25
|
+
from runa._models.anthropic import _to_anthropic_tool as _to_anthropic_tool
|
|
26
|
+
from runa._models.anthropic import _to_anthropic_tool_choice as _to_anthropic_tool_choice
|
|
27
|
+
from runa._models.anthropic import _to_chat_message as _to_chat_message
|
|
28
|
+
from runa._models.anthropic import _to_usage as _to_usage
|
|
29
|
+
from runa._models.interface import Model, StreamDelta
|
|
30
|
+
from runa._models.multi_provider import ModelProvider
|
|
31
|
+
from runa._models.openai_chatcompletions import OpenAICompatibleModel
|
|
32
|
+
|
|
33
|
+
__all__ = ["AnthropicModel", "Model", "ModelProvider", "OpenAICompatibleModel", "StreamDelta"]
|