Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ This directory contains examples of how to use the Agent Sandbox. Each subdirect
- [**python-runtime-sandbox**](./python-runtime-sandbox): An example of a Python runtime sandbox.
- [**sandbox-ksa**](./sandbox-ksa): Examples of a sandbox with a service account, namespace, and a basic sandbox.
- [**vscode-sandbox**](./vscode-sandbox): An example of running VSCode in a sandbox.
- [**aio-sandbox**](./aio-sandbox): An example of running aio-sandbox using agent-sandbox.
64 changes: 64 additions & 0 deletions examples/aio-sandbox/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

# AIO Sandbox Example

This example demonstrates how to create and access an [AIO Sandbox](https://github.com/agent-infra/sandbox) via Agent-Sandbox.

## Create an AIO Sandbox

Apply the sandbox manifest with AIO Sandbox runtime.

```sh
kubectl apply -k base
# sandbox.agents.x-k8s.io/aio-sandbox-example created
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instructions assume that the agentic-sandbox-client is already installed. It would be beneficial to add a prerequisite step that instructs users on how to install it, e.g., pip install agentic-sandbox-client.


They can then check the status of the applied resource.
Verify sandbox and pod are running:

```sh
# wait until the sandbox is ready
kubectl wait --for=condition=Ready sandbox aio-sandbox-example

kubectl get sandbox
# NAME AGE
# aio-sandbox-example 41s
kubectl get pod aio-sandbox-example
# NAME READY STATUS RESTARTS AGE
# aio-sandbox-example 1/1 Running 0 49s
```

## Accessing the AIO Sandbox Server

Port forward the aio-sandbox server port.

```sh
kubectl port-forward --address 0.0.0.0 pod/aio-sandbox-example 8080
```

Connect to the aio-sandbox on a browser via http://localhost:8080 or <machine-dns>:8080


## Access the AIO Sandbox via Python SDK

```sh
# set up a virtual environment if needed
python3 -m venv venv
source venv/bin/activate

# install the agent-sandbox package
pip install agent-sandbox
```

Run the basic python example:
```sh
python3 main.py
```

Run the site to markdown example:

```sh
# install the playwright package
pip install playwright

python3 site_to_markdown.py
```
20 changes: 20 additions & 0 deletions examples/aio-sandbox/base/aio-sandbox.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: agents.x-k8s.io/v1alpha1
kind: Sandbox
metadata:
name: aio-sandbox-example
spec:
podTemplate:
metadata:
labels:
sandbox: aio-sandbox-example
spec:
containers:
- name: aio-sandbox
image: ghcr.io/agent-infra/sandbox:latest
ports:
- containerPort: 8080
resources:
limits:
memory: "2Gi"
cpu: "1000m"

5 changes: 5 additions & 0 deletions examples/aio-sandbox/base/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- aio-sandbox.yaml
16 changes: 16 additions & 0 deletions examples/aio-sandbox/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from agent_sandbox import Sandbox

# Initialize client
client = Sandbox(base_url="http://localhost:8080")
home_dir = client.sandbox.get_context().home_dir

# Execute shell commands
result = client.shell.exec_command(command="ls -la")
print(result.data.output)

# File operations
content = client.file.read_file(file=f"{home_dir}/.bashrc")
print(content.data.content)

# Browser automation
screenshot = client.browser.screenshot()
40 changes: 40 additions & 0 deletions examples/aio-sandbox/site_to_markdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import asyncio
import base64
from playwright.async_api import async_playwright
from agent_sandbox import Sandbox

async def site_to_markdown():
# Initialize sandbox client
c = Sandbox(base_url="http://localhost:8080")
home_dir = c.sandbox.get_context().home_dir

# Browser: Automation to download HTML
async with async_playwright() as p:
browser_info = c.browser.get_info().data
page = await (await p.chromium.connect_over_cdp(browser_info.cdp_url)).new_page()
await page.goto("https://example.com", wait_until="networkidle")
html = await page.content()
screenshot_b64 = base64.b64encode(await page.screenshot()).decode('utf-8')

# Jupyter: Convert HTML to markdown in sandbox
c.jupyter.execute_code(code=f"""
from markdownify import markdownify
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output filename site.md is hardcoded. To make the script more flexible and reusable, consider making this configurable via a command-line argument.

html = '''{html}'''
screenshot_b64 = "{screenshot_b64}"
md = f"{{markdownify(html)}}\\n\\n![Screenshot](data:image/png;base64,{{screenshot_b64}})"
with open('{home_dir}/site.md', 'w') as f:
f.write(md)
print("Done!")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The browser context is not guaranteed to be closed if an error occurs within the with block for Playwright. To ensure resources are always released, it's better to wrap the page interaction logic in a try...finally block where context.close() is explicitly called.

""")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Playwright browser launch call (p.chromium.launch()) could potentially hang if the browser fails to start. It's good practice to include a timeout here to prevent the script from getting stuck.


# Shell: List files in sandbox
list_result = c.shell.exec_command(command=f"ls -lh {home_dir}")
print(f"Files in sandbox: {list_result.data.output}")

# File: Read the generated markdown
return c.file.read_file(file=f"{home_dir}/site.md").data.content

if __name__ == "__main__":
result = asyncio.run(site_to_markdown())
print(f"Markdown saved successfully!")