Uh oh!
There was an error while loading. Please reload this page.
Add SandboxToolset for sandboxed agent shell and file access - #68847
Conversation
Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contributors' Guide
|
kaxil
commented
Jun 24, 2026
Converted to draft to ensure, this is discussed on the mailing list first. My first main concern (without looking into much details) is how would this integrate with Common AI Provider and why should it be separate provider instead of part of |
Agrees with @kaxil - we also need to know that we have real person behind who is comitted to maintain it - not only drop AI generatad code, so discussion on devlist is a minimum, ideally some good discussion about why this is a good idea - and explaining (in human words) some rationale behind it, and choice of the sandbox "providers" (which cannot be named providers due to obvious conflict) - ideally you should present your idea, how it is already used and what actual real-use problems it solves at our dev call. |
zozo123
commented
Jun 25, 2026
Thanks @kaxil@potiuk — pivoted per your feedback. It's no longer a separate provider: it's now a Not single-vendor: the same per-session-microVM primitive now exists in AWS Lambda microVMs (Firecracker, shipped 2026-06-22 for "user or AI-generated code"), Daytona, E2B, Modal, and islo. The local backend needs no credentials. On maintenance: I'll own it — I'm at Incredibuild and islo (islo.dev) is our product, so there's a committed maintainer and real usage behind it, not a drive-by AI PR. The reference backend I commit to is islo. It already works end to end: a real agent's |
You will need to elaborate on that. Since you are new to the community we need to make sure there is a long term promise/ownership. Check out guidelines for adding new providers |
zozo123
commented
Jun 29, 2026
Thanks @eladkal, that's a fair bar and I appreciate you spelling it out. Two named maintainers at Incredibuild will own this long term: myself (@zozo123, yossi.eliaz@incredibuild.com) and Yuval Raz (yuval.r@incredibuild.com). support@incredibuild.com is our team alias, also committed and monitored by the islo team for issues and escalations. Incredibuild builds islo (islo.dev), a commercial product, so we have a direct reason to keep this alive. We'll land the first commit and maintain both the The backend interface is pluggable so any vendor can own its own. We plan to invite E2B, AWS (Lambda microVMs), Daytona, and Tensorlake; whether they pick it up is on them. We're not asking the community to carry single-vendor code. We'll answer issues and PRs, and meet the incubation and governance commitments in ACCEPTING_PROVIDERS. One scope note: this is a I'm new here, so who's the right committer to approach as a sponsor? I'll start the |
eladkal
commented
Jun 30, 2026
Should there be a need for this new provider I am happy to be the sponsor but lets take it one step at a time. The item in #68847 (comment) must be answered first. |
Uh oh!
There was an error while loading. Please reload this page.
79b43fc to
196317bComparezozo123
commented
Aug 10, 2026
@kaxil Done, scope is Drafted-by: Claude Code (Opus 5); reviewed by @zozo123 before posting |
gopidesupavan
commented
Aug 10, 2026
@zozo123 can you point me the github page for islo? i see the sdk is auto generated as per https://github.com/islo-labs/python-sdk i wanted to understand this more |
https://docs.islo.dev/getting-started/quick-start Let me know if this addresses the question. |
Give common.ai agents a run_code tool that executes model-generated Python off the Airflow worker, in a disposable per-run microVM, closing the isolation gap in code mode (whose run_code runs in-process on the worker with full credentials). A vendor-neutral SandboxBackend contract ships two backends: Docker Sandboxes via the sbx CLI (local microVM) and islo (hosted microVM). Airflow injects none of its context, connections, or worker environment into the sandbox; the islo backend keeps outbound network off by default.
Give each agent run its own sandbox so concurrent runs cannot share or tear down each other's; stream sandbox command output with a hard cap so generated code cannot exhaust worker memory; name the tool run_python_in_sandbox so it coexists with the run_code meta-tool that Monty code_mode reserves; report a run as timed out only on GNU timeout's unambiguous exit 124; clean up an orphaned microVM and workspace when provisioning fails; cap islo output like the sbx backend and keep timeout-driven teardown best-effort; and state the islo timeout honestly - it is enforced by the backend's poll deadline, not by the islo API.
The toolsets page is not a supported provider how-to guide path, which prevents static provider validation from succeeding.
Review feedback: GNU timeout exits 137 instead of 124 when generated code ignores SIGTERM and --kill-after escalates, so a stubborn timeout was reported as timed_out=False and indistinguishable from an OOM kill. Exit 137 now counts as a timeout when the call also outlived its budget. The passthrough args validator let a tool call without a string "code" reach call_tool and fail the task with KeyError; a real schema validator now turns malformed calls into retryable validation errors so max_retries works as intended.
The provider.yaml completeness check requires every module under toolsets/ to be listed; the new toolset registry category (apache#70122) landed after this branch was created.
Verify the code-execution boundary with a deterministic agent run and clarify that boundary size alone does not define security.
196317b to
e9e1899Compare0cccfef to
553829fCompare…ntract The toolset exposed one run_python_in_sandbox tool. pydantic-ai's own sandbox capabilities, and the vendors writing adapters for them, have converged on run_command plus read_file, write_file and list_directory, so an agent could run code here but never get a result out, and a vendor had two shapes to implement instead of one. The backend contract now names its four operation methods after those four tools, and create() takes a SandboxSpec describing environment and network policy. A backend that cannot enforce a field it was given raises rather than provisioning something weaker than the Dag author asked for, so a spec can no longer imply a restriction that is not in force. run_command carries code_arg_name metadata. Without it, code mode folded the sandbox tool into run_code and the model wrote orchestration that ran in the worker process and passed a second program to the sandbox as a string literal, which is what the toolset exists to avoid.
553829f to
f75a3a2CompareUh oh!
There was an error while loading. Please reload this page.
Summary
Adds
SandboxToolsetto the Common AI provider: an agent gets a shell and a filesystem inside a disposable sandbox that runs off the Airflow worker process.run_command&&and globs work. A non-zero exit is returned as output, not raised, so the model readsstderrand corrects itself.read_fileoffset, so the model can page through a long file.write_filelist_directory/.These are the same four names and shapes pydantic-ai's own sandbox capabilities use, so a model that has seen one already knows this one, and a vendor with an adapter for one is close to having written this one.
One backend ships:
SbxSandboxBackend, driving Docker Sandboxes through thesbxCLI. It needs no Python dependency, so this PR adds no runtime requirement and leavesuv.lockuntouched.Which boundary this is
"Sandboxed" means different things at different layers, and picking the wrong layer is the common way to end up with less protection than you expected.
KubernetesExecutordoesThis is the first row, and the docs say so plainly. Airflow puts none of its context, connections, variables or worker environment into the sandbox. It does not contain the agent: the agent loop and every other toolset on the same agent still run in the worker with the worker's credentials, so an agent holding
SandboxToolsetalongside a toolset that can reach connections has a contained code tool sitting next to an uncontained credential path.Design decisions
Four tools rather than one. An earlier revision exposed a single
run_python_in_sandbox, which let an agent run code but never get a result back out. Files are how work leaves a sandbox, so the file tools are not a convenience.A backend contract whose method names match the tools.
SandboxBackendiscreate/run_command/read_file/write_file/list_directory/destroy. Four of the six are named after the tool they serve, so the mapping from a model-facing tool to the call behind it is literal.A spec a backend must honour or refuse.
SandboxSpeccarries environment and network policy, and defaults to no environment and no egress. A backend that cannot enforce a field it was given raises instead of quietly provisioning something weaker, so a DAG author can never believe a restriction is in force when it is not.SbxSandboxBackendrefuses a per-sandbox egress allowlist outright, because Docker Sandboxes governs egress with a host-level policy, and refusesblock_network=Trueunless the Deployment Manager declares that policy throughhost_network_policy.A toolset, not a capability. pydantic-ai models its own sandboxes as capabilities, but Airflow already has a composition unit in
AgentOperator(toolsets=...), and durable execution only wraps toolsets it can reach. A capability that builds its own tools internally gets no replay caching, so shipping this as a capability would silently breakdurable=True.run_commandis marked as a code surface. ItsToolDefinitioncarriescode_arg_namemetadata. Without it, code mode folds the tool intorun_codeand the model ends up writing orchestration that runs in the worker process and passes a second program to the sandbox as a string literal, which is the opposite of what the toolset is for. With it,run_commandstays a normal tool besiderun_codewhile the three file tools fold in, where they are more useful as callables.Usage
Two sandboxes on one agent need
tool_prefix, since tool names must be unique:Tradeoffs and limitations
The
sbxbackend is for local development, not production. Docker Sandboxes is built for running coding agents against a checkout on your own machine:sbx createtakes an agent name and bind-mounts host paths, and its stock network profile allows "typical development traffic". A production worker would need the binary on the host, an authenticated Docker account, a one-timesbx policy init, and on Linux, KVM or nested virtualisation, which an unprivileged container cannot provide. The docs lead with this. Verified end to end againstsbx0.38.0, covering the file round trip, environment injection, non-zero exits, output bounding, timeout enforcement and teardown.No hosted backend ships yet, so there is no production story on Kubernetes until one lands.
SandboxBackendis the extension point; a vendor adapter is roughly the six methods above.sbxreclaims nothing automatically. There is no server-side TTL, so a worker killed outright leaves the microVM and its workspace directory behind. Sandboxes are namedairflow-sandbox-*so an operator can find and remove them.SandboxSpec.allow_egress_tois defined but unenforceable by the only backend here. It is part of the vendor-neutral contract;SbxSandboxBackendraises rather than accepting it.Durable execution and HITL regeneration are not supported. The sandbox is destroyed when a run ends, so a replayed
write_fileresult would describe a file in a sandbox that no longer exists.Scope
This is the toolset and its contract only. The islo backend that appeared in earlier revisions is dropped from this PR so the abstraction can be reviewed on its own merits and so the diff carries no vendor SDK, extra, or
uv.lockchange. It is expected as a follow-up owned by the islo maintainers.Not in scope: moving
AgentOperator, the LLM calls, or the Airflow task off the worker; releasing the worker slot while sandbox code runs; and any executor SPI. Those are different boundaries, tracked separately.Related work
SandboxExecutortracker.