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.
Files changed (71) hide show
  1. meristem-4.0.0/LICENSE +21 -0
  2. meristem-4.0.0/PKG-INFO +180 -0
  3. meristem-4.0.0/README.md +155 -0
  4. meristem-4.0.0/agent_utilities/__init__.py +32 -0
  5. meristem-4.0.0/agent_utilities/__main__.py +15 -0
  6. meristem-4.0.0/agent_utilities/_version.py +3 -0
  7. meristem-4.0.0/agent_utilities/core/__init__.py +1 -0
  8. meristem-4.0.0/agent_utilities/core/paths.py +435 -0
  9. meristem-4.0.0/agent_utilities/graph/__init__.py +61 -0
  10. meristem-4.0.0/agent_utilities/graph/budget.py +164 -0
  11. meristem-4.0.0/agent_utilities/graph/builder.py +125 -0
  12. meristem-4.0.0/agent_utilities/graph/dependency.py +321 -0
  13. meristem-4.0.0/agent_utilities/graph/executor.py +492 -0
  14. meristem-4.0.0/agent_utilities/graph/metrics.py +94 -0
  15. meristem-4.0.0/agent_utilities/graph/runner.py +132 -0
  16. meristem-4.0.0/agent_utilities/graph/state.py +392 -0
  17. meristem-4.0.0/agent_utilities/graph/text_only.py +194 -0
  18. meristem-4.0.0/agent_utilities/harness/__init__.py +62 -0
  19. meristem-4.0.0/agent_utilities/harness/client_capabilities.py +131 -0
  20. meristem-4.0.0/agent_utilities/harness/constraint_engine.py +352 -0
  21. meristem-4.0.0/agent_utilities/harness/contract_validator.py +91 -0
  22. meristem-4.0.0/agent_utilities/harness/conversation_history.py +51 -0
  23. meristem-4.0.0/agent_utilities/harness/edit_engine.py +642 -0
  24. meristem-4.0.0/agent_utilities/harness/harness_cycle.py +765 -0
  25. meristem-4.0.0/agent_utilities/harness/hosted_run.py +34 -0
  26. meristem-4.0.0/agent_utilities/harness/plan.py +57 -0
  27. meristem-4.0.0/agent_utilities/harness/plan_runtime.py +119 -0
  28. meristem-4.0.0/agent_utilities/harness/quality_gates.py +233 -0
  29. meristem-4.0.0/agent_utilities/host_ports.py +575 -0
  30. meristem-4.0.0/agent_utilities/py.typed +0 -0
  31. meristem-4.0.0/agent_utilities/rlm/__init__.py +13 -0
  32. meristem-4.0.0/agent_utilities/rlm/runner.py +222 -0
  33. meristem-4.0.0/agent_utilities/rlm/telemetry.py +64 -0
  34. meristem-4.0.0/agent_utilities/runtime/__init__.py +118 -0
  35. meristem-4.0.0/agent_utilities/runtime/bridge.py +441 -0
  36. meristem-4.0.0/agent_utilities/runtime/browser_tier.py +32 -0
  37. meristem-4.0.0/agent_utilities/runtime/computer_use_tier.py +29 -0
  38. meristem-4.0.0/agent_utilities/runtime/docker_workspace.py +181 -0
  39. meristem-4.0.0/agent_utilities/runtime/events.py +301 -0
  40. meristem-4.0.0/agent_utilities/runtime/local_workspace.py +50 -0
  41. meristem-4.0.0/agent_utilities/runtime/provenance.py +41 -0
  42. meristem-4.0.0/agent_utilities/runtime/workspace.py +206 -0
  43. meristem-4.0.0/meristem.egg-info/PKG-INFO +180 -0
  44. meristem-4.0.0/meristem.egg-info/SOURCES.txt +69 -0
  45. meristem-4.0.0/meristem.egg-info/dependency_links.txt +1 -0
  46. meristem-4.0.0/meristem.egg-info/entry_points.txt +2 -0
  47. meristem-4.0.0/meristem.egg-info/requires.txt +8 -0
  48. meristem-4.0.0/meristem.egg-info/top_level.txt +1 -0
  49. meristem-4.0.0/pyproject.toml +87 -0
  50. meristem-4.0.0/setup.cfg +4 -0
  51. meristem-4.0.0/tests/test_client_capabilities.py +194 -0
  52. meristem-4.0.0/tests/test_constraint_engine.py +62 -0
  53. meristem-4.0.0/tests/test_contract_validator.py +74 -0
  54. meristem-4.0.0/tests/test_conversation_history.py +415 -0
  55. meristem-4.0.0/tests/test_dependency.py +987 -0
  56. meristem-4.0.0/tests/test_edit_engine.py +151 -0
  57. meristem-4.0.0/tests/test_graph_metrics.py +131 -0
  58. meristem-4.0.0/tests/test_harness_plan.py +145 -0
  59. meristem-4.0.0/tests/test_host_ports.py +256 -0
  60. meristem-4.0.0/tests/test_hosted_run.py +446 -0
  61. meristem-4.0.0/tests/test_paths.py +90 -0
  62. meristem-4.0.0/tests/test_plan_runtime.py +419 -0
  63. meristem-4.0.0/tests/test_quality_gates.py +76 -0
  64. meristem-4.0.0/tests/test_release_config.py +20 -0
  65. meristem-4.0.0/tests/test_retired_deployment_sparql_images.py +131 -0
  66. meristem-4.0.0/tests/test_retired_manifest_compiler_finance.py +169 -0
  67. meristem-4.0.0/tests/test_retired_quantum_security_standardization.py +202 -0
  68. meristem-4.0.0/tests/test_rlm.py +345 -0
  69. meristem-4.0.0/tests/test_run_loop.py +2012 -0
  70. meristem-4.0.0/tests/test_runtime.py +234 -0
  71. 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.
@@ -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
+ [![PyPI - Version](https://img.shields.io/pypi/v/agent-utilities)](https://pypi.org/project/agent-utilities/)
38
+ [![Build](https://github.com/Knuckles-Team/agent-utilities/actions/workflows/release.yml/badge.svg)](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).
@@ -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
+ [![PyPI - Version](https://img.shields.io/pypi/v/agent-utilities)](https://pypi.org/project/agent-utilities/)
13
+ [![Build](https://github.com/Knuckles-Team/agent-utilities/actions/workflows/release.yml/badge.svg)](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,3 @@
1
+ """Authoritative package version for the meristem distribution."""
2
+
3
+ __version__ = "4.0.0"
@@ -0,0 +1 @@
1
+ """Core harness plumbing: the platform config/paths resolver."""