meristem 4.0.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.
- meristem-4.0.0/LICENSE +21 -0
- meristem-4.0.0/PKG-INFO +180 -0
- meristem-4.0.0/README.md +155 -0
- meristem-4.0.0/agent_utilities/__init__.py +32 -0
- meristem-4.0.0/agent_utilities/__main__.py +15 -0
- meristem-4.0.0/agent_utilities/_version.py +3 -0
- meristem-4.0.0/agent_utilities/core/__init__.py +1 -0
- meristem-4.0.0/agent_utilities/core/paths.py +435 -0
- meristem-4.0.0/agent_utilities/graph/__init__.py +61 -0
- meristem-4.0.0/agent_utilities/graph/budget.py +164 -0
- meristem-4.0.0/agent_utilities/graph/builder.py +125 -0
- meristem-4.0.0/agent_utilities/graph/dependency.py +321 -0
- meristem-4.0.0/agent_utilities/graph/executor.py +492 -0
- meristem-4.0.0/agent_utilities/graph/metrics.py +94 -0
- meristem-4.0.0/agent_utilities/graph/runner.py +132 -0
- meristem-4.0.0/agent_utilities/graph/state.py +392 -0
- meristem-4.0.0/agent_utilities/graph/text_only.py +194 -0
- meristem-4.0.0/agent_utilities/harness/__init__.py +62 -0
- meristem-4.0.0/agent_utilities/harness/client_capabilities.py +131 -0
- meristem-4.0.0/agent_utilities/harness/constraint_engine.py +352 -0
- meristem-4.0.0/agent_utilities/harness/contract_validator.py +91 -0
- meristem-4.0.0/agent_utilities/harness/conversation_history.py +51 -0
- meristem-4.0.0/agent_utilities/harness/edit_engine.py +642 -0
- meristem-4.0.0/agent_utilities/harness/harness_cycle.py +765 -0
- meristem-4.0.0/agent_utilities/harness/hosted_run.py +34 -0
- meristem-4.0.0/agent_utilities/harness/plan.py +57 -0
- meristem-4.0.0/agent_utilities/harness/plan_runtime.py +119 -0
- meristem-4.0.0/agent_utilities/harness/quality_gates.py +233 -0
- meristem-4.0.0/agent_utilities/host_ports.py +575 -0
- meristem-4.0.0/agent_utilities/py.typed +0 -0
- meristem-4.0.0/agent_utilities/rlm/__init__.py +13 -0
- meristem-4.0.0/agent_utilities/rlm/runner.py +222 -0
- meristem-4.0.0/agent_utilities/rlm/telemetry.py +64 -0
- meristem-4.0.0/agent_utilities/runtime/__init__.py +118 -0
- meristem-4.0.0/agent_utilities/runtime/bridge.py +441 -0
- meristem-4.0.0/agent_utilities/runtime/browser_tier.py +32 -0
- meristem-4.0.0/agent_utilities/runtime/computer_use_tier.py +29 -0
- meristem-4.0.0/agent_utilities/runtime/docker_workspace.py +181 -0
- meristem-4.0.0/agent_utilities/runtime/events.py +301 -0
- meristem-4.0.0/agent_utilities/runtime/local_workspace.py +50 -0
- meristem-4.0.0/agent_utilities/runtime/provenance.py +41 -0
- meristem-4.0.0/agent_utilities/runtime/workspace.py +206 -0
- meristem-4.0.0/meristem.egg-info/PKG-INFO +180 -0
- meristem-4.0.0/meristem.egg-info/SOURCES.txt +69 -0
- meristem-4.0.0/meristem.egg-info/dependency_links.txt +1 -0
- meristem-4.0.0/meristem.egg-info/entry_points.txt +2 -0
- meristem-4.0.0/meristem.egg-info/requires.txt +8 -0
- meristem-4.0.0/meristem.egg-info/top_level.txt +1 -0
- meristem-4.0.0/pyproject.toml +87 -0
- meristem-4.0.0/setup.cfg +4 -0
- meristem-4.0.0/tests/test_client_capabilities.py +194 -0
- meristem-4.0.0/tests/test_constraint_engine.py +62 -0
- meristem-4.0.0/tests/test_contract_validator.py +74 -0
- meristem-4.0.0/tests/test_conversation_history.py +415 -0
- meristem-4.0.0/tests/test_dependency.py +987 -0
- meristem-4.0.0/tests/test_edit_engine.py +151 -0
- meristem-4.0.0/tests/test_graph_metrics.py +131 -0
- meristem-4.0.0/tests/test_harness_plan.py +145 -0
- meristem-4.0.0/tests/test_host_ports.py +256 -0
- meristem-4.0.0/tests/test_hosted_run.py +446 -0
- meristem-4.0.0/tests/test_paths.py +90 -0
- meristem-4.0.0/tests/test_plan_runtime.py +419 -0
- meristem-4.0.0/tests/test_quality_gates.py +76 -0
- meristem-4.0.0/tests/test_release_config.py +20 -0
- meristem-4.0.0/tests/test_retired_deployment_sparql_images.py +131 -0
- meristem-4.0.0/tests/test_retired_manifest_compiler_finance.py +169 -0
- meristem-4.0.0/tests/test_retired_quantum_security_standardization.py +202 -0
- meristem-4.0.0/tests/test_rlm.py +345 -0
- meristem-4.0.0/tests/test_run_loop.py +2012 -0
- meristem-4.0.0/tests/test_runtime.py +234 -0
- meristem-4.0.0/tests/test_text_only.py +312 -0
meristem-4.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Knuckles Team
|
|
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.
|
meristem-4.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: meristem
|
|
3
|
+
Version: 4.0.0
|
|
4
|
+
Summary: Meristem, the in-run agent harness for explicit dependency DAGs and received plans: the agent run loop, edit application, tool contracts, constraints, pre-emit gates, the developer workspace and the host ports arbora fills
|
|
5
|
+
Author-email: Repository Maintainers <maintainers@knuckles.team>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: pydantic<2.15.0.dev0,>=2.14.1
|
|
18
|
+
Requires-Dist: platformdirs>=4.13.3
|
|
19
|
+
Requires-Dist: pydantic-ai-slim==2.57.0
|
|
20
|
+
Requires-Dist: pydantic-graph==2.57.0
|
|
21
|
+
Requires-Dist: pydantic-ai-harness<0.58.0,>=0.57.0
|
|
22
|
+
Provides-Extra: openai
|
|
23
|
+
Requires-Dist: pydantic-ai-slim[openai]==2.57.0; extra == "openai"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# Meristem
|
|
27
|
+
|
|
28
|
+
**The in-run agent harness.** Meristem supports and guides agent execution
|
|
29
|
+
through explicit dependency DAGs and received ordered plans. Inspired by
|
|
30
|
+
espalier-trained growth, it provides structure for execution, not model-weight
|
|
31
|
+
training. It applies the decisions it is given; it does not store, decide,
|
|
32
|
+
serve or connect on its own.
|
|
33
|
+
|
|
34
|
+
Meristem is distributed as `agent-utilities` and imported as `agent_utilities`.
|
|
35
|
+
Repository, package, CLI and API identifiers remain unchanged.
|
|
36
|
+
|
|
37
|
+
[](https://pypi.org/project/agent-utilities/)
|
|
38
|
+
[](https://github.com/Knuckles-Team/agent-utilities/actions/workflows/release.yml)
|
|
39
|
+
|
|
40
|
+
*Version: 4.0.0*
|
|
41
|
+
|
|
42
|
+
## What it contains
|
|
43
|
+
|
|
44
|
+
| Module | What it does inside one run |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `agent_utilities.graph` | Applies a received ordered plan or dependency DAG. It enforces task slots and shared budgets, and emits ordered execution events. |
|
|
47
|
+
| `agent_utilities.rlm` | Runs recursive model queries with shared request and tool limits and bounded concurrent model requests. |
|
|
48
|
+
| `agent_utilities.harness.edit_engine` | Parses model-proposed edits (search/replace blocks, unified diffs), applies them with graduated matching, and re-prompts on malformed or unmatched edits. |
|
|
49
|
+
| `agent_utilities.harness.contract_validator` | Checks a tool call's pre-conditions and its output's schema and verifier. |
|
|
50
|
+
| `agent_utilities.harness.constraint_engine` | Enforces hierarchical constraints on tool calls (prompt, tool description, middleware, implementation) and escalates repeated violations. |
|
|
51
|
+
| `agent_utilities.harness.quality_gates` | The pre-emit gate: antipattern detection, a preflight checklist and a multi-dimensional critique, in warn or block mode. |
|
|
52
|
+
| `agent_utilities.runtime` | The developer workspace: typed actions and observations, a stateful shell, local and container backends, a policy gate it is given, and the browser and computer-use tier ports. |
|
|
53
|
+
| `agent_utilities.host_ports` | The protocols the host fills: native and remote toolsets, tool clients, outbound credentials, delegated identity, the fleet catalog and the session keepalive. Without a host every binding port fails closed. |
|
|
54
|
+
| `agent_utilities.core.paths` | Resolves the platform config, data, cache and log directories (`ARBORA_CONFIG_DIR`, XDG). |
|
|
55
|
+
|
|
56
|
+
## Where everything else lives
|
|
57
|
+
|
|
58
|
+
- **[Medulla](https://github.com/Knuckles-Team/epistemic-graph)**: facts, records,
|
|
59
|
+
vocabulary, storage and queries, ingest, retrieval, reasoning, memory, decisions, and
|
|
60
|
+
learning (evaluation, harness evolution, reward and trace records).
|
|
61
|
+
- **[arbora](https://github.com/Knuckles-Team/arbora)**: admission, auth, served
|
|
62
|
+
operations (MCP, REST, A2A), messaging front-ends, the registry and the multiplexer.
|
|
63
|
+
arbora hosts this harness and registers the `host_ports` providers.
|
|
64
|
+
- **[Scion SDK](https://github.com/Knuckles-Team/agent-connector-sdk)**:
|
|
65
|
+
connector contracts, transports, the A2A protocol library and connector helpers.
|
|
66
|
+
|
|
67
|
+
## Install and use
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install agent-utilities
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from agent_utilities.runtime import create_workspace
|
|
75
|
+
from agent_utilities.runtime.events import CmdRunAction, TestRunAction
|
|
76
|
+
|
|
77
|
+
async with create_workspace(run_id="r1", prefer_docker=False) as ws:
|
|
78
|
+
await ws.act(CmdRunAction(command="git status"))
|
|
79
|
+
result = await ws.act(TestRunAction(selector="tests"))
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Run measurements
|
|
83
|
+
|
|
84
|
+
The graph run result and terminal event include `metrics` from a monotonic
|
|
85
|
+
client clock: `run_elapsed_ms` and ordered `model_requests` with
|
|
86
|
+
`client_request_elapsed_ms`, outcome, model/provider attribution and validated
|
|
87
|
+
per-response token counts. The sample list is bounded; `coverage: "partial"`
|
|
88
|
+
means some observed requests were omitted. Failed requests have no invented
|
|
89
|
+
token counts. These measurements are emitted through the host event sink for
|
|
90
|
+
shared backend consumption; AU stores no session totals.
|
|
91
|
+
|
|
92
|
+
Run time includes planning, tools and retries. Client request time includes
|
|
93
|
+
transport and provider waiting. Neither is provider generation time, and neither
|
|
94
|
+
is used to derive generation TPS. Provider queue wait, generation duration and
|
|
95
|
+
TTFT are absent unless a future adapter measures and identifies them explicitly.
|
|
96
|
+
|
|
97
|
+
## Received dependency plans
|
|
98
|
+
|
|
99
|
+
A host can pass `RunPlan(dependency_plan=DependencyPlan(...))` to the same
|
|
100
|
+
`run` or `iterate_run` entry point. Do not also set serial `steps`.
|
|
101
|
+
`DependencyPlan` contains ordered `RunTask(task_id, prompt, depends_on)` values,
|
|
102
|
+
an `output_task_id`, a `max_concurrency` task cap and an optional `plan_id`.
|
|
103
|
+
The host gets the plan from EG and admits it through Arbora. AU does not turn
|
|
104
|
+
free text into a plan or authorize a task.
|
|
105
|
+
|
|
106
|
+
A completed task frees a slot at once. A dependent task can start while an
|
|
107
|
+
unrelated task still runs. Every prerequisite must succeed. Each task gets a
|
|
108
|
+
fresh history with only its direct dependency outputs. The output task must
|
|
109
|
+
be the sole sink. Failed or stopped plans never return a partial child answer
|
|
110
|
+
as a completed parent result.
|
|
111
|
+
|
|
112
|
+
The trusted host can pass prior measured consumption as `RunPlan.initial_usage`
|
|
113
|
+
(a `pydantic_ai.usage.RunUsage`) and `initial_elapsed_seconds`. Both default to
|
|
114
|
+
zero. Keep `RunBudget` at its original bounds; do not subtract this usage in
|
|
115
|
+
the host or add it to AU's result again. AU snapshots the reported request,
|
|
116
|
+
tool and token counters. It includes them once in terminal aggregate usage.
|
|
117
|
+
It subtracts the elapsed time once from the execution deadline. Exhausted initial
|
|
118
|
+
model bounds stop before model binding or child dispatch. Prior tool usage above
|
|
119
|
+
the tool limit also stops. At the exact tool limit, model-only answers remain
|
|
120
|
+
allowed, but additional tools do not. Invalid counters or time
|
|
121
|
+
fail closed. Model proposals, request metadata and scaffold updates cannot
|
|
122
|
+
set this host-only input. Unreported token usage remains zero, not an estimate.
|
|
123
|
+
|
|
124
|
+
If measured host work fails before a plan can return, the decision provider can
|
|
125
|
+
raise `RunPlanFailure(error, initial_usage=usage, initial_elapsed_seconds=elapsed)`.
|
|
126
|
+
AU validates the same inputs and includes the counters once in the terminal
|
|
127
|
+
event and result. It preserves the original failure or cancellation, without
|
|
128
|
+
dispatching work or replacing a budget. Do not wrap a provider failure without
|
|
129
|
+
a reported usage ledger or add these counters again in the host.
|
|
130
|
+
|
|
131
|
+
`run()` returns a failed `RunResult`. `AgentRunExecutor.execute_agent()` raises
|
|
132
|
+
`RunFailed`, a `RuntimeError` subclass with the same error message. Its immutable
|
|
133
|
+
`result` snapshot retains that aggregate receipt, with `run_id` and `usage`
|
|
134
|
+
properties. The allowed host facade `agent_utilities.runtime` lazily re-exports
|
|
135
|
+
the same run executor, plans, tasks, bounds, stop rule and failure types.
|
|
136
|
+
Hosts must check the exception type and expected run identity
|
|
137
|
+
before copying these counters. Keep the outcome failed; do not publish a
|
|
138
|
+
partial answer or add the counters again. Successful and stopped returns,
|
|
139
|
+
cancellation, and empty unreported ledgers keep their existing behavior.
|
|
140
|
+
|
|
141
|
+
Request and tool reservations are shared across tasks and validation retries.
|
|
142
|
+
An unspecified parallel tool limit uses a finite fallback of fifty calls.
|
|
143
|
+
Token limits use reported usage, including fallback attempts. In-flight token
|
|
144
|
+
use is not known in advance. `RunBudget.max_concurrent_requests` also caps
|
|
145
|
+
model requests (fallback: four); the task cap can be lower. On cancellation,
|
|
146
|
+
AU drains child coroutines before invoking host-scope exit. Hosts own the
|
|
147
|
+
cancellation safety of their asynchronous scope exits; repeated cancellation
|
|
148
|
+
can interrupt that host cleanup. Host tools also own external work that cannot
|
|
149
|
+
stop with their coroutine. No elapsed cleanup bound is promised for handlers
|
|
150
|
+
that do not cooperate.
|
|
151
|
+
|
|
152
|
+
`RLMConfig.max_concurrent_requests` and `tool_calls_limit` bound recursive
|
|
153
|
+
model calls and tool fan-out (fallbacks: four and fifty). A parent releases its
|
|
154
|
+
model-request slot before waiting for a child, including at capacity one.
|
|
155
|
+
The parent model still chooses its next tool batch after the current batch
|
|
156
|
+
returns. That model-choice boundary is not a declared dependency DAG.
|
|
157
|
+
|
|
158
|
+
Public lifecycle events have a per-run `sequence` and stable `event_id`.
|
|
159
|
+
Task events carry `task_id`, `parent_run_id`, `plan_id` and `depends_on`.
|
|
160
|
+
They report execution state, not private model reasoning. Arbora owns their
|
|
161
|
+
safe replay projection and access checks.
|
|
162
|
+
|
|
163
|
+
A DAG driver owns the deadline after setup, using the same absolute deadline.
|
|
164
|
+
A paused event reader cannot delay task dispatch or timeout cleanup. Consumers
|
|
165
|
+
must finish or close the iterator. Pausing can delay the parent terminal event
|
|
166
|
+
and host-scope release, even after all task work has stopped. Request handlers
|
|
167
|
+
finish asynchronous cleanup before cancellation returns, including nested runs.
|
|
168
|
+
|
|
169
|
+
## Develop
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uv sync --group dev
|
|
173
|
+
uv run ruff check . && uv run ruff format --check .
|
|
174
|
+
uv run mypy agent_utilities
|
|
175
|
+
uv run pytest -q
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT, see [LICENSE](LICENSE).
|
meristem-4.0.0/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Meristem
|
|
2
|
+
|
|
3
|
+
**The in-run agent harness.** Meristem supports and guides agent execution
|
|
4
|
+
through explicit dependency DAGs and received ordered plans. Inspired by
|
|
5
|
+
espalier-trained growth, it provides structure for execution, not model-weight
|
|
6
|
+
training. It applies the decisions it is given; it does not store, decide,
|
|
7
|
+
serve or connect on its own.
|
|
8
|
+
|
|
9
|
+
Meristem is distributed as `agent-utilities` and imported as `agent_utilities`.
|
|
10
|
+
Repository, package, CLI and API identifiers remain unchanged.
|
|
11
|
+
|
|
12
|
+
[](https://pypi.org/project/agent-utilities/)
|
|
13
|
+
[](https://github.com/Knuckles-Team/agent-utilities/actions/workflows/release.yml)
|
|
14
|
+
|
|
15
|
+
*Version: 4.0.0*
|
|
16
|
+
|
|
17
|
+
## What it contains
|
|
18
|
+
|
|
19
|
+
| Module | What it does inside one run |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `agent_utilities.graph` | Applies a received ordered plan or dependency DAG. It enforces task slots and shared budgets, and emits ordered execution events. |
|
|
22
|
+
| `agent_utilities.rlm` | Runs recursive model queries with shared request and tool limits and bounded concurrent model requests. |
|
|
23
|
+
| `agent_utilities.harness.edit_engine` | Parses model-proposed edits (search/replace blocks, unified diffs), applies them with graduated matching, and re-prompts on malformed or unmatched edits. |
|
|
24
|
+
| `agent_utilities.harness.contract_validator` | Checks a tool call's pre-conditions and its output's schema and verifier. |
|
|
25
|
+
| `agent_utilities.harness.constraint_engine` | Enforces hierarchical constraints on tool calls (prompt, tool description, middleware, implementation) and escalates repeated violations. |
|
|
26
|
+
| `agent_utilities.harness.quality_gates` | The pre-emit gate: antipattern detection, a preflight checklist and a multi-dimensional critique, in warn or block mode. |
|
|
27
|
+
| `agent_utilities.runtime` | The developer workspace: typed actions and observations, a stateful shell, local and container backends, a policy gate it is given, and the browser and computer-use tier ports. |
|
|
28
|
+
| `agent_utilities.host_ports` | The protocols the host fills: native and remote toolsets, tool clients, outbound credentials, delegated identity, the fleet catalog and the session keepalive. Without a host every binding port fails closed. |
|
|
29
|
+
| `agent_utilities.core.paths` | Resolves the platform config, data, cache and log directories (`ARBORA_CONFIG_DIR`, XDG). |
|
|
30
|
+
|
|
31
|
+
## Where everything else lives
|
|
32
|
+
|
|
33
|
+
- **[Medulla](https://github.com/Knuckles-Team/epistemic-graph)**: facts, records,
|
|
34
|
+
vocabulary, storage and queries, ingest, retrieval, reasoning, memory, decisions, and
|
|
35
|
+
learning (evaluation, harness evolution, reward and trace records).
|
|
36
|
+
- **[arbora](https://github.com/Knuckles-Team/arbora)**: admission, auth, served
|
|
37
|
+
operations (MCP, REST, A2A), messaging front-ends, the registry and the multiplexer.
|
|
38
|
+
arbora hosts this harness and registers the `host_ports` providers.
|
|
39
|
+
- **[Scion SDK](https://github.com/Knuckles-Team/agent-connector-sdk)**:
|
|
40
|
+
connector contracts, transports, the A2A protocol library and connector helpers.
|
|
41
|
+
|
|
42
|
+
## Install and use
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install agent-utilities
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from agent_utilities.runtime import create_workspace
|
|
50
|
+
from agent_utilities.runtime.events import CmdRunAction, TestRunAction
|
|
51
|
+
|
|
52
|
+
async with create_workspace(run_id="r1", prefer_docker=False) as ws:
|
|
53
|
+
await ws.act(CmdRunAction(command="git status"))
|
|
54
|
+
result = await ws.act(TestRunAction(selector="tests"))
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Run measurements
|
|
58
|
+
|
|
59
|
+
The graph run result and terminal event include `metrics` from a monotonic
|
|
60
|
+
client clock: `run_elapsed_ms` and ordered `model_requests` with
|
|
61
|
+
`client_request_elapsed_ms`, outcome, model/provider attribution and validated
|
|
62
|
+
per-response token counts. The sample list is bounded; `coverage: "partial"`
|
|
63
|
+
means some observed requests were omitted. Failed requests have no invented
|
|
64
|
+
token counts. These measurements are emitted through the host event sink for
|
|
65
|
+
shared backend consumption; AU stores no session totals.
|
|
66
|
+
|
|
67
|
+
Run time includes planning, tools and retries. Client request time includes
|
|
68
|
+
transport and provider waiting. Neither is provider generation time, and neither
|
|
69
|
+
is used to derive generation TPS. Provider queue wait, generation duration and
|
|
70
|
+
TTFT are absent unless a future adapter measures and identifies them explicitly.
|
|
71
|
+
|
|
72
|
+
## Received dependency plans
|
|
73
|
+
|
|
74
|
+
A host can pass `RunPlan(dependency_plan=DependencyPlan(...))` to the same
|
|
75
|
+
`run` or `iterate_run` entry point. Do not also set serial `steps`.
|
|
76
|
+
`DependencyPlan` contains ordered `RunTask(task_id, prompt, depends_on)` values,
|
|
77
|
+
an `output_task_id`, a `max_concurrency` task cap and an optional `plan_id`.
|
|
78
|
+
The host gets the plan from EG and admits it through Arbora. AU does not turn
|
|
79
|
+
free text into a plan or authorize a task.
|
|
80
|
+
|
|
81
|
+
A completed task frees a slot at once. A dependent task can start while an
|
|
82
|
+
unrelated task still runs. Every prerequisite must succeed. Each task gets a
|
|
83
|
+
fresh history with only its direct dependency outputs. The output task must
|
|
84
|
+
be the sole sink. Failed or stopped plans never return a partial child answer
|
|
85
|
+
as a completed parent result.
|
|
86
|
+
|
|
87
|
+
The trusted host can pass prior measured consumption as `RunPlan.initial_usage`
|
|
88
|
+
(a `pydantic_ai.usage.RunUsage`) and `initial_elapsed_seconds`. Both default to
|
|
89
|
+
zero. Keep `RunBudget` at its original bounds; do not subtract this usage in
|
|
90
|
+
the host or add it to AU's result again. AU snapshots the reported request,
|
|
91
|
+
tool and token counters. It includes them once in terminal aggregate usage.
|
|
92
|
+
It subtracts the elapsed time once from the execution deadline. Exhausted initial
|
|
93
|
+
model bounds stop before model binding or child dispatch. Prior tool usage above
|
|
94
|
+
the tool limit also stops. At the exact tool limit, model-only answers remain
|
|
95
|
+
allowed, but additional tools do not. Invalid counters or time
|
|
96
|
+
fail closed. Model proposals, request metadata and scaffold updates cannot
|
|
97
|
+
set this host-only input. Unreported token usage remains zero, not an estimate.
|
|
98
|
+
|
|
99
|
+
If measured host work fails before a plan can return, the decision provider can
|
|
100
|
+
raise `RunPlanFailure(error, initial_usage=usage, initial_elapsed_seconds=elapsed)`.
|
|
101
|
+
AU validates the same inputs and includes the counters once in the terminal
|
|
102
|
+
event and result. It preserves the original failure or cancellation, without
|
|
103
|
+
dispatching work or replacing a budget. Do not wrap a provider failure without
|
|
104
|
+
a reported usage ledger or add these counters again in the host.
|
|
105
|
+
|
|
106
|
+
`run()` returns a failed `RunResult`. `AgentRunExecutor.execute_agent()` raises
|
|
107
|
+
`RunFailed`, a `RuntimeError` subclass with the same error message. Its immutable
|
|
108
|
+
`result` snapshot retains that aggregate receipt, with `run_id` and `usage`
|
|
109
|
+
properties. The allowed host facade `agent_utilities.runtime` lazily re-exports
|
|
110
|
+
the same run executor, plans, tasks, bounds, stop rule and failure types.
|
|
111
|
+
Hosts must check the exception type and expected run identity
|
|
112
|
+
before copying these counters. Keep the outcome failed; do not publish a
|
|
113
|
+
partial answer or add the counters again. Successful and stopped returns,
|
|
114
|
+
cancellation, and empty unreported ledgers keep their existing behavior.
|
|
115
|
+
|
|
116
|
+
Request and tool reservations are shared across tasks and validation retries.
|
|
117
|
+
An unspecified parallel tool limit uses a finite fallback of fifty calls.
|
|
118
|
+
Token limits use reported usage, including fallback attempts. In-flight token
|
|
119
|
+
use is not known in advance. `RunBudget.max_concurrent_requests` also caps
|
|
120
|
+
model requests (fallback: four); the task cap can be lower. On cancellation,
|
|
121
|
+
AU drains child coroutines before invoking host-scope exit. Hosts own the
|
|
122
|
+
cancellation safety of their asynchronous scope exits; repeated cancellation
|
|
123
|
+
can interrupt that host cleanup. Host tools also own external work that cannot
|
|
124
|
+
stop with their coroutine. No elapsed cleanup bound is promised for handlers
|
|
125
|
+
that do not cooperate.
|
|
126
|
+
|
|
127
|
+
`RLMConfig.max_concurrent_requests` and `tool_calls_limit` bound recursive
|
|
128
|
+
model calls and tool fan-out (fallbacks: four and fifty). A parent releases its
|
|
129
|
+
model-request slot before waiting for a child, including at capacity one.
|
|
130
|
+
The parent model still chooses its next tool batch after the current batch
|
|
131
|
+
returns. That model-choice boundary is not a declared dependency DAG.
|
|
132
|
+
|
|
133
|
+
Public lifecycle events have a per-run `sequence` and stable `event_id`.
|
|
134
|
+
Task events carry `task_id`, `parent_run_id`, `plan_id` and `depends_on`.
|
|
135
|
+
They report execution state, not private model reasoning. Arbora owns their
|
|
136
|
+
safe replay projection and access checks.
|
|
137
|
+
|
|
138
|
+
A DAG driver owns the deadline after setup, using the same absolute deadline.
|
|
139
|
+
A paused event reader cannot delay task dispatch or timeout cleanup. Consumers
|
|
140
|
+
must finish or close the iterator. Pausing can delay the parent terminal event
|
|
141
|
+
and host-scope release, even after all task work has stopped. Request handlers
|
|
142
|
+
finish asynchronous cleanup before cancellation returns, including nested runs.
|
|
143
|
+
|
|
144
|
+
## Develop
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
uv sync --group dev
|
|
148
|
+
uv run ruff check . && uv run ruff format --check .
|
|
149
|
+
uv run mypy agent_utilities
|
|
150
|
+
uv run pytest -q
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## License
|
|
154
|
+
|
|
155
|
+
MIT, see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""agent-utilities: the in-run agent harness.
|
|
2
|
+
|
|
3
|
+
The harness holds only the mechanism inside one agent run: applying edits,
|
|
4
|
+
checking tool contracts and constraints, pre-emit gates, the developer
|
|
5
|
+
workspace action/observation loop, the agent run loop
|
|
6
|
+
(``agent_utilities.graph``, ``agent_utilities.rlm``) and the ``host_ports`` protocols through
|
|
7
|
+
which the host (arbora) supplies tools, credentials, models and trace sinks.
|
|
8
|
+
|
|
9
|
+
Facts, storage, retrieval, decisions and learning live in epistemic-graph;
|
|
10
|
+
serving, admission and the registry live in arbora; connector contracts and
|
|
11
|
+
transports live in agent-connector-sdk.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from agent_utilities._version import __version__
|
|
17
|
+
|
|
18
|
+
_GRAPH_EXPORTS = frozenset(
|
|
19
|
+
{"create_graph_agent", "execute_graph", "initialize_graph_from_workspace"}
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def __getattr__(name: str) -> Any:
|
|
24
|
+
"""Load the run-loop entry points on first use (keeps ``import`` light)."""
|
|
25
|
+
if name in _GRAPH_EXPORTS:
|
|
26
|
+
from agent_utilities import graph
|
|
27
|
+
|
|
28
|
+
return getattr(graph, name)
|
|
29
|
+
raise AttributeError(f"module 'agent_utilities' has no attribute {name!r}")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = ["__version__", *sorted(_GRAPH_EXPORTS)]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""``python -m agent_utilities``: print the harness version.
|
|
2
|
+
|
|
3
|
+
Meristem is the in-run agent harness. It serves nothing on its own;
|
|
4
|
+
arbora hosts it and serves its operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from agent_utilities._version import __version__
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
print(f"meristem {__version__} (in-run harness; hosted by arbora)")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Core harness plumbing: the platform config/paths resolver."""
|