agent-runtime-kit 0.3.0__tar.gz → 0.5.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.
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/CHANGELOG.md +102 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/PKG-INFO +74 -13
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/README.md +72 -12
- agent_runtime_kit-0.5.0/docs/api-stability.md +110 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/docs/capability-matrix.md +28 -2
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/docs/providers.md +83 -6
- agent_runtime_kit-0.5.0/docs/quickstart.md +131 -0
- agent_runtime_kit-0.5.0/docs/task-control.md +61 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/pyproject.toml +6 -3
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/__init__.py +42 -0
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/_control.py +234 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/_errors.py +36 -0
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/_kit.py +775 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/_runtime.py +53 -32
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/_schema.py +380 -0
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/_types.py +887 -0
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/adapters/_common.py +478 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/adapters/antigravity.py +212 -90
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/adapters/claude.py +154 -80
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/adapters/codex.py +175 -77
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/adapters/diagnostics.py +42 -0
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/compatibility.py +100 -0
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/readiness.py +128 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/registry.py +45 -2
- agent_runtime_kit-0.5.0/src/agent_runtime_kit/support.py +138 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/testing/fakes.py +54 -1
- agent_runtime_kit-0.5.0/tests/test_adapter_common.py +173 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_adapter_protocol.py +13 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_antigravity_adapter.py +177 -11
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_claude_adapter.py +192 -4
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_codex_adapter.py +202 -14
- agent_runtime_kit-0.5.0/tests/test_control.py +662 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_core.py +170 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_events.py +40 -0
- agent_runtime_kit-0.5.0/tests/test_kit.py +480 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_live_smoke.py +5 -5
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_mestre_compatibility.py +4 -1
- agent_runtime_kit-0.5.0/tests/test_readiness.py +662 -0
- agent_runtime_kit-0.5.0/tests/test_schema.py +273 -0
- agent_runtime_kit-0.5.0/tests/test_support.py +282 -0
- agent_runtime_kit-0.3.0/docs/api-stability.md +0 -56
- agent_runtime_kit-0.3.0/docs/mestre-migration.md +0 -25
- agent_runtime_kit-0.3.0/docs/quickstart.md +0 -47
- agent_runtime_kit-0.3.0/src/agent_runtime_kit/_types.py +0 -408
- agent_runtime_kit-0.3.0/src/agent_runtime_kit/adapters/_common.py +0 -334
- agent_runtime_kit-0.3.0/src/agent_runtime_kit/adapters/diagnostics.py +0 -18
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/.gitignore +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/LICENSE +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/docs/live-smoke.md +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/docs/sdk-evolution-agent-design.md +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/docs/sdk-evolution-agent.md +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/__init__.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/run_same_task.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/__init__.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/__main__.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/auth.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/behavior.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/cli.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/collectors.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/current_state.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/events.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/models.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/pr.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/release_notes.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/report.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/schemas.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/snapshots.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/examples/sdk_evolution_agent/stages.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/adapters/__init__.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/events.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/py.typed +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/src/agent_runtime_kit/testing/__init__.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_optional_dependencies.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_provider_diagnostics.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_sdk_contract.py +0 -0
- {agent_runtime_kit-0.3.0 → agent_runtime_kit-0.5.0}/tests/test_sdk_evolution_agent.py +0 -0
|
@@ -5,6 +5,108 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.5.0 - 2026-07-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Core JSON Schema validation via `jsonschema`, including construction-time
|
|
13
|
+
schema checks and `OutputSchemaError` for malformed definitions.
|
|
14
|
+
- `AgentResult.parsed_output_available` distinguishes a valid JSON `null` from
|
|
15
|
+
absent or rejected structured output.
|
|
16
|
+
- All built-in adapters and public fake runtimes now validate returned values
|
|
17
|
+
against `output_schema` locally, including textual JSON fallbacks.
|
|
18
|
+
- `AgentResult.is_success` provides one canonical success predicate.
|
|
19
|
+
- `TaskSupportReport`, `TaskSupportProvider`, and `validate_task()` provide
|
|
20
|
+
side-effect-free task preflight without adding a requirement to the
|
|
21
|
+
`AgentRuntime` protocol. Registry and `AgentKit` helpers preserve custom
|
|
22
|
+
runtime validation and capability-based fallback for older runtimes.
|
|
23
|
+
- `COMPATIBILITY_MANIFEST` records each built-in adapter's install extra,
|
|
24
|
+
import module, accepted SDK range, tested lockfile version, and runtime binary
|
|
25
|
+
versions such as `openai-codex-cli-bin`.
|
|
26
|
+
- `RuntimeReadiness`, `ReadinessStatus`, the optional
|
|
27
|
+
`RuntimeReadinessProvider`, and bounded async `check_readiness()` probes
|
|
28
|
+
distinguish `READY_TO_ATTEMPT`, `NOT_READY`, and `INDETERMINATE` without
|
|
29
|
+
running an agent task. Registry, `AgentKit`, and provider-diagnostics helpers
|
|
30
|
+
expose the same async checks.
|
|
31
|
+
- Absolute `AgentTask.deadline` values, `AgentKit.run(timeout=...)`, typed
|
|
32
|
+
`AgentTaskTimeoutError`, and `FinishReason.TIMED_OUT` provide bounded task
|
|
33
|
+
execution across provider startup and reused-process queueing.
|
|
34
|
+
- Built-in runtimes and `AgentKit.cancel()` now return immutable
|
|
35
|
+
`CancellationReceipt` values with explicit request dispositions; legacy
|
|
36
|
+
third-party `cancel()` methods returning `None` remain supported.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- BREAKING: built-in adapters no longer pin library-owned default model names.
|
|
41
|
+
Model selection now follows task field > legacy metadata > `default_model=`
|
|
42
|
+
constructor override > provider-native configuration. Provider-native calls
|
|
43
|
+
omit the model kwarg; results expose `model_source` and only report a model
|
|
44
|
+
value when known. Existing constructor overrides remain supported.
|
|
45
|
+
- Pydantic structured-output parsing now requests strict validation, so values
|
|
46
|
+
such as `"42"` no longer coerce into integer fields.
|
|
47
|
+
- BREAKING: task and value-object constructors now reject blank identities,
|
|
48
|
+
non-positive execution hints, invalid budgets, ambiguous session inputs,
|
|
49
|
+
duplicate MCP names, and conflicting tool filters.
|
|
50
|
+
- BREAKING: unknown `Usage` values, including cost, are `None` rather than zero;
|
|
51
|
+
an explicit provider-reported zero remains `0`/`0.0`.
|
|
52
|
+
- Capability declarations now distinguish budget, reasoning-effort, network,
|
|
53
|
+
tool-filter, and per-MCP-server environment support. Built-in `run()` methods
|
|
54
|
+
consume the same support report used by preflight, eliminating divergent
|
|
55
|
+
rejection paths.
|
|
56
|
+
- `availability()` is now strictly package-only and side-effect-free. Credential
|
|
57
|
+
and setup checks moved to async readiness probes: Codex uses the supported
|
|
58
|
+
account API with guaranteed cleanup, and Antigravity runs Google ADC discovery
|
|
59
|
+
off the event loop. Probe failures/timeouts are secret-safe and indeterminate.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- `AgentKit.run(task=...)` now rejects every explicitly supplied per-field task
|
|
64
|
+
argument, including default-valued `sdk_executions=1` and empty tool lists,
|
|
65
|
+
instead of silently ignoring it.
|
|
66
|
+
- `ParsedResult[T]` clears an adapter's raw `parsed_output` when the adapter
|
|
67
|
+
reports failure, so the typed result surface never exposes unvalidated data.
|
|
68
|
+
- `AgentKit.aclose()` attempts to close every cached runtime before reraising
|
|
69
|
+
the first close error, preventing later resources from leaking.
|
|
70
|
+
- Permission- and budget-critical vendor options must now be explicit,
|
|
71
|
+
introspectable SDK parameters; opaque `**kwargs`, positional-only options,
|
|
72
|
+
and uninspectable callables fail closed.
|
|
73
|
+
- Configured model allow-lists, Antigravity MCP name syntax, disjoint
|
|
74
|
+
allow/deny lists, and Antigravity's legacy reasoning-effort alias are rejected
|
|
75
|
+
during static preflight instead of surfacing later or being silently ignored.
|
|
76
|
+
- A configured model allow-list now fails closed when model selection is
|
|
77
|
+
provider-native and therefore cannot be verified locally.
|
|
78
|
+
- Cancellation now binds to one active task generation, unregisters without a
|
|
79
|
+
cancellable lock window, emits at most one timeout/cancellation terminal, and
|
|
80
|
+
gives reusable provider-process teardown a bounded grace period under repeated
|
|
81
|
+
cancellation. Runtime instances stay quarantined from new work while detached
|
|
82
|
+
teardown remains pending.
|
|
83
|
+
|
|
84
|
+
## 0.4.0 - 2026-07-02
|
|
85
|
+
|
|
86
|
+
### Added
|
|
87
|
+
|
|
88
|
+
- `AgentKit`, a FastAPI-flavored hub over the registry: keyword-native
|
|
89
|
+
`await kit.run("claude", goal=..., permissions="strict", ...)` assembling
|
|
90
|
+
the frozen `AgentTask` internally (a prebuilt `task=` still passes through),
|
|
91
|
+
short aliases for the built-in kinds via the documented `KIND_ALIASES`
|
|
92
|
+
mapping, per-kind runtime caching closed by `aclose()`/`async with`,
|
|
93
|
+
`@kit.on(...)` sync/async event handlers that tee alongside a task's own
|
|
94
|
+
sink and can never break a run, and `@kit.runtime(...)` decorator
|
|
95
|
+
registration for third-party kinds.
|
|
96
|
+
- Typed structured output: `kit.run(..., output_type=SomeType)` derives the
|
|
97
|
+
wire schema from a dataclass/`TypedDict` (dependency-free, bounded subset,
|
|
98
|
+
fail-closed via the new `OutputTypeError`) or from a Pydantic-style model's
|
|
99
|
+
own `model_json_schema`, and validates `parsed_output` back into the type.
|
|
100
|
+
The result is `ParsedResult[T]` — a runtime-identical `AgentResult`
|
|
101
|
+
subclass with a typed `parsed` accessor; `AgentResult` itself stays
|
|
102
|
+
non-generic. Non-conforming payloads yield `finish_reason="failed"`, the
|
|
103
|
+
adapters' own structured-output convention.
|
|
104
|
+
- `PermissionProfile` accepts string literals for `mode`/`filesystem`
|
|
105
|
+
("strict", "read-only", ...) and coerces them to real enum members at
|
|
106
|
+
construction; unknown values raise `ValueError` listing the vocabulary.
|
|
107
|
+
Previously a bare string silently matched none of the adapters' identity
|
|
108
|
+
checks and ran at the default posture.
|
|
109
|
+
|
|
8
110
|
## 0.3.0 - 2026-07-02
|
|
9
111
|
|
|
10
112
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-runtime-kit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: One typed runtime API for Claude, Codex, and Antigravity agent SDKs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ebarti/agent-runtime-kit
|
|
6
6
|
Project-URL: Repository, https://github.com/ebarti/agent-runtime-kit
|
|
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Typing :: Typed
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: jsonschema<5,>=4.18
|
|
21
22
|
Provides-Extra: all
|
|
22
23
|
Requires-Dist: claude-agent-sdk<0.3,>=0.2.87; extra == 'all'
|
|
23
24
|
Requires-Dist: google-antigravity<0.2,>=0.1.2; extra == 'all'
|
|
@@ -46,7 +47,7 @@ capabilities visible.
|
|
|
46
47
|
`agent-runtime-kit` is for Python developers who want to run coding-agent tasks
|
|
47
48
|
through vendor runtimes without rewriting their application around each SDK. It
|
|
48
49
|
normalizes the runtime boundary: task inputs, capability checks, event streams,
|
|
49
|
-
tool audits,
|
|
50
|
+
tool audits, package/readiness diagnostics, and typed results.
|
|
50
51
|
|
|
51
52
|
The library keeps vendor differences visible. Claude, Codex, and Antigravity
|
|
52
53
|
still expose different capabilities, permission models, setup requirements, and
|
|
@@ -55,7 +56,7 @@ shape instead of hiding them behind a lowest-common-denominator wrapper.
|
|
|
55
56
|
|
|
56
57
|
The package is intentionally not a router, benchmark harness, queue, hosted
|
|
57
58
|
service, or full agent framework. It is the reusable layer underneath those
|
|
58
|
-
systems: task models, runtime capabilities, event sinks,
|
|
59
|
+
systems: task models, runtime capabilities, event sinks, package/readiness
|
|
59
60
|
diagnostics, and adapters.
|
|
60
61
|
|
|
61
62
|
## Install
|
|
@@ -66,7 +67,7 @@ If you want all first-party runtimes available, install the `all` extra:
|
|
|
66
67
|
pip install "agent-runtime-kit[all]"
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
Install the
|
|
70
|
+
Install the vendor-SDK-free core when you only need the public models, fake
|
|
70
71
|
runtime, registry, diagnostics types, or you plan to add provider SDKs later:
|
|
71
72
|
|
|
72
73
|
```bash
|
|
@@ -108,18 +109,53 @@ are added through optional extras.
|
|
|
108
109
|
|
|
109
110
|
## Real Providers
|
|
110
111
|
|
|
112
|
+
`AgentKit` is the keyword-native hub: it registers the built-in runtimes,
|
|
113
|
+
caches them per kind, and turns Python types into structured output.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import asyncio
|
|
117
|
+
from dataclasses import dataclass
|
|
118
|
+
|
|
119
|
+
from agent_runtime_kit import AgentKit, ReadinessStatus
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@dataclass
|
|
123
|
+
class RepoSummary:
|
|
124
|
+
name: str
|
|
125
|
+
languages: list[str]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
async def main() -> None:
|
|
129
|
+
async with AgentKit() as kit:
|
|
130
|
+
readiness = await kit.readiness_for("claude")
|
|
131
|
+
if readiness.status is ReadinessStatus.NOT_READY:
|
|
132
|
+
raise RuntimeError(readiness.message)
|
|
133
|
+
result = await kit.run(
|
|
134
|
+
"claude",
|
|
135
|
+
goal="Summarize this repository",
|
|
136
|
+
permissions="strict",
|
|
137
|
+
output_type=RepoSummary,
|
|
138
|
+
)
|
|
139
|
+
print(result.parsed.languages if result.parsed else result.error)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
asyncio.run(main())
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Adapters also work standalone when you need vendor-specific configuration:
|
|
146
|
+
|
|
111
147
|
```python
|
|
112
148
|
import asyncio
|
|
113
149
|
|
|
114
|
-
from agent_runtime_kit import AgentTask
|
|
150
|
+
from agent_runtime_kit import AgentTask, ReadinessStatus, check_readiness
|
|
115
151
|
from agent_runtime_kit.adapters import ClaudeAgentRuntime
|
|
116
152
|
|
|
117
153
|
|
|
118
154
|
async def main() -> None:
|
|
119
155
|
runtime = ClaudeAgentRuntime(default_model="claude-sonnet-4-6")
|
|
120
|
-
|
|
121
|
-
if
|
|
122
|
-
raise RuntimeError(
|
|
156
|
+
readiness = await check_readiness(runtime)
|
|
157
|
+
if readiness.status is ReadinessStatus.NOT_READY:
|
|
158
|
+
raise RuntimeError(readiness.message)
|
|
123
159
|
result = await runtime.run(AgentTask(goal="Summarize this repository"))
|
|
124
160
|
print(result.output)
|
|
125
161
|
|
|
@@ -138,10 +174,35 @@ a field (for example only Claude maps `budget_usd`; Codex and Antigravity reject
|
|
|
138
174
|
it with a typed `UnsupportedTaskInputError`) the adapter raises rather than
|
|
139
175
|
silently dropping it.
|
|
140
176
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
177
|
+
Model selection follows one explicit precedence chain: `AgentTask.model`, then
|
|
178
|
+
legacy `metadata["model"]`, then an adapter's `default_model=` constructor
|
|
179
|
+
override, then the provider's native configuration/default. Adapters omit the
|
|
180
|
+
vendor model option at the final step rather than pinning a library-owned model.
|
|
181
|
+
Results record `metadata["model_source"]`; `metadata["model"]` appears only when
|
|
182
|
+
the kit knows the selected value.
|
|
183
|
+
|
|
184
|
+
Call `validate_task(runtime, task)` (or `kit.validate_task("codex", task)`) to
|
|
185
|
+
inspect every statically detectable incompatibility before dispatch. The
|
|
186
|
+
returned `TaskSupportReport` is side-effect-free and lists source fields such as
|
|
187
|
+
`budget_usd` and `permissions.network`; `run()` still fails closed on the first
|
|
188
|
+
issue. Third-party runtimes can opt into provider-specific checks with the
|
|
189
|
+
`TaskSupportProvider` protocol, while older `AgentRuntime` implementations
|
|
190
|
+
continue to work through capability-based fallback checks.
|
|
191
|
+
|
|
192
|
+
`availability()` is deliberately synchronous, side-effect-free, and package-only.
|
|
193
|
+
Use `await check_readiness(runtime)` (or `kit.readiness_for(...)`) for an explicit,
|
|
194
|
+
bounded credential/setup probe. `READY_TO_ATTEMPT` means setup was positively
|
|
195
|
+
detected, not that a future provider call is guaranteed to succeed;
|
|
196
|
+
`INDETERMINATE` lets callers decide whether to attempt provider-chain or local
|
|
197
|
+
login authentication. Probe failures and timeouts never include credential values.
|
|
198
|
+
|
|
199
|
+
`AgentResult` returns output, finish reason (see `FinishReason`), locally
|
|
200
|
+
validated structured output, usage, cost, session id, tool-call audits, and
|
|
201
|
+
provider metadata. `is_success` is true only for a natural, error-free
|
|
202
|
+
completion. Unknown usage and cost fields are `None`; reported zero remains
|
|
203
|
+
distinct. `parsed_output_available` distinguishes an absent payload from valid
|
|
204
|
+
JSON `null` (both use `parsed_output=None`). `artifacts` is a reserved field: no
|
|
205
|
+
built-in runtime populates it yet, so it is always an empty tuple today.
|
|
145
206
|
|
|
146
207
|
## Docs
|
|
147
208
|
|
|
@@ -150,5 +211,5 @@ so it is always an empty tuple today.
|
|
|
150
211
|
- [Capability matrix](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/capability-matrix.md)
|
|
151
212
|
- [API stability](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/api-stability.md)
|
|
152
213
|
- [Live smoke tests](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/live-smoke.md)
|
|
153
|
-
- [
|
|
214
|
+
- [Deadlines and cancellation](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/task-control.md)
|
|
154
215
|
- [SDK evolution agent](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/sdk-evolution-agent.md)
|
|
@@ -14,7 +14,7 @@ capabilities visible.
|
|
|
14
14
|
`agent-runtime-kit` is for Python developers who want to run coding-agent tasks
|
|
15
15
|
through vendor runtimes without rewriting their application around each SDK. It
|
|
16
16
|
normalizes the runtime boundary: task inputs, capability checks, event streams,
|
|
17
|
-
tool audits,
|
|
17
|
+
tool audits, package/readiness diagnostics, and typed results.
|
|
18
18
|
|
|
19
19
|
The library keeps vendor differences visible. Claude, Codex, and Antigravity
|
|
20
20
|
still expose different capabilities, permission models, setup requirements, and
|
|
@@ -23,7 +23,7 @@ shape instead of hiding them behind a lowest-common-denominator wrapper.
|
|
|
23
23
|
|
|
24
24
|
The package is intentionally not a router, benchmark harness, queue, hosted
|
|
25
25
|
service, or full agent framework. It is the reusable layer underneath those
|
|
26
|
-
systems: task models, runtime capabilities, event sinks,
|
|
26
|
+
systems: task models, runtime capabilities, event sinks, package/readiness
|
|
27
27
|
diagnostics, and adapters.
|
|
28
28
|
|
|
29
29
|
## Install
|
|
@@ -34,7 +34,7 @@ If you want all first-party runtimes available, install the `all` extra:
|
|
|
34
34
|
pip install "agent-runtime-kit[all]"
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Install the
|
|
37
|
+
Install the vendor-SDK-free core when you only need the public models, fake
|
|
38
38
|
runtime, registry, diagnostics types, or you plan to add provider SDKs later:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
@@ -76,18 +76,53 @@ are added through optional extras.
|
|
|
76
76
|
|
|
77
77
|
## Real Providers
|
|
78
78
|
|
|
79
|
+
`AgentKit` is the keyword-native hub: it registers the built-in runtimes,
|
|
80
|
+
caches them per kind, and turns Python types into structured output.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import asyncio
|
|
84
|
+
from dataclasses import dataclass
|
|
85
|
+
|
|
86
|
+
from agent_runtime_kit import AgentKit, ReadinessStatus
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass
|
|
90
|
+
class RepoSummary:
|
|
91
|
+
name: str
|
|
92
|
+
languages: list[str]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
async def main() -> None:
|
|
96
|
+
async with AgentKit() as kit:
|
|
97
|
+
readiness = await kit.readiness_for("claude")
|
|
98
|
+
if readiness.status is ReadinessStatus.NOT_READY:
|
|
99
|
+
raise RuntimeError(readiness.message)
|
|
100
|
+
result = await kit.run(
|
|
101
|
+
"claude",
|
|
102
|
+
goal="Summarize this repository",
|
|
103
|
+
permissions="strict",
|
|
104
|
+
output_type=RepoSummary,
|
|
105
|
+
)
|
|
106
|
+
print(result.parsed.languages if result.parsed else result.error)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
asyncio.run(main())
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Adapters also work standalone when you need vendor-specific configuration:
|
|
113
|
+
|
|
79
114
|
```python
|
|
80
115
|
import asyncio
|
|
81
116
|
|
|
82
|
-
from agent_runtime_kit import AgentTask
|
|
117
|
+
from agent_runtime_kit import AgentTask, ReadinessStatus, check_readiness
|
|
83
118
|
from agent_runtime_kit.adapters import ClaudeAgentRuntime
|
|
84
119
|
|
|
85
120
|
|
|
86
121
|
async def main() -> None:
|
|
87
122
|
runtime = ClaudeAgentRuntime(default_model="claude-sonnet-4-6")
|
|
88
|
-
|
|
89
|
-
if
|
|
90
|
-
raise RuntimeError(
|
|
123
|
+
readiness = await check_readiness(runtime)
|
|
124
|
+
if readiness.status is ReadinessStatus.NOT_READY:
|
|
125
|
+
raise RuntimeError(readiness.message)
|
|
91
126
|
result = await runtime.run(AgentTask(goal="Summarize this repository"))
|
|
92
127
|
print(result.output)
|
|
93
128
|
|
|
@@ -106,10 +141,35 @@ a field (for example only Claude maps `budget_usd`; Codex and Antigravity reject
|
|
|
106
141
|
it with a typed `UnsupportedTaskInputError`) the adapter raises rather than
|
|
107
142
|
silently dropping it.
|
|
108
143
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
144
|
+
Model selection follows one explicit precedence chain: `AgentTask.model`, then
|
|
145
|
+
legacy `metadata["model"]`, then an adapter's `default_model=` constructor
|
|
146
|
+
override, then the provider's native configuration/default. Adapters omit the
|
|
147
|
+
vendor model option at the final step rather than pinning a library-owned model.
|
|
148
|
+
Results record `metadata["model_source"]`; `metadata["model"]` appears only when
|
|
149
|
+
the kit knows the selected value.
|
|
150
|
+
|
|
151
|
+
Call `validate_task(runtime, task)` (or `kit.validate_task("codex", task)`) to
|
|
152
|
+
inspect every statically detectable incompatibility before dispatch. The
|
|
153
|
+
returned `TaskSupportReport` is side-effect-free and lists source fields such as
|
|
154
|
+
`budget_usd` and `permissions.network`; `run()` still fails closed on the first
|
|
155
|
+
issue. Third-party runtimes can opt into provider-specific checks with the
|
|
156
|
+
`TaskSupportProvider` protocol, while older `AgentRuntime` implementations
|
|
157
|
+
continue to work through capability-based fallback checks.
|
|
158
|
+
|
|
159
|
+
`availability()` is deliberately synchronous, side-effect-free, and package-only.
|
|
160
|
+
Use `await check_readiness(runtime)` (or `kit.readiness_for(...)`) for an explicit,
|
|
161
|
+
bounded credential/setup probe. `READY_TO_ATTEMPT` means setup was positively
|
|
162
|
+
detected, not that a future provider call is guaranteed to succeed;
|
|
163
|
+
`INDETERMINATE` lets callers decide whether to attempt provider-chain or local
|
|
164
|
+
login authentication. Probe failures and timeouts never include credential values.
|
|
165
|
+
|
|
166
|
+
`AgentResult` returns output, finish reason (see `FinishReason`), locally
|
|
167
|
+
validated structured output, usage, cost, session id, tool-call audits, and
|
|
168
|
+
provider metadata. `is_success` is true only for a natural, error-free
|
|
169
|
+
completion. Unknown usage and cost fields are `None`; reported zero remains
|
|
170
|
+
distinct. `parsed_output_available` distinguishes an absent payload from valid
|
|
171
|
+
JSON `null` (both use `parsed_output=None`). `artifacts` is a reserved field: no
|
|
172
|
+
built-in runtime populates it yet, so it is always an empty tuple today.
|
|
113
173
|
|
|
114
174
|
## Docs
|
|
115
175
|
|
|
@@ -118,5 +178,5 @@ so it is always an empty tuple today.
|
|
|
118
178
|
- [Capability matrix](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/capability-matrix.md)
|
|
119
179
|
- [API stability](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/api-stability.md)
|
|
120
180
|
- [Live smoke tests](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/live-smoke.md)
|
|
121
|
-
- [
|
|
181
|
+
- [Deadlines and cancellation](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/task-control.md)
|
|
122
182
|
- [SDK evolution agent](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/sdk-evolution-agent.md)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# API stability & versioning
|
|
2
|
+
|
|
3
|
+
`agent-runtime-kit` is pre-1.0 (`0.x`) and follows semantic versioning with the
|
|
4
|
+
usual pre-1.0 caveat: **breaking changes may land in a minor release** (`0.N`)
|
|
5
|
+
while the API is being shaped toward 1.0. Patch releases (`0.N.P`) are additive
|
|
6
|
+
or bug-fix only.
|
|
7
|
+
|
|
8
|
+
## Public API
|
|
9
|
+
|
|
10
|
+
The supported surface is exactly what `agent_runtime_kit.__all__` exports (and
|
|
11
|
+
the vendor adapters under `agent_runtime_kit.adapters`). Anything whose module or
|
|
12
|
+
name begins with an underscore (`agent_runtime_kit._types`,
|
|
13
|
+
`agent_runtime_kit._runtime`, etc.) is internal and may change without notice —
|
|
14
|
+
import the names from the top-level package instead.
|
|
15
|
+
|
|
16
|
+
`agent_runtime_kit.testing` is public and intended for downstream test suites
|
|
17
|
+
(fake runtimes and event sinks).
|
|
18
|
+
|
|
19
|
+
## Compatibility guarantees within a 0.x line
|
|
20
|
+
|
|
21
|
+
- **Runtime kinds are open.** `AgentRuntimeKind.coerce` accepts namespaced
|
|
22
|
+
strings (e.g. `"x-myorg-agent"`), and the registry stores them, so a third
|
|
23
|
+
party can ship an adapter for a new runtime without forking the enum.
|
|
24
|
+
- **Every runtime exposes the async lifecycle** (`aclose`, `async with`) declared
|
|
25
|
+
by the `AgentRuntime` protocol. Stateless runtimes implement it as a no-op.
|
|
26
|
+
- **Cancellation receipts describe requests, not rollback.** Built-in runtimes
|
|
27
|
+
return an immutable `CancellationReceipt`; the protocol still permits `None`
|
|
28
|
+
for existing third-party runtimes, which `AgentKit` reports as
|
|
29
|
+
`LEGACY_UNCONFIRMED`. `AgentTask.deadline` is keyword-only and an expired task
|
|
30
|
+
raises `AgentTaskTimeoutError` with `FinishReason.TIMED_OUT` event semantics.
|
|
31
|
+
- **`finish_reason` values** come from `FinishReason`. The field is typed `str`
|
|
32
|
+
for forward-compatibility, so new reasons can be added without a type break;
|
|
33
|
+
compare against `FinishReason` members rather than bare literals.
|
|
34
|
+
- **Result/task mappings are read-only at the top level.** `AgentTask`/`AgentResult`
|
|
35
|
+
copy `Mapping` fields into read-only dicts at construction; in-place writes to
|
|
36
|
+
the mapping itself raise `TypeError`. The freeze is shallow — nested containers
|
|
37
|
+
are not copied or frozen — so treat the whole structure as immutable by
|
|
38
|
+
convention and compare by value. The wrappers remain plain `dict` subclasses,
|
|
39
|
+
so `dataclasses.asdict`, `pickle`, `copy.deepcopy`, and JSON serialization
|
|
40
|
+
keep working.
|
|
41
|
+
- **Constructors enforce domain invariants.** Goals and identifiers are
|
|
42
|
+
non-blank; execution hints are positive; counts and monetary values are
|
|
43
|
+
finite and non-negative; session start and resume inputs are mutually
|
|
44
|
+
exclusive; MCP server names and tool filters are unambiguous.
|
|
45
|
+
- **Unknown telemetry is not zero.** Every `Usage` field is nullable. `None`
|
|
46
|
+
means the provider did not report a value; `0` and `0.0` mean it explicitly
|
|
47
|
+
reported zero.
|
|
48
|
+
- **Unsupported inputs raise, they are not dropped.** An adapter that cannot honor
|
|
49
|
+
a task field raises `UnsupportedTaskInputError`; the one exception is
|
|
50
|
+
vendor-option drift, which is recorded in
|
|
51
|
+
`AgentResult.metadata["dropped_options"]` instead.
|
|
52
|
+
- **Task support can be inspected without dispatch.** `validate_task(runtime,
|
|
53
|
+
task)`, `RuntimeRegistry.validate_task_for(...)`, and `AgentKit.validate_task(...)`
|
|
54
|
+
return every statically detectable incompatibility as a `TaskSupportReport`.
|
|
55
|
+
`TaskSupportProvider` is an optional extension, not a new requirement on the
|
|
56
|
+
`AgentRuntime` protocol, so existing third-party runtimes retain structural
|
|
57
|
+
compatibility and use capability-based fallback checks.
|
|
58
|
+
- **Package availability and execution readiness are separate.** Synchronous
|
|
59
|
+
`availability()` is package-only and side-effect-free. The bounded async
|
|
60
|
+
`check_readiness()` helper uses the optional `RuntimeReadinessProvider`
|
|
61
|
+
extension without changing the `AgentRuntime` protocol. A third-party runtime
|
|
62
|
+
without the extension maps a missing package to `NOT_READY` and present
|
|
63
|
+
package to `INDETERMINATE`. `READY_TO_ATTEMPT` establishes only that known
|
|
64
|
+
setup signals are present; it is not a guarantee of future execution.
|
|
65
|
+
- **Providers own the default model.** With no task, legacy metadata, or
|
|
66
|
+
`default_model=` override, built-in adapters omit the SDK model option and let
|
|
67
|
+
the provider's supported configuration select it. The effective precedence is
|
|
68
|
+
task field, metadata alias, constructor override, provider-native. Result
|
|
69
|
+
metadata always records `model_source` and records `model` only when known.
|
|
70
|
+
A configured `supported_models` allow-list requires an explicit/verifiable
|
|
71
|
+
selection and fails closed on provider-native selection.
|
|
72
|
+
- **`AgentKit` is sugar, not a second API.** The hub assembles the same frozen
|
|
73
|
+
`AgentTask` and returns the same `AgentResult` the runtimes produce
|
|
74
|
+
(`ParsedResult` is a runtime-identical subclass adding only the typed
|
|
75
|
+
`parsed` accessor). Kind aliases are limited to the documented
|
|
76
|
+
`KIND_ALIASES` mapping; exact kind strings always work. `output_type=`
|
|
77
|
+
supports a bounded, documented subset of the typing system and raises
|
|
78
|
+
`OutputTypeError` on anything outside it (Pydantic-style models are used
|
|
79
|
+
through their own `model_json_schema`/`model_validate(strict=True)` when
|
|
80
|
+
present). Raw schemas are checked at construction and again at dispatch
|
|
81
|
+
because their nested values are only shallow-frozen. Every built-in adapter
|
|
82
|
+
validates returned structured values locally.
|
|
83
|
+
- **Structured-output presence is explicit.** `parsed_output_available` is true
|
|
84
|
+
for a validated payload, including JSON `null`. Existing non-null custom
|
|
85
|
+
runtime results opt in automatically; a custom runtime returning valid null
|
|
86
|
+
must set the flag explicitly.
|
|
87
|
+
|
|
88
|
+
## Vendor SDK version policy
|
|
89
|
+
|
|
90
|
+
The vendor SDK extras are pinned with cautious upper bounds (e.g.
|
|
91
|
+
`claude-agent-sdk>=0.2.87,<0.3`) because those SDKs are themselves pre-1.0 and
|
|
92
|
+
have shipped breaking changes within a minor series. The bounds are raised
|
|
93
|
+
deliberately — after the contract tests and the SDK-evolution agent verify a new
|
|
94
|
+
version — rather than left unbounded. A weekly CI lane installs the latest vendor
|
|
95
|
+
SDKs *within the declared caps*, so drift inside an allowed range surfaces before
|
|
96
|
+
it reaches installed users; a release above a cap is by design invisible to that
|
|
97
|
+
lane until the cap is raised. A separate lane installs every direct dependency at
|
|
98
|
+
its declared floor so a stale minimum cannot sit undetected in the metadata.
|
|
99
|
+
|
|
100
|
+
`COMPATIBILITY_MANIFEST` is the machine-readable form of that policy. Each entry
|
|
101
|
+
records the install extra, import module, accepted SDK range, exact lockfile
|
|
102
|
+
version exercised by the repository, and any separately versioned runtime binary
|
|
103
|
+
(currently `openai-codex-cli-bin`). The manifest is tested against both
|
|
104
|
+
`pyproject.toml` and `uv.lock`; it is evidence of the committed test baseline,
|
|
105
|
+
not a claim that every version in the accepted range was exhaustively tested.
|
|
106
|
+
|
|
107
|
+
## Deprecation
|
|
108
|
+
|
|
109
|
+
When a public name is slated for removal it will be kept working for at least one
|
|
110
|
+
minor release with a `DeprecationWarning` before it is dropped.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|------------|------------------|------------------|------------------------|
|
|
5
5
|
| Optional extra | `claude` | `codex` | `antigravity` |
|
|
6
6
|
| Core import without extra | Yes | Yes | Yes |
|
|
7
|
+
| Model selection | Provider-native unless task/metadata/constructor overrides it | Provider-native unless task/metadata/constructor overrides it | Provider-native unless task/metadata/constructor overrides it |
|
|
7
8
|
| Working directory | Yes | Yes | Yes |
|
|
8
9
|
| Session resume | Yes | Yes | Yes |
|
|
9
10
|
| Structured output | Native `output_format` when available | Native output schema / JSON parse fallback | Native response schema / JSON parse fallback |
|
|
@@ -11,15 +12,33 @@
|
|
|
11
12
|
| Permission mapping | `permission_mode` | approval mode + sandbox | capabilities + policies |
|
|
12
13
|
| Streaming output events | Yes — incremental `output.delta` while the SDK runs | No — a single `output.delta` at the end (non-streaming SDK) | Yes — from response chunks |
|
|
13
14
|
| Tool audit events | Yes — streamed from message blocks | Yes — emitted from parsed `TurnResult` items after the turn | Yes — from tool chunks |
|
|
15
|
+
| Deadlines and cancellation | Absolute deadline + coroutine cancellation | Absolute deadline + coroutine cancellation | Absolute deadline + coroutine cancellation |
|
|
14
16
|
| `vendor.turn` events | No | No | Yes — from thought/unknown chunks |
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
+
| Package availability | Sync, side-effect-free, package-only | Sync, side-effect-free, package-only | Sync, side-effect-free, package-only; never calls ADC |
|
|
18
|
+
| Async readiness | Direct API key/OAuth/Bedrock bearer signal → `READY_TO_ATTEMPT`; provider/local chains → `INDETERMINATE` | Supported `AsyncCodex.account(refresh_token=False)` probe; absent account → `NOT_READY` | API key or off-loop ADC/project probe; missing → `NOT_READY` |
|
|
19
|
+
| Probe failure/timeout | `INDETERMINATE` | `INDETERMINATE`, app-server always closed | `INDETERMINATE` |
|
|
17
20
|
| Live smoke test | Opt-in | Opt-in | Opt-in |
|
|
18
21
|
|
|
19
22
|
The matrix is intentionally not a lowest-common-denominator contract. Adapters
|
|
20
23
|
reject unsupported inputs (see below) when silently dropping them would be
|
|
21
24
|
misleading.
|
|
22
25
|
|
|
26
|
+
The public `AgentCapabilities` value also advertises the granular task controls
|
|
27
|
+
used by preflight: `budget`, `reasoning_effort`, `network_control`,
|
|
28
|
+
`tool_filters`, and `mcp_server_env`. Use `validate_task(runtime, task)` when a
|
|
29
|
+
concrete task is available; unlike a raw capability flag, its
|
|
30
|
+
`TaskSupportReport` preserves instance-specific rules such as a configured model
|
|
31
|
+
allow-list and reports all detectable issues at once.
|
|
32
|
+
|
|
33
|
+
For every provider, malformed schemas are rejected locally before dispatch and
|
|
34
|
+
returned structured values are validated locally after the SDK completes.
|
|
35
|
+
`parsed_output_available` distinguishes valid JSON `null` from no parsed value.
|
|
36
|
+
|
|
37
|
+
Deadlines cover provider startup and waits for a reused process. Cancellation
|
|
38
|
+
receipts acknowledge a request at the coroutine boundary; they do not imply
|
|
39
|
+
rollback of tool side effects that already completed. See
|
|
40
|
+
[Deadlines and cancellation](task-control.md).
|
|
41
|
+
|
|
23
42
|
## Permission mapping
|
|
24
43
|
|
|
25
44
|
A single portable `PermissionMode` maps to each vendor's native controls. The
|
|
@@ -59,6 +78,13 @@ tool, uses the SDK's `disabled_tools` route).
|
|
|
59
78
|
Each adapter raises `UnsupportedTaskInputError` for task fields it has no SDK
|
|
60
79
|
surface to honor, rather than dropping them silently.
|
|
61
80
|
|
|
81
|
+
The same fields can be checked before dispatch through `validate_task`,
|
|
82
|
+
`RuntimeRegistry.validate_task_for`, or `AgentKit.validate_task`. Built-in
|
|
83
|
+
adapters additionally preflight configured model allow-lists. Antigravity also
|
|
84
|
+
checks its MCP server-name syntax and the SDK's prohibition on combining an
|
|
85
|
+
allow-list with a deny-list. SDK-version-dependent Antigravity tool vocabulary
|
|
86
|
+
is still validated at dispatch, after the installed SDK supplies its enum.
|
|
87
|
+
|
|
62
88
|
| Field | Claude | Codex | Antigravity |
|
|
63
89
|
|-------|--------|-------|-------------|
|
|
64
90
|
| `budget_usd` | Mapped (`max_budget_usd`, fails closed under SDK drift) | Rejected | Rejected |
|