Skip to content

Commit 52ea994

Browse files
Antigravity Teamcopybara-github
authored andcommitted
No public description
PiperOrigin-RevId: 975094670 Change-Id: I4bbd1fb2b75fe40bd23b77568dbd2e82ec09e0dc
1 parent 708ed5b commit 52ea994

5 files changed

Lines changed: 193 additions & 3 deletions

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Example demonstrating OS-level sandboxing of terminal commands.
16+
17+
By default the agent's ``run_command`` tool executes shell commands directly on
18+
the host. When you opt in with ``RunCommandConfig(enable_sandbox=True)``,
19+
``run_command`` is instead executed inside the OS-level sandbox, which
20+
confines what the command can touch.
21+
22+
``run_command`` must be allowed for the sandbox to matter, so this example pairs
23+
the flag with ``policy.allow_all()``.
24+
25+
.. warning::
26+
27+
``allow_all()`` grants unrestricted tool access, including shell execution.
28+
The sandbox is the safety boundary here; only run this in a trusted
29+
environment.
30+
31+
The demo asks the agent to write a file *outside* its workspace (into
32+
``$HOME``). With the sandbox enabled the write is blocked; with it disabled the
33+
same command would succeed.
34+
35+
To run:
36+
python sandboxing.py
37+
38+
Criteria for correct script performance:
39+
1. The script exits cleanly with return code 0 (no unhandled exceptions).
40+
2. The agent produces a non-empty text response.
41+
3. With the sandbox enabled, the response reports that the out-of-workspace
42+
write was blocked, i.e. the file was NOT created outside the workspace.
43+
"""
44+
45+
import asyncio
46+
import os
47+
48+
from google.antigravity import Agent
49+
from google.antigravity import CapabilitiesConfig
50+
from google.antigravity import LocalAgentConfig
51+
from google.antigravity.hooks import policy
52+
from google.antigravity.types import RunCommandConfig
53+
54+
# A path deliberately *outside* the agent's workspace. A normal (unsandboxed)
55+
# process owned by the user can write here; the exebox sandbox denies it.
56+
_ESCAPE_PROBE_PATH = os.path.join(
57+
os.path.expanduser("~"), "agy_sandbox_escape_probe.txt"
58+
)
59+
60+
61+
async def run_probe(*, enable_sandbox: bool) -> str:
62+
"""Runs the escape-probe command under an agent with the given sandbox flag.
63+
64+
Args:
65+
enable_sandbox: Whether to execute run_command inside the OS sandbox.
66+
67+
Returns:
68+
The agent's final text response.
69+
"""
70+
config = LocalAgentConfig(
71+
capabilities=CapabilitiesConfig(
72+
run_command_config=RunCommandConfig(enable_sandbox=enable_sandbox),
73+
),
74+
# allow_all() is required so run_command executes without confirmation;
75+
# the sandbox (not a confirmation prompt) is what contains it.
76+
policies=[policy.allow_all()],
77+
)
78+
79+
# A concrete command that writes to a throwaway path outside the sandbox
80+
# boundary, so the block is attributable to the sandbox rather than to the
81+
# model declining on its own.
82+
prompt = (
83+
"Run exactly this shell command and then tell me whether it succeeded, "
84+
"quoting any error output verbatim:\n"
85+
f" echo 'sandbox escape attempt' > '{_ESCAPE_PROBE_PATH}'"
86+
)
87+
88+
async with Agent(config) as agent:
89+
response = await agent.chat(prompt)
90+
return await response.text()
91+
92+
93+
async def main() -> None:
94+
# Best-effort clean slate so a leftover file from a prior unsandboxed run
95+
# doesn't confuse the result.
96+
try:
97+
os.remove(_ESCAPE_PROBE_PATH)
98+
except FileNotFoundError:
99+
pass
100+
101+
print("=== Sandbox ENABLED: out-of-workspace write should be blocked ===")
102+
print(f" User: attempt to write to {_ESCAPE_PROBE_PATH}")
103+
sandboxed_response = await run_probe(enable_sandbox=True)
104+
print(f" Agent: {sandboxed_response}")
105+
106+
escaped = os.path.exists(_ESCAPE_PROBE_PATH)
107+
print()
108+
if escaped:
109+
# enable_sandbox has no effect where the exebox sandbox is unavailable, and
110+
# the SDK neither warns nor raises in that case -- so surface it loudly here
111+
# rather than letting the write pass silently.
112+
print(
113+
" WARNING: file WAS created -> the write was NOT sandboxed. "
114+
"enable_sandbox has no effect where the exebox sandbox is unavailable. "
115+
"Verify the sandbox is available in your environment before relying "
116+
"on it."
117+
)
118+
os.remove(_ESCAPE_PROBE_PATH)
119+
else:
120+
print(
121+
" RESULT: file was NOT created -> the OS sandbox denied the "
122+
"out-of-workspace write, as expected."
123+
)
124+
125+
# To see the contrasting baseline (the same command succeeding without the
126+
# sandbox), flip the flag -- kept commented out so the example is safe by
127+
# default:
128+
#
129+
# baseline = await run_probe(enable_sandbox=False)
130+
# print(baseline) # the file is created under $HOME
131+
# os.remove(_ESCAPE_PROBE_PATH)
132+
133+
134+
if __name__ == "__main__":
135+
asyncio.run(main())

‎skills/google-antigravity-sdk/SKILL.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ relevant information.
5757
- If the user needs to extend an agent's capabilities by integrating Model
5858
Context Protocol (MCP) servers, or configure tool permissions for the agent,
5959
read `references/mcp_integration.md`.
60-
- If the user needs to define safety policies, resolve execution order, or
61-
restrict agent actions using predicates, read
62-
`references/safety_policies.md`.
60+
- If the user needs to define safety policies, resolve execution order,
61+
restrict agent actions using predicates, or run terminal commands inside an
62+
OS-level sandbox, read `references/safety_policies.md`.
6363
- If the user needs to debug failed agents, stream logs, or implement error
6464
recovery using hooks to make agents robust, read
6565
`references/error_handling.md`.

‎skills/google-antigravity-sdk/references/agent_configuration.md‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,26 @@ config = LocalAgentConfig(
280280
)
281281
```
282282

283+
### `run_command` Configuration (`RunCommandConfig`)
284+
285+
Configure the built-in `run_command` tool via `RunCommandConfig`, including
286+
running commands inside an OS-level sandbox with `enable_sandbox`:
287+
288+
```python
289+
from google.antigravity import Agent, LocalAgentConfig, types
290+
from google.antigravity.hooks import policy
291+
292+
config = LocalAgentConfig(
293+
capabilities=types.CapabilitiesConfig(
294+
run_command_config=types.RunCommandConfig(enable_sandbox=True),
295+
),
296+
policies=[policy.allow_all()],
297+
)
298+
```
299+
300+
For details and caveats, see
301+
[safety_policies.md](safety_policies.md#defense-in-depth-os-level-command-sandboxing).
302+
283303
### Session Budget Controls & Stop Reasons
284304

285305
You can configure session operational limits (`max_model_calls`, `max_tool_calls`) and proactive token budget controls (`max_input_tokens`, `max_output_tokens`, `max_total_tokens`) using `BudgetConfig`:
@@ -301,6 +321,7 @@ For a full guide and multi-turn stop reason handling examples, see [budget_limit
301321
### Context Compaction & Token Limits (`compaction_config`)
302322

303323
Antigravity manages conversation context using a two-stage sliding-window pipeline:
324+
304325
1. **Background Checkpointing**: A background model pre-computes cumulative trajectory summaries (checkpoints) at regular token intervals (`checkpoint_interval_tokens`). Checkpoint generation runs asynchronously and silently in parallel without modifying or truncating the active prompt.
305326
2. **Prompt Eviction (Compaction)**: When cumulative prompt tokens reach the context ceiling (`max_context_tokens`), the prompt snaps back to the latest completed checkpoint. Earlier checkpoints and older turns preceding the latest checkpoint are evicted from the prompt, while recent turns between the latest checkpoint and the current turn are preserved verbatim with full fidelity.
306327

‎skills/google-antigravity-sdk/references/built_in_tools.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,9 @@ descriptions.
4444

4545
> [!NOTE] Some production backends may require additional environment or
4646
> filesystem configuration to support these tools.
47+
48+
> [!NOTE] `run_command` can be hardened by executing shell commands inside an
49+
> OS-level sandbox. Set `enable_sandbox=True` on `RunCommandConfig` (nested
50+
> under `CapabilitiesConfig.run_command_config`). See
51+
> [Safety Policies](safety_policies.md#defense-in-depth-os-level-command-sandboxing)
52+
> for details and caveats.

‎skills/google-antigravity-sdk/references/safety_policies.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,31 @@ config = LocalAgentConfig(
214214
policies=[policy.allow_all()],
215215
)
216216
```
217+
218+
## Defense in Depth: OS-Level Command Sandboxing
219+
220+
Policies decide **whether** `run_command` runs; the OS sandbox confines **what a
221+
command can do once it runs**. The two are complementary — a permissive policy
222+
(e.g. `allow_all()`) can be paired with the sandbox so shell commands still
223+
cannot touch anything outside the agent's workspace.
224+
225+
Enable it with `enable_sandbox` on `RunCommandConfig`:
226+
227+
```python
228+
from google.antigravity import Agent, LocalAgentConfig, types
229+
from google.antigravity.hooks import policy
230+
231+
config = LocalAgentConfig(
232+
capabilities=types.CapabilitiesConfig(
233+
run_command_config=types.RunCommandConfig(enable_sandbox=True),
234+
),
235+
# run_command must be allowed for the sandbox to apply.
236+
policies=[policy.allow_all()],
237+
)
238+
```
239+
240+
> [!IMPORTANT] `enable_sandbox` has no effect on platforms/environments where
241+
> the sandbox is unavailable, and the SDK does not warn or raise in that case.
242+
> Do not rely on it as your only safety boundary — combine it with policies
243+
> (`deny` / `ask_user`) and verify the sandbox is available in your target
244+
> environment.

0 commit comments

Comments
 (0)