adk-code-mode 2.0.0__tar.gz → 2.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.github/workflows/release-please.yml +2 -2
- adk_code_mode-2.1.0/.release-please-manifest.json +3 -0
- adk_code_mode-2.1.0/CHANGELOG.md +177 -0
- adk_code_mode-2.0.0/README.md → adk_code_mode-2.1.0/PKG-INFO +70 -27
- adk_code_mode-2.0.0/PKG-INFO → adk_code_mode-2.1.0/README.md +43 -54
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/docker/Dockerfile +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/pyproject.toml +4 -4
- adk_code_mode-2.1.0/sandbox-wheel/README.md +14 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/pyproject.toml +4 -4
- adk_code_mode-2.1.0/sandbox-wheel/src/adk_code_mode_sandbox/__about__.py +4 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/src/adk_code_mode_sandbox/__init__.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/src/adk_code_mode_sandbox/__main__.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/src/adk_code_mode_sandbox/_entry.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/src/adk_code_mode_sandbox/_http_server.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/src/adk_code_mode_sandbox/_interrupt.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/sandbox-wheel/src/adk_code_mode_sandbox/_rpc_client.py +1 -1
- {adk_code_mode-2.0.0/src/adk_code_mode/runtime → adk_code_mode-2.1.0/sandbox-wheel/src/adk_code_mode_sandbox}/protocol.py +1 -1
- adk_code_mode-2.1.0/src/adk_code_mode/__about__.py +4 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/__init__.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/_artifact_tools.py +1 -1
- adk_code_mode-2.1.0/src/adk_code_mode/_json.py +43 -0
- adk_code_mode-2.1.0/src/adk_code_mode/mcp_results.py +30 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/metadata.py +35 -14
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/output.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/runtime/__init__.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/runtime/base.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/runtime/docker.py +2 -2
- {adk_code_mode-2.0.0/sandbox-wheel/src/adk_code_mode_sandbox → adk_code_mode-2.1.0/src/adk_code_mode/runtime}/protocol.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/runtime/remote.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tool.py +44 -52
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tool_failures.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tool_result_artifacts.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tools/__init__.py +1 -1
- adk_code_mode-2.1.0/src/adk_code_mode/tools/catalog.py +69 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tools/dispatcher.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tools/namespacing.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tools/normaliser.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/tools/stubs.py +290 -20
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/workspace/__init__.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/workspace/files.py +1 -1
- adk_code_mode-2.1.0/tests/__init__.py +3 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/_docker_helpers.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/_fake_runtime.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/_rest_tool.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/conftest.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_agent_with_fake_llm.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_artifact_tools.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_catalog.py +49 -2
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_dispatcher.py +56 -18
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_docker_image.py +4 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_docker_integration.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_host_loop.py +3 -3
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_integration.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_metadata.py +9 -4
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_namespacing.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_normaliser.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_output.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_protocol.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_remote_backend.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_remote_integration.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_runtime_docker.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_sandbox_entry.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_sandbox_rpc_client.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_stubs.py +337 -2
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_stubs_json_schema.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_tool.py +35 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_tool_result_artifacts.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_version.py +1 -1
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/tests/test_workspace_files.py +1 -1
- adk_code_mode-2.0.0/.release-please-manifest.json +0 -3
- adk_code_mode-2.0.0/CHANGELOG.md +0 -162
- adk_code_mode-2.0.0/sandbox-wheel/README.md +0 -14
- adk_code_mode-2.0.0/sandbox-wheel/src/adk_code_mode_sandbox/__about__.py +0 -4
- adk_code_mode-2.0.0/src/adk_code_mode/__about__.py +0 -4
- adk_code_mode-2.0.0/src/adk_code_mode/tools/catalog.py +0 -87
- adk_code_mode-2.0.0/tests/__init__.py +0 -3
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.githooks/pre-commit +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.githooks/pre-push +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.github/workflows/ci.yml +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.gitignore +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.prettierrc +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.vscode/settings.json +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/.zed/settings.json +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/LICENSE +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/Makefile +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/release-please-config.json +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/scripts/install-git-hooks.sh +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/src/adk_code_mode/py.typed +0 -0
- {adk_code_mode-2.0.0 → adk_code_mode-2.1.0}/uv.lock +0 -0
|
@@ -112,5 +112,5 @@ jobs:
|
|
|
112
112
|
file: docker/Dockerfile
|
|
113
113
|
push: true
|
|
114
114
|
tags: |
|
|
115
|
-
ghcr.io/
|
|
116
|
-
ghcr.io/
|
|
115
|
+
ghcr.io/buildagenta/adk-code-mode:${{ needs.release-please.outputs.version }}
|
|
116
|
+
ghcr.io/buildagenta/adk-code-mode:latest
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [2.1.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v2.0.1...adk-code-mode-v2.1.0) (2026-11-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* show return types in the catalog and point the names tier at stubs ([#29](https://github.com/buildagenta/adk-code-mode/issues/29)) ([a238bfd](https://github.com/buildagenta/adk-code-mode/commit/a238bfd0eecf0acf371fe879a529a85a9e1f2dba))
|
|
9
|
+
* type stub return values and escape docstrings ([#28](https://github.com/buildagenta/adk-code-mode/issues/28)) ([dcb15ab](https://github.com/buildagenta/adk-code-mode/commit/dcb15abfcecc841dc06f5051f41251a1f6ab9100))
|
|
10
|
+
|
|
11
|
+
## [2.0.1](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v2.0.0...adk-code-mode-v2.0.1) (2026-11-02)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Miscellaneous Chores
|
|
15
|
+
|
|
16
|
+
* credit Agenta as the author ([#25](https://github.com/buildagenta/adk-code-mode/issues/25)) ([bfe577e](https://github.com/buildagenta/adk-code-mode/commit/bfe577e9aaba31ed9d8f6423485b061deb77b963))
|
|
17
|
+
|
|
18
|
+
## [2.0.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.6.1...adk-code-mode-v2.0.0) (2026-09-25)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### ⚠ BREAKING CHANGES
|
|
22
|
+
|
|
23
|
+
* sandbox code that checked a tool result for an `error` key now gets an exception instead, and the sandbox image must be rebuilt for protocol version 3.
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* raise when a tool call fails instead of returning the error ([#22](https://github.com/buildagenta/adk-code-mode/issues/22)) ([489083d](https://github.com/buildagenta/adk-code-mode/commit/489083d988cd7e958e94f3ef6acba6443284abd8))
|
|
28
|
+
* stop a timed-out block without losing the turn's state ([#23](https://github.com/buildagenta/adk-code-mode/issues/23)) ([4720156](https://github.com/buildagenta/adk-code-mode/commit/47201568d0bb06527e32f850b7abb1b465e36920))
|
|
29
|
+
|
|
30
|
+
## [1.6.1](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.6.0...adk-code-mode-v1.6.1) (2026-09-22)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Bug Fixes
|
|
34
|
+
|
|
35
|
+
* exit the sandbox when the host disconnects mid-block ([bd3fb0f](https://github.com/buildagenta/adk-code-mode/commit/bd3fb0fb0d8a0cab9370f2ad6db56dfacf566cb4))
|
|
36
|
+
|
|
37
|
+
## [1.6.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.5.0...adk-code-mode-v1.6.0) (2026-08-29)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
### Features
|
|
41
|
+
|
|
42
|
+
* bound an execute_code block by default ([1609c0d](https://github.com/buildagenta/adk-code-mode/commit/1609c0d24b8563cba51434cd1214b4299aeefc86))
|
|
43
|
+
* expand object oneOf/anyOf branches in tool stub docstrings ([#20](https://github.com/buildagenta/adk-code-mode/issues/20)) ([7d42cb1](https://github.com/buildagenta/adk-code-mode/commit/7d42cb1ee9d9e217d008776dc74a84034f4b67a9))
|
|
44
|
+
|
|
45
|
+
## [1.5.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.4.0...adk-code-mode-v1.5.0) (2026-08-10)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
### Features
|
|
49
|
+
|
|
50
|
+
* scope tool-name uniqueness to each namespace ([#17](https://github.com/buildagenta/adk-code-mode/issues/17)) ([437bc0d](https://github.com/buildagenta/adk-code-mode/commit/437bc0dc930521a933e5c25b4bd6103e9434fc27))
|
|
51
|
+
|
|
52
|
+
## [1.4.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.3.0...adk-code-mode-v1.4.0) (2026-07-28)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
### Features
|
|
56
|
+
|
|
57
|
+
* surface nested schema properties and validation keywords in tool stubs ([608d14b](https://github.com/buildagenta/adk-code-mode/commit/608d14bb115159b2991c7d8d4e3c641977fd0d66))
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Documentation
|
|
61
|
+
|
|
62
|
+
* document stub schema fidelity and the `JSON_SCHEMA_FOR_FUNC_DECL` flag in `README.md` ([219f02b](https://github.com/buildagenta/adk-code-mode/commit/219f02bd493c2e2d7275a0034ef2a40db933859f))
|
|
63
|
+
|
|
64
|
+
## [1.3.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.2.0...adk-code-mode-v1.3.0) (2026-07-23)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Features
|
|
68
|
+
|
|
69
|
+
* describe the sandbox to the model in a tagged `<code-mode>` block ([#14](https://github.com/buildagenta/adk-code-mode/issues/14)) ([662a281](https://github.com/buildagenta/adk-code-mode/commit/662a28138e8632b434e5f1ecd52793f7d83ee097))
|
|
70
|
+
|
|
71
|
+
## [1.2.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.1.0...adk-code-mode-v1.2.0) (2026-07-23)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Features
|
|
75
|
+
|
|
76
|
+
* add `custom_metadata` to the `save_artifact` tool ([dfd9a59](https://github.com/buildagenta/adk-code-mode/commit/dfd9a59bf1718084a1d5c02cc1ea453269223f16))
|
|
77
|
+
|
|
78
|
+
## [1.1.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v1.0.0...adk-code-mode-v1.1.0) (2026-07-15)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### Features
|
|
82
|
+
|
|
83
|
+
* expose `tools` and `backend` as public properties on `ExecuteCodeTool` ([acfb704](https://github.com/buildagenta/adk-code-mode/commit/acfb704d388da5d66e318775e03fe055467679c2))
|
|
84
|
+
|
|
85
|
+
## [1.0.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.4.1...adk-code-mode-v1.0.0) (2026-07-15)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
### ⚠ BREAKING CHANGES
|
|
89
|
+
|
|
90
|
+
* `CodeModeCodeExecutor`, `code_mode_before_model_callback`, and `CODE_MODE_SYSTEM_INSTRUCTION` no longer exist. Add `ExecuteCodeTool` to the agent's `tools=[...]` instead of wiring `code_executor=`; drop `before_model_callback=`, `generate_content_config=`, and `CODE_MODE_SYSTEM_INSTRUCTION` entirely; `release_invocation` is now `async`. See the README's migration section.
|
|
91
|
+
|
|
92
|
+
### Features
|
|
93
|
+
|
|
94
|
+
* replace `CodeModeCodeExecutor` with `ExecuteCodeTool` ([#10](https://github.com/buildagenta/adk-code-mode/issues/10)) ([b78572e](https://github.com/buildagenta/adk-code-mode/commit/b78572e72446930548760756255390d1a3cc388a))
|
|
95
|
+
|
|
96
|
+
## [0.4.1](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.4.0...adk-code-mode-v0.4.1) (2026-07-10)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
### Documentation
|
|
100
|
+
|
|
101
|
+
* note the sandbox writes to `/tools` in remote deployment guide ([96bb45e](https://github.com/buildagenta/adk-code-mode/commit/96bb45e4e18d9d54709f4c10b6b09cf3567ee385))
|
|
102
|
+
|
|
103
|
+
## [0.4.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.3.0...adk-code-mode-v0.4.0) (2026-07-09)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
### Features
|
|
107
|
+
|
|
108
|
+
* save tool results as artifacts with optional model-supplied naming ([76a3671](https://github.com/buildagenta/adk-code-mode/commit/76a36713b2c52bd5b8dc51d3669226a47e7108e5))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
### Bug Fixes
|
|
112
|
+
|
|
113
|
+
* align code-mode example with the `<code-mode>` catalog and fix fences ([4a0cc6d](https://github.com/buildagenta/adk-code-mode/commit/4a0cc6d0fc99d5425f6682cc489e76c9ddef7d46))
|
|
114
|
+
* clarify code-mode tools are a Python library, not function tools ([48d1018](https://github.com/buildagenta/adk-code-mode/commit/48d1018152a2ed2a8e7361de6ce0f43b31b429ce))
|
|
115
|
+
* nudge the model to call tools via Python in the code-mode block ([141baf3](https://github.com/buildagenta/adk-code-mode/commit/141baf3a44976e82cf437b2064666be893d6d409))
|
|
116
|
+
* update `CODE_MODE_SYSTEM_INSTRUCTION` and `README.md` ([933d42c](https://github.com/buildagenta/adk-code-mode/commit/933d42cb237b9d6deeb6611511cba28a0d5e9261))
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
### Documentation
|
|
120
|
+
|
|
121
|
+
* streamline `README.md` and fix broken code fences ([c237514](https://github.com/buildagenta/adk-code-mode/commit/c2375149df48e21318967090b6c85d0b1f411ea2))
|
|
122
|
+
|
|
123
|
+
## [0.3.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.2.2...adk-code-mode-v0.3.0) (2026-07-06)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
### Features
|
|
127
|
+
|
|
128
|
+
* hold one sandbox container open per turn (protocol v2) ([#6](https://github.com/buildagenta/adk-code-mode/issues/6)) ([aebe17d](https://github.com/buildagenta/adk-code-mode/commit/aebe17d2bbbf21cc0f05852efaf910ff6adc3154))
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
### Documentation
|
|
132
|
+
|
|
133
|
+
* lower startup probe period in `README.md` for faster cold starts ([e251af2](https://github.com/buildagenta/adk-code-mode/commit/e251af2cf7307c9944361e1a0e37c7191822a9e1))
|
|
134
|
+
* note HTTP `/health` startup probe in `README.md` Cloud Run section ([d58fb10](https://github.com/buildagenta/adk-code-mode/commit/d58fb10f7aeda95e5c8cf29263a13e1333f661dd))
|
|
135
|
+
|
|
136
|
+
## [0.2.2](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.2.1...adk-code-mode-v0.2.2) (2026-05-08)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
### Bug Fixes
|
|
140
|
+
|
|
141
|
+
* use `python` fences instead of `tool_code` in `CodeModeCodeExecutor` ([efcc11e](https://github.com/buildagenta/adk-code-mode/commit/efcc11e1020c7544223074e00a8649f9c85d4ad6))
|
|
142
|
+
|
|
143
|
+
## [0.2.1](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.2.0...adk-code-mode-v0.2.1) (2026-05-05)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
### Bug Fixes
|
|
147
|
+
|
|
148
|
+
* rename `<tools>` tag to `<code-mode>` and update `CODE_MODE_SYSTEM_INSTRUCTION` ([0a06bfb](https://github.com/buildagenta/adk-code-mode/commit/0a06bfbdf22db6e0226e477d0ed074a6cc4d1515))
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
### Documentation
|
|
152
|
+
|
|
153
|
+
* update `README.md` with deployment instructions ([1dd7a95](https://github.com/buildagenta/adk-code-mode/commit/1dd7a95197fd56231ba97182526a825baf18508a))
|
|
154
|
+
|
|
155
|
+
## [0.2.0](https://github.com/buildagenta/adk-code-mode/compare/adk-code-mode-v0.1.0...adk-code-mode-v0.2.0) (2026-05-03)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
### Features
|
|
159
|
+
|
|
160
|
+
* add `RemoteBackend`, sandbox hardening, and make `README.md` more concise ([a1a70ee](https://github.com/buildagenta/adk-code-mode/commit/a1a70eec0686f164ce3796ba1d82bb82b7fbda59))
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
### Bug Fixes
|
|
164
|
+
|
|
165
|
+
* improve `CODE_MODE_SYSTEM_INSTRUCTION` ([0d00863](https://github.com/buildagenta/adk-code-mode/commit/0d008636e2e273b438192f737e20e207c165a610))
|
|
166
|
+
|
|
167
|
+
## 0.1.0 (2026-04-29)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
### Features
|
|
171
|
+
|
|
172
|
+
* ADK Code Mode: `CodeModeExecutor`, `DockerRuntime`, and more ([6ab1ac2](https://github.com/buildagenta/adk-code-mode/commit/6ab1ac28236d21ecb740d8e920e08e4d9bd969c5))
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
### Documentation
|
|
176
|
+
|
|
177
|
+
* shorten ADK code executor comparison table headers ([28116cf](https://github.com/buildagenta/adk-code-mode/commit/28116cf9f40b3623c31782a55885fa5c4f8c6bbf))
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: adk-code-mode
|
|
3
|
+
Version: 2.1.0
|
|
4
|
+
Summary: A "Code Mode" sandboxed code-execution tool for ADK agents to interact with tools, files, and custom packages with Python
|
|
5
|
+
Project-URL: Documentation, https://github.com/buildagenta/adk-code-mode#readme
|
|
6
|
+
Project-URL: Issues, https://github.com/buildagenta/adk-code-mode/issues
|
|
7
|
+
Project-URL: Source, https://github.com/buildagenta/adk-code-mode
|
|
8
|
+
Author-email: Agenta <hello@buildagenta.com>
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: a2a,adk,agents,code-mode,execute-code
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: google-adk<2.0.0,>=1.0.0
|
|
21
|
+
Requires-Dist: google-genai>=1.0.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Requires-Dist: websockets>=14.0
|
|
24
|
+
Provides-Extra: docker
|
|
25
|
+
Requires-Dist: docker>=7.0.0; extra == 'docker'
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
1
28
|
# ADK Code Mode
|
|
2
29
|
|
|
3
30
|
A [Code Mode](https://blog.cloudflare.com/code-mode/) sandboxed code-execution tool for [Agent Development Kit (ADK)](https://github.com/google/adk-python).
|
|
@@ -14,7 +41,7 @@ Inspired by Cloudflare's [Code Mode](https://blog.cloudflare.com/code-mode/) and
|
|
|
14
41
|
- **Call ADK tools from sandbox code** — imports against the `tools` package proxy back to the host and run through ADK's `before_tool` / `after_tool` / `on_error` callbacks and the plugin manager exactly as direct tool calls would.
|
|
15
42
|
- **Failed tool calls raise** — a REST tool whose API answers with an HTTP error raises `HTTPStatusError` (with `status_code` and `body`), and any other failure, including an MCP tool that reports one, raises `ToolError`. ADK returns these as values for a model to read, but sandbox code reads return values, so it would otherwise carry on as if the call had worked.
|
|
16
43
|
- **Bake any Python package into the image** — extend the published base image with anything the model's code needs to `import`, no runtime `pip install` required. The sandbox reports what it has installed, so the model is told about it automatically.
|
|
17
|
-
- **Cross-turn persistence via ADK Artifacts** — `save_artifact` / `load_artifact` / `list_artifacts` are auto-injected and route through your configured `ArtifactService`.
|
|
44
|
+
- **Cross-turn persistence via ADK Artifacts** — files the code creates or changes are saved as artifacts automatically, and `save_artifact` / `load_artifact` / `list_artifacts` are auto-injected and route through your configured `ArtifactService`.
|
|
18
45
|
- **Tool results saved as artifacts** — on by default; every tool's result is persisted as a `code_mode.tool_result` artifact (with optional model-supplied name/description) so hosts can forward outputs and large results stay out of the prompt. Opt out with `save_tool_results_as_artifacts=False`.
|
|
19
46
|
- **Bounded stdout/stderr** — overflow lands in a session artifact instead of poisoning the prompt.
|
|
20
47
|
- **Production-ready remote sandbox** — `RemoteBackend` connects to an isolated per-turn container over WebSocket, reused across the turn's `execute_code` calls. Deploy on any cloud platform (Cloud Run, Fargate, ACI, Kubernetes, Fly.io, etc.).
|
|
@@ -98,7 +125,7 @@ override_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True)
|
|
|
98
125
|
|
|
99
126
|
tool = ExecuteCodeTool(
|
|
100
127
|
tools=[my_fn_tool, McpToolset(...), OpenAPIToolset(...)],
|
|
101
|
-
backend=UnsafeLocalDockerBackend(image="ghcr.io/
|
|
128
|
+
backend=UnsafeLocalDockerBackend(image="ghcr.io/buildagenta/adk-code-mode:latest"),
|
|
102
129
|
)
|
|
103
130
|
```
|
|
104
131
|
|
|
@@ -118,8 +145,8 @@ print(send_message(channel="C123", text="hi"))
|
|
|
118
145
|
```bash
|
|
119
146
|
# Push the sandbox image to Artifact Registry
|
|
120
147
|
gcloud auth configure-docker <region>-docker.pkg.dev
|
|
121
|
-
docker pull --platform linux/amd64 ghcr.io/
|
|
122
|
-
docker tag ghcr.io/
|
|
148
|
+
docker pull --platform linux/amd64 ghcr.io/buildagenta/adk-code-mode:latest
|
|
149
|
+
docker tag ghcr.io/buildagenta/adk-code-mode:latest \
|
|
123
150
|
<region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
124
151
|
docker push <region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
125
152
|
|
|
@@ -225,9 +252,7 @@ save_artifact(
|
|
|
225
252
|
mime_type="application/json",
|
|
226
253
|
)
|
|
227
254
|
print(list_artifacts())
|
|
228
|
-
report = load_artifact(filename="report.json")
|
|
229
|
-
if report is not None and report["kind"] == "text":
|
|
230
|
-
payload = json.loads(report["data"])
|
|
255
|
+
report = json.loads(load_artifact(filename="report.json")["data"])
|
|
231
256
|
```
|
|
232
257
|
|
|
233
258
|
Pass `include_artifact_tools=False` to opt out. To react when the model saves an artifact, pass `on_artifacts_saved`:
|
|
@@ -243,7 +268,7 @@ ExecuteCodeTool(tools=..., backend=..., on_artifacts_saved=on_saved)
|
|
|
243
268
|
|
|
244
269
|
### Tool results as artifacts
|
|
245
270
|
|
|
246
|
-
By default (`save_tool_results_as_artifacts=True`) every non-artifact tool is wrapped so its return value is saved as a session artifact tagged `code_mode.tool_result = "true"`. This lets a host forward tool outputs to the user (read the marker in `on_artifacts_saved`) and
|
|
271
|
+
By default (`save_tool_results_as_artifacts=True`) every non-artifact tool is wrapped so its return value is saved as a session artifact tagged `code_mode.tool_result = "true"`. This lets a host forward tool outputs to the user (read the marker in `on_artifacts_saved`) and lets a later turn reload a result with `load_artifact`. Results over 50,000 bytes return a dictionary with a `tool_result_artifact` filename and a `note` instead of the inline result.
|
|
247
272
|
|
|
248
273
|
Naming is transparent: the filename is derived from the tool name and call id. Each wrapped tool also gains two **optional** parameters — `artifact_name` and `artifact_description` — that the model may pass to name/describe the saved artifact; both land in the artifact's `custom_metadata` (`code_mode.artifact_name` / `code_mode.artifact_description`) alongside the marker. Set `save_tool_results_as_artifacts=False` to return tool results inline without persisting them.
|
|
249
274
|
|
|
@@ -253,10 +278,10 @@ ExecuteCodeTool(tools=..., backend=..., save_tool_results_as_artifacts=True)
|
|
|
253
278
|
|
|
254
279
|
## 🐳 Sandbox Image
|
|
255
280
|
|
|
256
|
-
The published base image (`ghcr.io/
|
|
281
|
+
The published base image (`ghcr.io/buildagenta/adk-code-mode`) works as-is for tools whose execution is fully host-side. To bake in extra Python packages:
|
|
257
282
|
|
|
258
283
|
```dockerfile
|
|
259
|
-
FROM ghcr.io/
|
|
284
|
+
FROM ghcr.io/buildagenta/adk-code-mode:latest
|
|
260
285
|
RUN pip install --no-cache-dir pandas==2.2.*
|
|
261
286
|
```
|
|
262
287
|
|
|
@@ -311,14 +336,18 @@ Two surfaces, deliberately kept apart. The **tool description** is the invariant
|
|
|
311
336
|
Execute Python code in a sandboxed container. Custom tools are Python functions to
|
|
312
337
|
import from the `tools` package (e.g. `from tools.slack import send_message`). See
|
|
313
338
|
the `<code-mode>` section of the system instruction for the Python version,
|
|
314
|
-
preinstalled packages, and available functions. Print
|
|
315
|
-
stdout/stderr are returned. Variables and
|
|
316
|
-
within the same turn and reset on the next turn
|
|
317
|
-
|
|
318
|
-
|
|
339
|
+
preinstalled packages, and available functions. Print function calls, variables, etc.
|
|
340
|
+
to see output, only stdout/stderr are returned. Variables and files persist across
|
|
341
|
+
calls within the same turn and reset on the next turn. Every file the code writes in
|
|
342
|
+
the working directory, and every tool's result, is saved as an artifact; use
|
|
343
|
+
`load_artifact` (imported the same way) to read one in a later turn. Large tool
|
|
344
|
+
results return a `tool_result_artifact` pointer. Tool calls that
|
|
345
|
+
call APIs raise HTTP errors as `HTTPStatusError` (with `status_code` and `body`);
|
|
346
|
+
other failures raise `ToolError`. Import both from `tools`. Each call can run for up
|
|
347
|
+
to 60s.
|
|
319
348
|
~~~
|
|
320
349
|
|
|
321
|
-
With `append_code_mode_metadata_to_system_instruction` disabled that middle sentence is replaced by
|
|
350
|
+
With `append_code_mode_metadata_to_system_instruction` disabled that middle sentence is replaced by the discovery text the pointer tier uses (see [Fitting the budget](#fitting-the-budget)), so the description never points at a section that wasn't appended. With `save_tool_results_as_artifacts=False` the description drops "and every tool's result" and the sentence about large results, and with `include_artifact_tools=False` it drops the `load_artifact` clause. The last sentence follows `timeout_seconds` and is left out when it's `None`.
|
|
322
351
|
|
|
323
352
|
The **`<code-mode>` block** is the per-deployment inventory of the sandbox, appended to the system instruction on every model turn:
|
|
324
353
|
|
|
@@ -339,7 +368,15 @@ yaml: PyYAML 6.0.2
|
|
|
339
368
|
|
|
340
369
|
from tools.slack import list_channels, send_message
|
|
341
370
|
|
|
342
|
-
|
|
371
|
+
class ListChannelsResponse(TypedDict):
|
|
372
|
+
channels: list[ChannelsItem]
|
|
373
|
+
next_cursor: NotRequired[str]
|
|
374
|
+
|
|
375
|
+
class ChannelsItem(TypedDict):
|
|
376
|
+
id: str
|
|
377
|
+
name: str
|
|
378
|
+
|
|
379
|
+
def list_channels() -> ListChannelsResponse:
|
|
343
380
|
"""List Slack channels."""
|
|
344
381
|
...
|
|
345
382
|
|
|
@@ -355,6 +392,8 @@ from tools import save_artifact, load_artifact, list_artifacts
|
|
|
355
392
|
</code-mode>
|
|
356
393
|
~~~
|
|
357
394
|
|
|
395
|
+
Return types come from each tool's `response_json_schema`, or an MCP tool's `outputSchema`; a tool without one returns `Any`. Objects become `TypedDict` classes named after their `$defs` key or `title`, else the property holding them. Identical shapes share one class across a module, defined once at the top of its catalog section; a name clash with another module's class falls back to the tool's or parent's name; each stub file carries the classes its tool uses. An MCP tool's `outputSchema` describes the `structuredContent` field in its result. A saved tool result can also be a `ToolResultArtifact` pointer when it exceeds the size threshold. A tool with exactly one required parameter takes it positionally (`load_artifact("report.csv", version=2)`); every other parameter is keyword-only.
|
|
396
|
+
|
|
358
397
|
Tags are indented; their content is not. The `<tools-package>` body is Python source, where leading whitespace is meaningful. Each installed-package line is `<import name>: <distribution> <version>`; namespace imports supplied by multiple distributions list every provider in deterministic order. Import names and providers are sorted so the block stays byte-stable for prompt caching. `<python-version>` and `<installed-packages>` are omitted entirely — rather than rendered blank — when the sandbox hasn't reported yet or the image has no extra packages, since an empty tag reads as "none exist".
|
|
359
398
|
|
|
360
399
|
With `save_tool_results_as_artifacts` enabled (the default), each non-artifact tool above — e.g. `list_channels` and `send_message` — also carries two optional `artifact_name: str | None = ...` / `artifact_description: str | None = ...` parameters for naming its saved result.
|
|
@@ -364,7 +403,10 @@ With `save_tool_results_as_artifacts` enabled (the default), each non-artifact t
|
|
|
364
403
|
A block over `max_code_mode_metadata_chars` degrades in tiers instead of vanishing. The Python version and package list survive every tier — they're small, and the model cannot discover them any other way.
|
|
365
404
|
|
|
366
405
|
1. **Full** — as above.
|
|
367
|
-
2. **Names only** — signatures and docstrings dropped, import lines kept:
|
|
406
|
+
2. **Names only** — types, signatures and docstrings dropped, import lines kept. `<how-to-use>` gains:
|
|
407
|
+
|
|
408
|
+
> Before calling a function you haven't used, print its stub to see its signature, docstring and the fields of its return type: `/tools/<module>/<fn>.py`, or `/tools/<fn>.py` for a function imported from `tools`. Print every stub you need in one `execute_code` call.
|
|
409
|
+
|
|
368
410
|
|
|
369
411
|
~~~
|
|
370
412
|
<tools-package>
|
|
@@ -374,11 +416,11 @@ A block over `max_code_mode_metadata_chars` degrades in tiers instead of vanishi
|
|
|
374
416
|
</tools-package>
|
|
375
417
|
~~~
|
|
376
418
|
|
|
377
|
-
3. **Pointer** — the catalog is replaced by a
|
|
419
|
+
3. **Pointer** — the catalog is replaced by a note, and this tier is emitted no matter how small the budget. `<how-to-use>` gains the same text, prefixed with "List `/tools/` and its module directories to find the functions available.":
|
|
378
420
|
|
|
379
421
|
~~~
|
|
380
422
|
<tools-package>
|
|
381
|
-
The full catalog is too large to include here.
|
|
423
|
+
The full catalog is too large to include here.
|
|
382
424
|
</tools-package>
|
|
383
425
|
~~~
|
|
384
426
|
|
|
@@ -386,11 +428,12 @@ At the last tier the model navigates the sandbox from Python instead:
|
|
|
386
428
|
|
|
387
429
|
```python
|
|
388
430
|
import pathlib
|
|
389
|
-
print(
|
|
390
|
-
print(open("/tools/slack/send_message.py").read()) # signature + docstring
|
|
431
|
+
print(sorted(pathlib.Path("/tools").rglob("*.py")))
|
|
432
|
+
print(open("/tools/slack/send_message.py").read()) # types, signature + docstring
|
|
433
|
+
print(open("/tools/slack/list_channels.py").read())
|
|
391
434
|
```
|
|
392
435
|
|
|
393
|
-
Text and JSON-like MIME types travel as plain strings in artifact tools; binary content is base64-encoded. `load_artifact` returns `
|
|
436
|
+
Text and JSON-like MIME types travel as plain strings in artifact tools; binary content is base64-encoded. `load_artifact` returns a dictionary with `kind`, `data`, and `mime_type`. Text and JSON use `kind="text"` and keep the string in `data`. Binary artifacts use `kind="bytes"` and store base64 in `data`.
|
|
394
437
|
|
|
395
438
|
## 🛡️ Safety
|
|
396
439
|
|
|
@@ -423,7 +466,7 @@ Named "Unsafe" intentionally: it binds a TCP listener on `0.0.0.0`, communicates
|
|
|
423
466
|
## ⚠️ Limitations
|
|
424
467
|
|
|
425
468
|
- **No credential-requesting tools.** Tools that need ADK to request credentials, confirmations, UI widgets, agent transfer, escalation, or that yield without an immediate response are rejected with a structured error.
|
|
426
|
-
- **State is turn-scoped.** Variables and the working directory persist across `execute_code` calls **within** a turn, but reset between turns.
|
|
469
|
+
- **State is turn-scoped.** Variables and the working directory persist across `execute_code` calls **within** a turn, but reset between turns. Files the code writes and tool results are saved as artifacts; use `load_artifact` to read them in a later turn.
|
|
427
470
|
- **No runtime package installation.** The sandbox ships with the Python Standard Library and the runtime's own dependencies only. Extra packages must be baked into the image at build time.
|
|
428
471
|
|
|
429
472
|
## 🛠️ Development
|
|
@@ -443,9 +486,9 @@ uv run pytest -m docker
|
|
|
443
486
|
|
|
444
487
|
`adk-code-mode` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
|
|
445
488
|
|
|
446
|
-
## 🤝 Join the
|
|
489
|
+
## 🤝 Join the Agenta Community
|
|
447
490
|
|
|
448
|
-
|
|
491
|
+
Agenta is a site to find and share AI agents and open-source community. Join to share your A2A agents, ask questions, stay up-to-date with the latest A2A news, be the first to hear about open-source releases, tutorials, and more!
|
|
449
492
|
|
|
450
|
-
- 🌍 Site: [
|
|
493
|
+
- 🌍 Site: [Agenta](https://buildagenta.com)
|
|
451
494
|
- 🤖 Discord: [Join the Discord](https://discord.gg/674NGXpAjU)
|
|
@@ -1,30 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: adk-code-mode
|
|
3
|
-
Version: 2.0.0
|
|
4
|
-
Summary: A "Code Mode" sandboxed code-execution tool for ADK agents to interact with tools, files, and custom packages with Python
|
|
5
|
-
Project-URL: Documentation, https://github.com/A2ANet/adk-code-mode#readme
|
|
6
|
-
Project-URL: Issues, https://github.com/A2ANet/adk-code-mode/issues
|
|
7
|
-
Project-URL: Source, https://github.com/A2ANet/adk-code-mode
|
|
8
|
-
Author-email: A2A Net <hello@a2anet.com>
|
|
9
|
-
License-Expression: Apache-2.0
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Keywords: a2a,adk,agents,code-mode,execute-code
|
|
12
|
-
Classifier: Development Status :: 4 - Beta
|
|
13
|
-
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
-
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: google-adk<2.0.0,>=1.0.0
|
|
21
|
-
Requires-Dist: google-genai>=1.0.0
|
|
22
|
-
Requires-Dist: pydantic>=2.0.0
|
|
23
|
-
Requires-Dist: websockets>=14.0
|
|
24
|
-
Provides-Extra: docker
|
|
25
|
-
Requires-Dist: docker>=7.0.0; extra == 'docker'
|
|
26
|
-
Description-Content-Type: text/markdown
|
|
27
|
-
|
|
28
1
|
# ADK Code Mode
|
|
29
2
|
|
|
30
3
|
A [Code Mode](https://blog.cloudflare.com/code-mode/) sandboxed code-execution tool for [Agent Development Kit (ADK)](https://github.com/google/adk-python).
|
|
@@ -41,7 +14,7 @@ Inspired by Cloudflare's [Code Mode](https://blog.cloudflare.com/code-mode/) and
|
|
|
41
14
|
- **Call ADK tools from sandbox code** — imports against the `tools` package proxy back to the host and run through ADK's `before_tool` / `after_tool` / `on_error` callbacks and the plugin manager exactly as direct tool calls would.
|
|
42
15
|
- **Failed tool calls raise** — a REST tool whose API answers with an HTTP error raises `HTTPStatusError` (with `status_code` and `body`), and any other failure, including an MCP tool that reports one, raises `ToolError`. ADK returns these as values for a model to read, but sandbox code reads return values, so it would otherwise carry on as if the call had worked.
|
|
43
16
|
- **Bake any Python package into the image** — extend the published base image with anything the model's code needs to `import`, no runtime `pip install` required. The sandbox reports what it has installed, so the model is told about it automatically.
|
|
44
|
-
- **Cross-turn persistence via ADK Artifacts** — `save_artifact` / `load_artifact` / `list_artifacts` are auto-injected and route through your configured `ArtifactService`.
|
|
17
|
+
- **Cross-turn persistence via ADK Artifacts** — files the code creates or changes are saved as artifacts automatically, and `save_artifact` / `load_artifact` / `list_artifacts` are auto-injected and route through your configured `ArtifactService`.
|
|
45
18
|
- **Tool results saved as artifacts** — on by default; every tool's result is persisted as a `code_mode.tool_result` artifact (with optional model-supplied name/description) so hosts can forward outputs and large results stay out of the prompt. Opt out with `save_tool_results_as_artifacts=False`.
|
|
46
19
|
- **Bounded stdout/stderr** — overflow lands in a session artifact instead of poisoning the prompt.
|
|
47
20
|
- **Production-ready remote sandbox** — `RemoteBackend` connects to an isolated per-turn container over WebSocket, reused across the turn's `execute_code` calls. Deploy on any cloud platform (Cloud Run, Fargate, ACI, Kubernetes, Fly.io, etc.).
|
|
@@ -125,7 +98,7 @@ override_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True)
|
|
|
125
98
|
|
|
126
99
|
tool = ExecuteCodeTool(
|
|
127
100
|
tools=[my_fn_tool, McpToolset(...), OpenAPIToolset(...)],
|
|
128
|
-
backend=UnsafeLocalDockerBackend(image="ghcr.io/
|
|
101
|
+
backend=UnsafeLocalDockerBackend(image="ghcr.io/buildagenta/adk-code-mode:latest"),
|
|
129
102
|
)
|
|
130
103
|
```
|
|
131
104
|
|
|
@@ -145,8 +118,8 @@ print(send_message(channel="C123", text="hi"))
|
|
|
145
118
|
```bash
|
|
146
119
|
# Push the sandbox image to Artifact Registry
|
|
147
120
|
gcloud auth configure-docker <region>-docker.pkg.dev
|
|
148
|
-
docker pull --platform linux/amd64 ghcr.io/
|
|
149
|
-
docker tag ghcr.io/
|
|
121
|
+
docker pull --platform linux/amd64 ghcr.io/buildagenta/adk-code-mode:latest
|
|
122
|
+
docker tag ghcr.io/buildagenta/adk-code-mode:latest \
|
|
150
123
|
<region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
151
124
|
docker push <region>-docker.pkg.dev/<project>/<repository>/adk-code-mode-sandbox:latest
|
|
152
125
|
|
|
@@ -252,9 +225,7 @@ save_artifact(
|
|
|
252
225
|
mime_type="application/json",
|
|
253
226
|
)
|
|
254
227
|
print(list_artifacts())
|
|
255
|
-
report = load_artifact(filename="report.json")
|
|
256
|
-
if report is not None and report["kind"] == "text":
|
|
257
|
-
payload = json.loads(report["data"])
|
|
228
|
+
report = json.loads(load_artifact(filename="report.json")["data"])
|
|
258
229
|
```
|
|
259
230
|
|
|
260
231
|
Pass `include_artifact_tools=False` to opt out. To react when the model saves an artifact, pass `on_artifacts_saved`:
|
|
@@ -270,7 +241,7 @@ ExecuteCodeTool(tools=..., backend=..., on_artifacts_saved=on_saved)
|
|
|
270
241
|
|
|
271
242
|
### Tool results as artifacts
|
|
272
243
|
|
|
273
|
-
By default (`save_tool_results_as_artifacts=True`) every non-artifact tool is wrapped so its return value is saved as a session artifact tagged `code_mode.tool_result = "true"`. This lets a host forward tool outputs to the user (read the marker in `on_artifacts_saved`) and
|
|
244
|
+
By default (`save_tool_results_as_artifacts=True`) every non-artifact tool is wrapped so its return value is saved as a session artifact tagged `code_mode.tool_result = "true"`. This lets a host forward tool outputs to the user (read the marker in `on_artifacts_saved`) and lets a later turn reload a result with `load_artifact`. Results over 50,000 bytes return a dictionary with a `tool_result_artifact` filename and a `note` instead of the inline result.
|
|
274
245
|
|
|
275
246
|
Naming is transparent: the filename is derived from the tool name and call id. Each wrapped tool also gains two **optional** parameters — `artifact_name` and `artifact_description` — that the model may pass to name/describe the saved artifact; both land in the artifact's `custom_metadata` (`code_mode.artifact_name` / `code_mode.artifact_description`) alongside the marker. Set `save_tool_results_as_artifacts=False` to return tool results inline without persisting them.
|
|
276
247
|
|
|
@@ -280,10 +251,10 @@ ExecuteCodeTool(tools=..., backend=..., save_tool_results_as_artifacts=True)
|
|
|
280
251
|
|
|
281
252
|
## 🐳 Sandbox Image
|
|
282
253
|
|
|
283
|
-
The published base image (`ghcr.io/
|
|
254
|
+
The published base image (`ghcr.io/buildagenta/adk-code-mode`) works as-is for tools whose execution is fully host-side. To bake in extra Python packages:
|
|
284
255
|
|
|
285
256
|
```dockerfile
|
|
286
|
-
FROM ghcr.io/
|
|
257
|
+
FROM ghcr.io/buildagenta/adk-code-mode:latest
|
|
287
258
|
RUN pip install --no-cache-dir pandas==2.2.*
|
|
288
259
|
```
|
|
289
260
|
|
|
@@ -338,14 +309,18 @@ Two surfaces, deliberately kept apart. The **tool description** is the invariant
|
|
|
338
309
|
Execute Python code in a sandboxed container. Custom tools are Python functions to
|
|
339
310
|
import from the `tools` package (e.g. `from tools.slack import send_message`). See
|
|
340
311
|
the `<code-mode>` section of the system instruction for the Python version,
|
|
341
|
-
preinstalled packages, and available functions. Print
|
|
342
|
-
stdout/stderr are returned. Variables and
|
|
343
|
-
within the same turn and reset on the next turn
|
|
344
|
-
|
|
345
|
-
|
|
312
|
+
preinstalled packages, and available functions. Print function calls, variables, etc.
|
|
313
|
+
to see output, only stdout/stderr are returned. Variables and files persist across
|
|
314
|
+
calls within the same turn and reset on the next turn. Every file the code writes in
|
|
315
|
+
the working directory, and every tool's result, is saved as an artifact; use
|
|
316
|
+
`load_artifact` (imported the same way) to read one in a later turn. Large tool
|
|
317
|
+
results return a `tool_result_artifact` pointer. Tool calls that
|
|
318
|
+
call APIs raise HTTP errors as `HTTPStatusError` (with `status_code` and `body`);
|
|
319
|
+
other failures raise `ToolError`. Import both from `tools`. Each call can run for up
|
|
320
|
+
to 60s.
|
|
346
321
|
~~~
|
|
347
322
|
|
|
348
|
-
With `append_code_mode_metadata_to_system_instruction` disabled that middle sentence is replaced by
|
|
323
|
+
With `append_code_mode_metadata_to_system_instruction` disabled that middle sentence is replaced by the discovery text the pointer tier uses (see [Fitting the budget](#fitting-the-budget)), so the description never points at a section that wasn't appended. With `save_tool_results_as_artifacts=False` the description drops "and every tool's result" and the sentence about large results, and with `include_artifact_tools=False` it drops the `load_artifact` clause. The last sentence follows `timeout_seconds` and is left out when it's `None`.
|
|
349
324
|
|
|
350
325
|
The **`<code-mode>` block** is the per-deployment inventory of the sandbox, appended to the system instruction on every model turn:
|
|
351
326
|
|
|
@@ -366,7 +341,15 @@ yaml: PyYAML 6.0.2
|
|
|
366
341
|
|
|
367
342
|
from tools.slack import list_channels, send_message
|
|
368
343
|
|
|
369
|
-
|
|
344
|
+
class ListChannelsResponse(TypedDict):
|
|
345
|
+
channels: list[ChannelsItem]
|
|
346
|
+
next_cursor: NotRequired[str]
|
|
347
|
+
|
|
348
|
+
class ChannelsItem(TypedDict):
|
|
349
|
+
id: str
|
|
350
|
+
name: str
|
|
351
|
+
|
|
352
|
+
def list_channels() -> ListChannelsResponse:
|
|
370
353
|
"""List Slack channels."""
|
|
371
354
|
...
|
|
372
355
|
|
|
@@ -382,6 +365,8 @@ from tools import save_artifact, load_artifact, list_artifacts
|
|
|
382
365
|
</code-mode>
|
|
383
366
|
~~~
|
|
384
367
|
|
|
368
|
+
Return types come from each tool's `response_json_schema`, or an MCP tool's `outputSchema`; a tool without one returns `Any`. Objects become `TypedDict` classes named after their `$defs` key or `title`, else the property holding them. Identical shapes share one class across a module, defined once at the top of its catalog section; a name clash with another module's class falls back to the tool's or parent's name; each stub file carries the classes its tool uses. An MCP tool's `outputSchema` describes the `structuredContent` field in its result. A saved tool result can also be a `ToolResultArtifact` pointer when it exceeds the size threshold. A tool with exactly one required parameter takes it positionally (`load_artifact("report.csv", version=2)`); every other parameter is keyword-only.
|
|
369
|
+
|
|
385
370
|
Tags are indented; their content is not. The `<tools-package>` body is Python source, where leading whitespace is meaningful. Each installed-package line is `<import name>: <distribution> <version>`; namespace imports supplied by multiple distributions list every provider in deterministic order. Import names and providers are sorted so the block stays byte-stable for prompt caching. `<python-version>` and `<installed-packages>` are omitted entirely — rather than rendered blank — when the sandbox hasn't reported yet or the image has no extra packages, since an empty tag reads as "none exist".
|
|
386
371
|
|
|
387
372
|
With `save_tool_results_as_artifacts` enabled (the default), each non-artifact tool above — e.g. `list_channels` and `send_message` — also carries two optional `artifact_name: str | None = ...` / `artifact_description: str | None = ...` parameters for naming its saved result.
|
|
@@ -391,7 +376,10 @@ With `save_tool_results_as_artifacts` enabled (the default), each non-artifact t
|
|
|
391
376
|
A block over `max_code_mode_metadata_chars` degrades in tiers instead of vanishing. The Python version and package list survive every tier — they're small, and the model cannot discover them any other way.
|
|
392
377
|
|
|
393
378
|
1. **Full** — as above.
|
|
394
|
-
2. **Names only** — signatures and docstrings dropped, import lines kept:
|
|
379
|
+
2. **Names only** — types, signatures and docstrings dropped, import lines kept. `<how-to-use>` gains:
|
|
380
|
+
|
|
381
|
+
> Before calling a function you haven't used, print its stub to see its signature, docstring and the fields of its return type: `/tools/<module>/<fn>.py`, or `/tools/<fn>.py` for a function imported from `tools`. Print every stub you need in one `execute_code` call.
|
|
382
|
+
|
|
395
383
|
|
|
396
384
|
~~~
|
|
397
385
|
<tools-package>
|
|
@@ -401,11 +389,11 @@ A block over `max_code_mode_metadata_chars` degrades in tiers instead of vanishi
|
|
|
401
389
|
</tools-package>
|
|
402
390
|
~~~
|
|
403
391
|
|
|
404
|
-
3. **Pointer** — the catalog is replaced by a
|
|
392
|
+
3. **Pointer** — the catalog is replaced by a note, and this tier is emitted no matter how small the budget. `<how-to-use>` gains the same text, prefixed with "List `/tools/` and its module directories to find the functions available.":
|
|
405
393
|
|
|
406
394
|
~~~
|
|
407
395
|
<tools-package>
|
|
408
|
-
The full catalog is too large to include here.
|
|
396
|
+
The full catalog is too large to include here.
|
|
409
397
|
</tools-package>
|
|
410
398
|
~~~
|
|
411
399
|
|
|
@@ -413,11 +401,12 @@ At the last tier the model navigates the sandbox from Python instead:
|
|
|
413
401
|
|
|
414
402
|
```python
|
|
415
403
|
import pathlib
|
|
416
|
-
print(
|
|
417
|
-
print(open("/tools/slack/send_message.py").read()) # signature + docstring
|
|
404
|
+
print(sorted(pathlib.Path("/tools").rglob("*.py")))
|
|
405
|
+
print(open("/tools/slack/send_message.py").read()) # types, signature + docstring
|
|
406
|
+
print(open("/tools/slack/list_channels.py").read())
|
|
418
407
|
```
|
|
419
408
|
|
|
420
|
-
Text and JSON-like MIME types travel as plain strings in artifact tools; binary content is base64-encoded. `load_artifact` returns `
|
|
409
|
+
Text and JSON-like MIME types travel as plain strings in artifact tools; binary content is base64-encoded. `load_artifact` returns a dictionary with `kind`, `data`, and `mime_type`. Text and JSON use `kind="text"` and keep the string in `data`. Binary artifacts use `kind="bytes"` and store base64 in `data`.
|
|
421
410
|
|
|
422
411
|
## 🛡️ Safety
|
|
423
412
|
|
|
@@ -450,7 +439,7 @@ Named "Unsafe" intentionally: it binds a TCP listener on `0.0.0.0`, communicates
|
|
|
450
439
|
## ⚠️ Limitations
|
|
451
440
|
|
|
452
441
|
- **No credential-requesting tools.** Tools that need ADK to request credentials, confirmations, UI widgets, agent transfer, escalation, or that yield without an immediate response are rejected with a structured error.
|
|
453
|
-
- **State is turn-scoped.** Variables and the working directory persist across `execute_code` calls **within** a turn, but reset between turns.
|
|
442
|
+
- **State is turn-scoped.** Variables and the working directory persist across `execute_code` calls **within** a turn, but reset between turns. Files the code writes and tool results are saved as artifacts; use `load_artifact` to read them in a later turn.
|
|
454
443
|
- **No runtime package installation.** The sandbox ships with the Python Standard Library and the runtime's own dependencies only. Extra packages must be baked into the image at build time.
|
|
455
444
|
|
|
456
445
|
## 🛠️ Development
|
|
@@ -470,9 +459,9 @@ uv run pytest -m docker
|
|
|
470
459
|
|
|
471
460
|
`adk-code-mode` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
|
|
472
461
|
|
|
473
|
-
## 🤝 Join the
|
|
462
|
+
## 🤝 Join the Agenta Community
|
|
474
463
|
|
|
475
|
-
|
|
464
|
+
Agenta is a site to find and share AI agents and open-source community. Join to share your A2A agents, ask questions, stay up-to-date with the latest A2A news, be the first to hear about open-source releases, tutorials, and more!
|
|
476
465
|
|
|
477
|
-
- 🌍 Site: [
|
|
466
|
+
- 🌍 Site: [Agenta](https://buildagenta.com)
|
|
478
467
|
- 🤖 Discord: [Join the Discord](https://discord.gg/674NGXpAjU)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
FROM python:3.13-slim
|
|
2
2
|
|
|
3
|
-
LABEL org.opencontainers.image.source="https://github.com/
|
|
3
|
+
LABEL org.opencontainers.image.source="https://github.com/buildagenta/adk-code-mode"
|
|
4
4
|
LABEL org.opencontainers.image.description="Sandbox base image for ADK Code Mode"
|
|
5
5
|
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
|
6
6
|
|