google / google/adk-python

Add exec-sandbox code executor (self-hosted QEMU microVMs)

Aperta
#4,643 1 commento 0 reazioni 2 assegnatari Rivendicata da @xuanyang15 Vedi su GitHub
needs review tools
Lingua principale
Python
Stelle
21.5k
Fork
4k
Merge medio
1g 14h
PR unite (30g)
37

Descrizione

# Add exec-sandbox code executor (self-hosted QEMU microVMs)

## Summary

Proposing [exec-sandbox](https://github.com/dualeai/exec-sandbox) as a new `BaseCodeExecutor` backend. It runs code in ephemeral QEMU microVMs with hardware-level isolation (KVM on Linux, HVF on macOS) — self-hosted, no cloud account needed.

## Why

- **Self-hosted** — ContainerCodeExecutor needs Docker, GkeCodeExecutor needs GKE, VertexAiCodeExecutor needs Vertex. exec-sandbox runs on bare metal with just QEMU. Data never leaves the machine — relevant for customer data privacy, regulated environments, and cheaper at scale.
- **macOS + Linux** — HVF on macOS, KVM on Linux. Same codebase for dev and prod.
- **Fast** — ~1-2ms from warm pool, ~200ms from memory snapshots.
- **Stronger isolation than containers** — Hardware-level VM boundary vs Docker process isolation.
- **Apache-2.0**

## How it maps

exec-sandbox is a Python library with an async API. A `BaseCodeExecutor` subclass bridges async → sync, following the same pattern as ContainerCodeExecutor:

```python
import asyncio
from exec_sandbox import Scheduler

class ExecSandboxCodeExecutor(BaseCodeExecutor):
stateful: bool = True

def __init__(self, **kwargs):
super().__init__(**kwargs)
self._loop = asyncio.new_event_loop()
self._scheduler = self._loop.run_until_complete(Scheduler().__aenter__())
self._sessions: dict[str, Session] = {}

def execute_code(self, invocation_context, code_execution_input):
# Reuse session for stateful execution
eid = code_execution_input.execution_id
if eid and eid in self._sessions:
session = self._sessions[eid]
else:
session = self._loop.run_until_complete(
self._scheduler.session(language="python")
)
if eid:
self._sessions[eid] = session

result = self._loop.run_until_complete(session.exec(code_execution_input.code))
return CodeExecutionResult(
stdout=result.stdout,
stderr=result.stderr,
)
```

Usage:

```python
agent = LlmAgent(
code_executor=ExecSandboxCodeExecutor(),
...
)
```

## Open questions

- **Async/sync bridge** — exec-sandbox is fully async. The sketch uses a dedicated event loop. A background-thread loop would be safer if called from an existing async context.
- **File I/O** — `CodeExecutionInput.input_files` and `CodeExecutionResult.output_files` could use exec-sandbox's native `write_file`/`read_file` APIs instead of writing to a shared volume.
- **Shipping** — External package (`exec-sandbox[adk]` extra) vs upstream in `code_executors/` following the GkeCodeExecutor pattern from PR #1629.

## Links

- [Repo](https://github.com/dualeai/exec-sandbox) · [PyPI](https://pypi.org/project/exec-sandbox/)
- Reference: `gke_code_executor.py` in `code_executors/` (same integration pattern)

Happy to submit a PR if there's interest.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.