google / google/adk-python

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

Đang mở
#4,643 1 bình luận 0 reaction 2 người được giao Được @xuanyang15 nhận Xem trên GitHub
needs review tools
Ngôn ngữ chính
Python
Star
21.5k
Fork
4k
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
37

Mô tả

# 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.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.