agent-runtime-kit 0.5.2__tar.gz → 0.5.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/CHANGELOG.md +26 -0
  2. agent_runtime_kit-0.5.3/PKG-INFO +113 -0
  3. agent_runtime_kit-0.5.3/README.md +79 -0
  4. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/providers.md +18 -0
  5. agent_runtime_kit-0.5.3/docs/quickstart.md +114 -0
  6. agent_runtime_kit-0.5.3/docs/recipes.md +125 -0
  7. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/task-control.md +47 -12
  8. agent_runtime_kit-0.5.3/examples/README.md +41 -0
  9. agent_runtime_kit-0.5.3/examples/basic_offline.py +20 -0
  10. agent_runtime_kit-0.5.3/examples/diagnostics.py +33 -0
  11. agent_runtime_kit-0.5.3/examples/events.py +31 -0
  12. agent_runtime_kit-0.5.3/examples/provider_task.py +65 -0
  13. agent_runtime_kit-0.5.3/examples/run_same_task.py +29 -0
  14. agent_runtime_kit-0.5.3/examples/structured_output.py +34 -0
  15. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/pyproject.toml +9 -7
  16. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/_types.py +20 -10
  17. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/adapters/antigravity.py +12 -0
  18. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/adapters/claude.py +8 -0
  19. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/adapters/codex.py +187 -10
  20. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/compatibility.py +5 -5
  21. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/support.py +10 -9
  22. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_antigravity_adapter.py +60 -0
  23. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_claude_adapter.py +52 -0
  24. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_codex_adapter.py +235 -0
  25. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_core.py +4 -3
  26. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_sdk_contract.py +54 -0
  27. agent_runtime_kit-0.5.2/PKG-INFO +0 -215
  28. agent_runtime_kit-0.5.2/README.md +0 -182
  29. agent_runtime_kit-0.5.2/docs/quickstart.md +0 -131
  30. agent_runtime_kit-0.5.2/examples/run_same_task.py +0 -31
  31. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/.gitignore +0 -0
  32. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/LICENSE +0 -0
  33. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/api-stability.md +0 -0
  34. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/capability-matrix.md +0 -0
  35. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/live-smoke.md +0 -0
  36. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/sdk-evolution-agent-design.md +0 -0
  37. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/docs/sdk-evolution-agent.md +0 -0
  38. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/__init__.py +0 -0
  39. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/__init__.py +0 -0
  40. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/__main__.py +0 -0
  41. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/auth.py +0 -0
  42. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/behavior.py +0 -0
  43. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/cli.py +0 -0
  44. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/collectors.py +0 -0
  45. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/current_state.py +0 -0
  46. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/events.py +0 -0
  47. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/inspection.py +0 -0
  48. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/models.py +0 -0
  49. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/pr.py +0 -0
  50. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/release_notes.py +0 -0
  51. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/report.py +0 -0
  52. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/schemas.py +0 -0
  53. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/snapshots.py +0 -0
  54. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/examples/sdk_evolution_agent/stages.py +0 -0
  55. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/__init__.py +0 -0
  56. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/_control.py +0 -0
  57. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/_errors.py +0 -0
  58. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/_kit.py +0 -0
  59. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/_runtime.py +0 -0
  60. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/_schema.py +0 -0
  61. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/adapters/__init__.py +0 -0
  62. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/adapters/_common.py +0 -0
  63. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/adapters/diagnostics.py +0 -0
  64. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/events.py +0 -0
  65. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/py.typed +0 -0
  66. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/readiness.py +0 -0
  67. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/registry.py +0 -0
  68. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/testing/__init__.py +0 -0
  69. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/src/agent_runtime_kit/testing/fakes.py +0 -0
  70. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_adapter_common.py +0 -0
  71. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_adapter_protocol.py +0 -0
  72. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_control.py +0 -0
  73. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_events.py +0 -0
  74. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_kit.py +0 -0
  75. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_live_smoke.py +0 -0
  76. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_mestre_compatibility.py +0 -0
  77. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_optional_dependencies.py +0 -0
  78. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_provider_diagnostics.py +0 -0
  79. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_readiness.py +0 -0
  80. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_schema.py +0 -0
  81. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_sdk_evolution_agent.py +0 -0
  82. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_sdk_evolution_docs.py +0 -0
  83. {agent_runtime_kit-0.5.2 → agent_runtime_kit-0.5.3}/tests/test_support.py +0 -0
@@ -5,6 +5,32 @@ 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.3 - 2026-10-02
9
+
10
+ ### Added
11
+
12
+ - Codex tasks can request provider-native named permission profiles through
13
+ `PermissionProfile(native_profile="...")`, with conflicting settings rejected
14
+ and the effective policy preserved across reused sessions.
15
+ - Claude runtime exposes opt-in `verbatim_prompts=True` for literal composed
16
+ goals, with a typed refusal if the installed SDK cannot honor the option.
17
+
18
+ ### Changed
19
+
20
+ - Updated tested Claude Agent SDK to `0.2.163`, Google Antigravity SDK to
21
+ `0.1.20`, and the exactly coupled Codex SDK and CLI to `0.160.0`.
22
+ - Raised the Codex SDK minimum to `0.157.1` for native named-profile support.
23
+ - Quickstart and examples now provide runnable offline, structured-output,
24
+ event-streaming, diagnostics, and provider-task flows.
25
+
26
+ ### Fixed
27
+
28
+ - Codex named permission profiles no longer receive a legacy sandbox override
29
+ that could bypass the requested profile.
30
+ - Antigravity explicit read-only allowlists retain directory/search tools after
31
+ the SDK removes them from default tool collections, without re-enabling them
32
+ by default or admitting deprecated write tools.
33
+
8
34
  ## 0.5.2 - 2026-09-19
9
35
 
10
36
  ### Changed
@@ -0,0 +1,113 @@
1
+ Metadata-Version: 2.5
2
+ Name: agent-runtime-kit
3
+ Version: 0.5.3
4
+ Summary: One typed runtime API for Claude, Codex, and Antigravity agent SDKs.
5
+ Project-URL: Homepage, https://github.com/ebarti/agent-runtime-kit
6
+ Project-URL: Repository, https://github.com/ebarti/agent-runtime-kit
7
+ Project-URL: Issues, https://github.com/ebarti/agent-runtime-kit/issues
8
+ Author: Eloi Barti
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent-runtime,agent-sdk,agents,antigravity,async-python,claude,claude-code,codex,coding-agents,developer-tools,google-antigravity,mcp,openai-codex,runtime-api,sdk,typed-python
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: jsonschema<5,>=4.18
22
+ Requires-Dist: tomli<3,>=2; python_version < '3.11'
23
+ Provides-Extra: all
24
+ Requires-Dist: claude-agent-sdk<0.3,>=0.2.87; extra == 'all'
25
+ Requires-Dist: google-antigravity<0.2,>=0.1.2; extra == 'all'
26
+ Requires-Dist: openai-codex<0.161,>=0.157.1; extra == 'all'
27
+ Provides-Extra: antigravity
28
+ Requires-Dist: google-antigravity<0.2,>=0.1.2; extra == 'antigravity'
29
+ Provides-Extra: claude
30
+ Requires-Dist: claude-agent-sdk<0.3,>=0.2.87; extra == 'claude'
31
+ Provides-Extra: codex
32
+ Requires-Dist: openai-codex<0.161,>=0.157.1; extra == 'codex'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # agent-runtime-kit
36
+
37
+ `agent-runtime-kit` gives Python 3.10+ applications one typed, async API for
38
+ running coding-agent tasks with Claude Agent SDK, OpenAI Codex SDK, or Google
39
+ Antigravity SDK. It exposes capability checks, events, diagnostics, and results
40
+ while keeping each provider's permissions and supported inputs explicit.
41
+
42
+ ## Install and try it offline
43
+
44
+ The core install has no vendor SDK or credential requirement:
45
+
46
+ ```bash
47
+ python -m pip install agent-runtime-kit
48
+ ```
49
+
50
+ ```python
51
+ import asyncio
52
+
53
+ from agent_runtime_kit import AgentKit, FakeAgentRuntime
54
+
55
+
56
+ async def main() -> None:
57
+ async with AgentKit() as kit:
58
+ result = await kit.run(
59
+ FakeAgentRuntime(output="offline example complete"),
60
+ goal="Demonstrate a task result",
61
+ )
62
+ if not result.is_success:
63
+ raise RuntimeError(result.error or result.finish_reason)
64
+ print(result.output)
65
+
66
+
67
+ asyncio.run(main())
68
+ ```
69
+
70
+ This prints `offline example complete`. The fake runtime returns a deterministic
71
+ result; it does not inspect the repository or contact a provider. Run the file
72
+ version with `python -m examples.basic_offline` from a source checkout.
73
+
74
+ ## Run a real provider
75
+
76
+ Install only the provider you use, then configure its supported authentication:
77
+
78
+ ```bash
79
+ python -m pip install "agent-runtime-kit[claude]" # Claude Agent SDK
80
+ python -m pip install "agent-runtime-kit[codex]" # OpenAI Codex SDK
81
+ python -m pip install "agent-runtime-kit[antigravity]" # Google Antigravity SDK
82
+ ```
83
+
84
+ `agent-runtime-kit[all]` installs all three. A real task may use a paid provider
85
+ and may invoke tools. After setting up the chosen provider, run one explicitly
86
+ from a source checkout:
87
+
88
+ ```bash
89
+ python -m examples.provider_task claude
90
+ ```
91
+
92
+ Choose `codex` or `antigravity` instead to use that runtime. The example checks
93
+ package availability, probes setup, requests read-only filesystem access, and
94
+ checks `result.is_success`. Readiness only indicates whether a task is worth
95
+ attempting; it cannot guarantee the provider will accept the request.
96
+
97
+ The adapters share `AgentTask` and `AgentResult`, but inputs are not silently
98
+ discarded. For example, Claude supports per-task MCP servers and a cost budget;
99
+ Codex does not expose either per task; Antigravity supports MCP servers without
100
+ per-server environment values. Unsupported inputs raise typed errors. The
101
+ provider's native model selection is used unless you set a model explicitly.
102
+
103
+ ## Guides
104
+
105
+ - [Quickstart](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/quickstart.md): install, offline result, and first provider run
106
+ - [Examples](https://github.com/ebarti/agent-runtime-kit/blob/main/examples/README.md): runnable commands and expected results
107
+ - [Recipes](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/recipes.md): results, events, preflight, permissions, sessions, and MCP
108
+ - [Provider diagnostics](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/providers.md) and [capability matrix](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/capability-matrix.md)
109
+ - [Deadlines and cancellation](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/task-control.md) and [API stability](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/api-stability.md)
110
+ - [Live smoke tests](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/live-smoke.md) and [SDK evolution agent](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/sdk-evolution-agent.md)
111
+
112
+ The package is a runtime layer, not a router, queue, hosted service, or full
113
+ agent framework. Applications choose when and where to run a task.
@@ -0,0 +1,79 @@
1
+ # agent-runtime-kit
2
+
3
+ `agent-runtime-kit` gives Python 3.10+ applications one typed, async API for
4
+ running coding-agent tasks with Claude Agent SDK, OpenAI Codex SDK, or Google
5
+ Antigravity SDK. It exposes capability checks, events, diagnostics, and results
6
+ while keeping each provider's permissions and supported inputs explicit.
7
+
8
+ ## Install and try it offline
9
+
10
+ The core install has no vendor SDK or credential requirement:
11
+
12
+ ```bash
13
+ python -m pip install agent-runtime-kit
14
+ ```
15
+
16
+ ```python
17
+ import asyncio
18
+
19
+ from agent_runtime_kit import AgentKit, FakeAgentRuntime
20
+
21
+
22
+ async def main() -> None:
23
+ async with AgentKit() as kit:
24
+ result = await kit.run(
25
+ FakeAgentRuntime(output="offline example complete"),
26
+ goal="Demonstrate a task result",
27
+ )
28
+ if not result.is_success:
29
+ raise RuntimeError(result.error or result.finish_reason)
30
+ print(result.output)
31
+
32
+
33
+ asyncio.run(main())
34
+ ```
35
+
36
+ This prints `offline example complete`. The fake runtime returns a deterministic
37
+ result; it does not inspect the repository or contact a provider. Run the file
38
+ version with `python -m examples.basic_offline` from a source checkout.
39
+
40
+ ## Run a real provider
41
+
42
+ Install only the provider you use, then configure its supported authentication:
43
+
44
+ ```bash
45
+ python -m pip install "agent-runtime-kit[claude]" # Claude Agent SDK
46
+ python -m pip install "agent-runtime-kit[codex]" # OpenAI Codex SDK
47
+ python -m pip install "agent-runtime-kit[antigravity]" # Google Antigravity SDK
48
+ ```
49
+
50
+ `agent-runtime-kit[all]` installs all three. A real task may use a paid provider
51
+ and may invoke tools. After setting up the chosen provider, run one explicitly
52
+ from a source checkout:
53
+
54
+ ```bash
55
+ python -m examples.provider_task claude
56
+ ```
57
+
58
+ Choose `codex` or `antigravity` instead to use that runtime. The example checks
59
+ package availability, probes setup, requests read-only filesystem access, and
60
+ checks `result.is_success`. Readiness only indicates whether a task is worth
61
+ attempting; it cannot guarantee the provider will accept the request.
62
+
63
+ The adapters share `AgentTask` and `AgentResult`, but inputs are not silently
64
+ discarded. For example, Claude supports per-task MCP servers and a cost budget;
65
+ Codex does not expose either per task; Antigravity supports MCP servers without
66
+ per-server environment values. Unsupported inputs raise typed errors. The
67
+ provider's native model selection is used unless you set a model explicitly.
68
+
69
+ ## Guides
70
+
71
+ - [Quickstart](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/quickstart.md): install, offline result, and first provider run
72
+ - [Examples](https://github.com/ebarti/agent-runtime-kit/blob/main/examples/README.md): runnable commands and expected results
73
+ - [Recipes](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/recipes.md): results, events, preflight, permissions, sessions, and MCP
74
+ - [Provider diagnostics](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/providers.md) and [capability matrix](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/capability-matrix.md)
75
+ - [Deadlines and cancellation](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/task-control.md) and [API stability](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/api-stability.md)
76
+ - [Live smoke tests](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/live-smoke.md) and [SDK evolution agent](https://github.com/ebarti/agent-runtime-kit/blob/main/docs/sdk-evolution-agent.md)
77
+
78
+ The package is a runtime layer, not a router, queue, hosted service, or full
79
+ agent framework. Applications choose when and where to run a task.
@@ -153,6 +153,17 @@ per-query session id. `AgentResult.metadata["sdk_process_reuse_scope"]` reports
153
153
  `"conversation"` or `"shared"` accordingly. The runtime restarts the SDK process
154
154
  when the option fingerprint changes and evicts it after SDK exceptions.
155
155
 
156
+ With Claude Agent SDK 0.2.158 or newer, pass
157
+ `ClaudeAgentRuntime(verbatim_prompts=True)` when goals contain composed or
158
+ third-party text. This opts into the SDK's literal prompt delivery: `@path`
159
+ mentions and slash commands are not expanded or dispatched. The default stays
160
+ `False`. An older SDK that cannot accept the requested option raises
161
+ `UnsupportedTaskInputError` before dispatch. The bundled Claude CLI must be
162
+ 2.1.248 or newer; older custom CLIs may ignore the option. Verbatim delivery also
163
+ skips the CLI's initial attachment pass, including MCP mentions, nested
164
+ `CLAUDE.md`/rules, and skill/tool listings; some context arrives after the first
165
+ tool call instead. It applies to both one-shot and reused-process execution.
166
+
156
167
  Codex uses the `openai-codex` package and maps working directory, session
157
168
  resume, approval mode, sandbox, structured output, model, and reasoning effort.
158
169
  Approval mode follows `PermissionMode`: `STRICT`/`CAUTIOUS` → `deny_all` (never
@@ -233,6 +244,13 @@ dropped only for `STRICT`. When an explicit `allowed_tools` list is combined wit
233
244
  a `READ_ONLY` filesystem, any non-read-only tool in it is rejected rather than
234
245
  silently granted.
235
246
 
247
+ Antigravity 0.1.20 removes `list_directory`, `search_directory`, and `find_file`
248
+ from its default read-only and nondestructive collections. Request them
249
+ explicitly through `allowed_tools` when needed; they remain valid under
250
+ `READ_ONLY` or `STRICT`. Default and deny-list baselines continue to follow the
251
+ SDK's collections. The SDK also adds `schedule` to those collections; callers
252
+ that need a narrower toolset should provide an explicit allow-list.
253
+
236
254
  A deny-list under a `READ_ONLY` filesystem (or `STRICT`) subtracts from the
237
255
  read-only toolset, and under `DEFAULT`/`CAUTIOUS` from the nondestructive
238
256
  toolset — `disabled_tools` alone would re-enable every unnamed write or
@@ -0,0 +1,114 @@
1
+ # Quickstart
2
+
3
+ `agent-runtime-kit` requires Python 3.10 or newer. Install the core package to
4
+ run the credential-free example:
5
+
6
+ ```bash
7
+ python -m pip install agent-runtime-kit
8
+ ```
9
+
10
+ If you cloned the repository, run examples from its root with
11
+ `python -m examples.basic_offline`. For a standalone script, save the following
12
+ as `offline.py` and run `python offline.py`:
13
+
14
+ ```python
15
+ import asyncio
16
+
17
+ from agent_runtime_kit import AgentKit, FakeAgentRuntime
18
+
19
+
20
+ async def main() -> None:
21
+ async with AgentKit() as kit:
22
+ result = await kit.run(
23
+ FakeAgentRuntime(output="offline example complete"),
24
+ goal="Demonstrate a task result",
25
+ )
26
+ if not result.is_success:
27
+ raise RuntimeError(result.error or result.finish_reason)
28
+ print(result.output)
29
+
30
+
31
+ asyncio.run(main())
32
+ ```
33
+
34
+ Expected output: `offline example complete`. `FakeAgentRuntime` is a
35
+ deterministic test runtime. Its goal is carried through the API, but it does not
36
+ read files or call a model.
37
+
38
+ ## Choose a provider
39
+
40
+ Install exactly the extra you need, or use `agent-runtime-kit[all]`:
41
+
42
+ ```bash
43
+ python -m pip install "agent-runtime-kit[claude]"
44
+ python -m pip install "agent-runtime-kit[codex]"
45
+ python -m pip install "agent-runtime-kit[antigravity]"
46
+ ```
47
+
48
+ Set up authentication with the provider's supported mechanism: [Claude Agent
49
+ SDK](https://code.claude.com/docs/en/agent-sdk/overview), [Codex
50
+ authentication](https://learn.chatgpt.com/docs/auth), or [Antigravity SDK
51
+ setup](https://github.com/google-antigravity/antigravity-sdk-python). For
52
+ example, Codex supports `codex login` and `codex login status`; Antigravity's
53
+ API-key path uses `GEMINI_API_KEY`. See [provider notes](providers.md) for this
54
+ package's exact adapter mappings.
55
+
56
+ From a source checkout, run one chosen provider:
57
+
58
+ ```bash
59
+ python -m examples.provider_task claude
60
+ ```
61
+
62
+ The command takes `claude`, `codex`, or `antigravity`. It may make a paid model
63
+ call. It checks the installed package and bounded readiness probe, then asks
64
+ the provider to summarize the current directory with explicit read-only
65
+ filesystem access. A confirmed `NOT_READY` result stops the example;
66
+ `INDETERMINATE` also stops until you explicitly pass `--attempt-indeterminate`.
67
+ That flag is a caller policy choice, not proof of readiness.
68
+
69
+ ## Use the API directly
70
+
71
+ ```python
72
+ import asyncio
73
+ from pathlib import Path
74
+
75
+ from agent_runtime_kit import AgentKit, ReadinessStatus
76
+
77
+
78
+ async def main() -> None:
79
+ async with AgentKit() as kit:
80
+ provider = "claude"
81
+ availability = kit.availability_for(provider)
82
+ if not availability.available:
83
+ raise RuntimeError(availability.message)
84
+
85
+ readiness = await kit.readiness_for(provider)
86
+ if readiness.status is not ReadinessStatus.READY_TO_ATTEMPT:
87
+ raise RuntimeError(readiness.message)
88
+
89
+ result = await kit.run(
90
+ provider,
91
+ goal="Summarize the purpose of this repository in one paragraph.",
92
+ working_directory=Path.cwd(),
93
+ permissions="strict",
94
+ filesystem="read-only",
95
+ )
96
+ if not result.is_success:
97
+ raise RuntimeError(result.error or result.finish_reason)
98
+ print(result.output)
99
+
100
+
101
+ asyncio.run(main())
102
+ ```
103
+
104
+ `AgentKit` lazily resolves and caches built-in runtimes; `async with` closes
105
+ those it created. A runtime instance passed directly to `run` remains the
106
+ caller's responsibility to close. `permissions="strict"` alone does not
107
+ request read-only filesystem access: the default filesystem posture is
108
+ `workspace-write`. Each provider maps permission requests through its own SDK,
109
+ so check the [capability matrix](capability-matrix.md) before relying on a
110
+ particular tool posture.
111
+
112
+ For typed output and event examples, see the [runnable example
113
+ index](../examples/README.md). The [recipes](recipes.md) explain result
114
+ semantics, compatibility preflight, sessions, and MCP.
@@ -0,0 +1,125 @@
1
+ # Practical recipes
2
+
3
+ These recipes use the public API. Start with the [quickstart](quickstart.md)
4
+ and [runnable examples](../examples/README.md).
5
+
6
+ ## Handle results and errors
7
+
8
+ `run()` can raise for invalid or unsupported inputs, missing runtimes, and
9
+ deadlines. It can also return an `AgentResult` whose `finish_reason` is not
10
+ `done` or whose `error` is set. Always check `is_success` before using output:
11
+
12
+ ```python
13
+ result = await kit.run(
14
+ "claude",
15
+ goal="Summarize this repository",
16
+ permissions="strict",
17
+ filesystem="read-only",
18
+ )
19
+ if not result.is_success:
20
+ raise RuntimeError(result.error or result.finish_reason)
21
+ print(result.output)
22
+ ```
23
+
24
+ For `output_type=Summary`, `result.parsed` is a validated instance on a
25
+ successful non-null result. A mismatched payload becomes a failed result.
26
+ Use `result.parsed_output_available` to distinguish an absent structured
27
+ payload from valid JSON `null`; both have `parsed_output is None`. Usage and
28
+ cost fields are `None` when the provider does not report them, while reported
29
+ zero stays zero. Built-in runtimes currently leave `artifacts` empty.
30
+
31
+ ## Separate preflight from setup
32
+
33
+ Use `kit.validate_task(provider, task)` to list statically detectable
34
+ unsupported fields without dispatching a task. Use
35
+ `kit.availability_for(provider)` for a synchronous, package-only check. Use
36
+ `await kit.readiness_for(provider)` for a bounded setup probe:
37
+
38
+ ```python
39
+ from agent_runtime_kit import AgentTask, ReadinessStatus
40
+
41
+ task = AgentTask(goal="Summarize this repository")
42
+ report = kit.validate_task("codex", task)
43
+ if not report.supported:
44
+ for issue in report.issues:
45
+ print(issue.field, issue.message)
46
+
47
+ availability = kit.availability_for("codex")
48
+ if availability.available:
49
+ readiness = await kit.readiness_for("codex")
50
+ if readiness.status is ReadinessStatus.READY_TO_ATTEMPT:
51
+ print("Setup detected; a task may be attempted")
52
+ ```
53
+
54
+ These checks answer different questions. Static support does not prove that a
55
+ package is installed. Package availability does not prove credentials or
56
+ network access. `READY_TO_ATTEMPT` means setup was detected, not that a task
57
+ will succeed. `INDETERMINATE` requires an application policy decision; it is
58
+ not a positive readiness result. The [provider diagnostics](providers.md)
59
+ describe safe probe behavior.
60
+
61
+ ## Request permissions explicitly
62
+
63
+ ```python
64
+ result = await kit.run(
65
+ "claude",
66
+ goal="Summarize this repository",
67
+ permissions="strict",
68
+ filesystem="read-only",
69
+ )
70
+ ```
71
+
72
+ The default filesystem request is `workspace-write`, even under `strict`.
73
+ Adapters map both settings to vendor controls; they are not a universal OS
74
+ sandbox guarantee. `permissions.network` has no supported per-task mapping in
75
+ the built-in adapters and is rejected. Tool allow/deny lists and approval
76
+ behavior differ by provider. Read the [capability matrix](capability-matrix.md)
77
+ before requesting a more permissive posture.
78
+
79
+ `sdk_executions` is an informational task/event field, not a portable turn or
80
+ spend cap. Only Claude maps `budget_usd`; Codex and Antigravity reject it.
81
+ Use [deadlines and cancellation](task-control.md) to bound a task's duration.
82
+
83
+ ## Observe events
84
+
85
+ `AgentKit.on()` registers a sync or async handler for normalized event names.
86
+ Register before dispatch. Handler failures are swallowed so logging cannot
87
+ break a run; send events to your own durable sink if they must be retained.
88
+
89
+ ```python
90
+ @kit.on("agent.tool.completed")
91
+ def log_tool(event):
92
+ print(event["summary"])
93
+ ```
94
+
95
+ See `python -m examples.events` for a complete offline run. Events may contain
96
+ redacted or truncated attributes; a tool audit is best-effort evidence of what
97
+ the vendor reported, not proof that no other side effect occurred.
98
+
99
+ ## Resume a session when supported
100
+
101
+ Pass `session_id` or `resume_from` on a task, but not both. Save a returned
102
+ `result.session_id` if you need it later, and check session support for the
103
+ chosen runtime before reuse. An omitted handle starts a task-isolated
104
+ conversation; process reuse does not imply session reuse. Provider-specific
105
+ session behavior is documented in [provider notes](providers.md).
106
+
107
+ ## Configure an MCP server where supported
108
+
109
+ ```python
110
+ from agent_runtime_kit import AgentTask, McpServerConfig
111
+
112
+ task = AgentTask(
113
+ goal="Use the local documentation server",
114
+ mcp_servers=(McpServerConfig(name="docs", command="my-docs-mcp"),),
115
+ )
116
+ report = kit.validate_task("claude", task)
117
+ if not report.supported:
118
+ raise ValueError(report.issues)
119
+ ```
120
+
121
+ Claude and Antigravity accept per-task stdio MCP servers; Codex rejects
122
+ per-task MCP configuration. Antigravity does not accept per-server `env` values.
123
+ The command starts only when a real task is dispatched. Choose and trust the
124
+ server executable as you would any local process. See the [capability
125
+ matrix](capability-matrix.md) for other differences.
@@ -10,7 +10,10 @@ deadline at call time.
10
10
  from agent_runtime_kit import AgentKit, AgentTaskTimeoutError
11
11
 
12
12
  try:
13
- result = await kit.run("codex", goal="Refactor the parser", timeout=30)
13
+ result = await kit.run(
14
+ "codex", goal="Inspect the parser", timeout=30,
15
+ permissions="strict", filesystem="read-only",
16
+ )
14
17
  except AgentTaskTimeoutError as exc:
15
18
  print(exc.task_id, exc.deadline)
16
19
  ```
@@ -25,23 +28,55 @@ that grace, the runtime instance is quarantined and rejects new runs rather than
25
28
  overlapping them; it becomes reusable when the detached cleanup finally settles.
26
29
 
27
30
  To cancel a task started through `AgentKit`, keep its task id and use the same
28
- runtime instance or cached kind:
31
+ runtime instance or cached kind. Wait for its started event (or for an early
32
+ completion) before calling `cancel()`; scheduling `kit.run()` with
33
+ `asyncio.create_task()` does not guarantee that it has registered the run yet.
34
+ This example makes a real provider call and may incur charges:
29
35
 
30
36
  ```python
31
37
  import asyncio
32
38
 
33
- task_id = "index-repository"
34
- running = asyncio.create_task(
35
- kit.run("claude", goal="Index the repository", task_id=task_id)
36
- )
37
- receipt = await kit.cancel("claude", task_id)
39
+ from agent_runtime_kit import AgentKit
40
+
41
+
42
+ async def main() -> None:
43
+ task_id = "index-repository"
44
+ started = asyncio.Event()
45
+ async with AgentKit() as kit:
46
+
47
+ @kit.on("agent.task.started")
48
+ def on_started(event):
49
+ if event["attributes"]["task_id"] == task_id:
50
+ started.set()
51
+
52
+ running = asyncio.create_task(
53
+ kit.run(
54
+ "claude", goal="Index the repository", task_id=task_id,
55
+ permissions="strict", filesystem="read-only",
56
+ )
57
+ )
58
+ start_wait = asyncio.create_task(started.wait())
59
+ try:
60
+ done, _ = await asyncio.wait(
61
+ {running, start_wait}, return_when=asyncio.FIRST_COMPLETED
62
+ )
63
+ if running in done:
64
+ result = await running # completed or failed before cancellation
65
+ print(result.finish_reason)
66
+ return
67
+ receipt = await kit.cancel("claude", task_id)
68
+ print(receipt.disposition)
69
+ try:
70
+ result = await running
71
+ print(result.finish_reason) # it may finish before cancellation takes effect
72
+ except asyncio.CancelledError:
73
+ print("cancelled")
74
+ finally:
75
+ start_wait.cancel()
76
+ await asyncio.gather(start_wait, return_exceptions=True)
38
77
 
39
- try:
40
- await running
41
- except asyncio.CancelledError:
42
- pass
43
78
 
44
- print(receipt.disposition)
79
+ asyncio.run(main())
45
80
  ```
46
81
 
47
82
  `cancel()` does not construct a runtime that has not already been cached, and
@@ -0,0 +1,41 @@
1
+ # Runnable examples
2
+
3
+ Run these commands from the repository root with Python 3.10+ after installing
4
+ the package locally (`python -m pip install -e .`), or use `uv run --locked`
5
+ before each `python` command. The commands in this table use the core package,
6
+ need no credentials, and make no provider calls.
7
+
8
+ | Command | Expected behavior |
9
+ | --- | --- |
10
+ | `python -m examples.basic_offline` | Prints `offline example complete`. The fake returns a fixture; it does not read files. |
11
+ | `python -m examples.structured_output` | Prints `example: Python` after validating a dataclass result. |
12
+ | `python -m examples.events` | Prints `agent.task.started`, `agent.tool.completed`, then `agent.task.completed`. |
13
+ | `python -m examples.diagnostics fake --probe-readiness` | Prints available package and `ready-to-attempt`; no task runs. |
14
+ | `python -m examples.diagnostics codex` | Reports package availability only and exits nonzero if missing. This does not inspect credentials or run a task. |
15
+
16
+ The following commands use a real vendor runtime. Install its extra and follow
17
+ the [provider setup guide](../docs/quickstart.md#choose-a-provider). A provider
18
+ call may incur charges and may run tools; the examples request strict,
19
+ read-only filesystem access through the adapter. Check the [permission
20
+ mapping](../docs/capability-matrix.md) for each provider's exact behavior.
21
+
22
+ | Command | Expected behavior |
23
+ | --- | --- |
24
+ | `python -m examples.diagnostics claude --probe-readiness` | Prints package and setup readiness, exiting zero only for `ready-to-attempt`, without running an agent task. |
25
+ | `python -m examples.provider_task claude` | Checks setup and runs one Claude task if ready; prints its output on success. |
26
+ | `python -m examples.provider_task codex` | Runs one Codex task after the same checks. |
27
+ | `python -m examples.provider_task antigravity` | Runs one Antigravity task after the same checks. |
28
+ | `python -m examples.run_same_task claude codex` | Runs the same task sequentially through the two named providers. Nothing runs unless you name it. |
29
+
30
+ For diagnostics, `not-ready` and `indeterminate` readiness both return a nonzero
31
+ status; applications can choose their own policy for `indeterminate`. Use
32
+ `--attempt-indeterminate` with the provider task or comparison command to
33
+ explicitly attempt a provider whose bounded setup probe could not determine
34
+ readiness. A confirmed `not-ready` status still stops. Missing extras, failed
35
+ results, and provider exceptions print an error and yield a nonzero exit code.
36
+ The commands choose the provider's native model default; set a task model in
37
+ your application when you need a fixed model.
38
+
39
+ The comparison command closes cached runtime resources at the end of the run.
40
+ No example stores secrets or starts a paid call during import or `--help`.
41
+ See [recipes](../docs/recipes.md) for error handling and input compatibility.
@@ -0,0 +1,20 @@
1
+ """Run one deterministic task with the vendor-SDK-free core package."""
2
+
3
+ import asyncio
4
+
5
+ from agent_runtime_kit import AgentKit, FakeAgentRuntime
6
+
7
+
8
+ async def main() -> None:
9
+ async with AgentKit() as kit:
10
+ result = await kit.run(
11
+ FakeAgentRuntime(output="offline example complete"),
12
+ goal="Demonstrate a task result",
13
+ )
14
+ if not result.is_success:
15
+ raise RuntimeError(result.error or result.finish_reason)
16
+ print(result.output)
17
+
18
+
19
+ if __name__ == "__main__":
20
+ asyncio.run(main())
@@ -0,0 +1,33 @@
1
+ """Inspect package availability and, optionally, bounded setup readiness."""
2
+
3
+ import argparse
4
+ import asyncio
5
+
6
+ from agent_runtime_kit import AgentKit, ReadinessStatus
7
+
8
+
9
+ async def main(provider: str, probe_readiness: bool) -> int:
10
+ async with AgentKit() as kit:
11
+ availability = kit.availability_for(provider)
12
+ print(f"{provider} package: {'available' if availability.available else 'unavailable'}")
13
+ if not availability.available:
14
+ print(availability.message)
15
+ success = availability.available
16
+ if probe_readiness:
17
+ readiness = await kit.readiness_for(provider)
18
+ print(f"{provider} readiness: {readiness.status.value}")
19
+ print(readiness.message)
20
+ success = success and readiness.status is ReadinessStatus.READY_TO_ATTEMPT
21
+ return 0 if success else 1
22
+
23
+
24
+ if __name__ == "__main__":
25
+ parser = argparse.ArgumentParser(description=__doc__)
26
+ parser.add_argument("provider", choices=("fake", "claude", "codex", "antigravity"))
27
+ parser.add_argument(
28
+ "--probe-readiness",
29
+ action="store_true",
30
+ help="probe provider setup without running an agent task",
31
+ )
32
+ arguments = parser.parse_args()
33
+ raise SystemExit(asyncio.run(main(arguments.provider, arguments.probe_readiness)))