From dbb18e74fc2603f21a5f0008d73e4eb0b97a42d2 Mon Sep 17 00:00:00 2001 From: rmanjunath18 <242545101+rmanjunath18@users.noreply.github.com> Date: Mon, 2 Nov 2026 12:52:37 +0530 Subject: [PATCH] docs(examples): add auto-resume examples for sandboxes and agents auto_resume.py pauses a sandbox, then runs a command against it without calling resume(), and reports whether the sandbox woke by itself. agent_auto_resume.py does the same for an agent, through its backing sandbox, and calls agent.resume() in the fallback. Both fall back to an explicit resume() only on a 429 while still Paused, and replay the read-only command at most once. Every 429 on the exec path is sent before the command runs; that is how the backend behaves today, not an API guarantee. A 503 or any other error is not replayed. The marker read passes timeout_ms=120000, matching the JS port, and both examples exit non-zero when deleting the sandbox or agent fails. examples/README.md gains a step-by-step section with each example's run command and expected output, and its table and notes now match the code. minimal_agent's banner shows the configured model, and repo_analyzer defaults to the repository's current URL. Both auto-resume examples are listed in examples/README.md and docs/example-coverage.md. --- docs/example-coverage.md | 9 +- examples/README.md | 254 +++++++++++++++++++- examples/agent_auto_resume.py | 120 +++++++++ examples/agent_patterns/minimal_agent.py | 4 +- examples/auto_resume.py | 107 +++++++++ examples/workflow_examples/README.md | 2 +- examples/workflow_examples/repo_analyzer.py | 4 +- 7 files changed, 483 insertions(+), 17 deletions(-) create mode 100644 examples/agent_auto_resume.py create mode 100644 examples/auto_resume.py diff --git a/docs/example-coverage.md b/docs/example-coverage.md index ac98933..3a67c21 100644 --- a/docs/example-coverage.md +++ b/docs/example-coverage.md @@ -57,11 +57,11 @@ examples themselves, see [`examples/README.md`](../examples/README.md). | `client.agent_templates.list` | `create_agent.py` | `page = client.agent_templates.list()` | | `client.agent_templates.get` | — | `tpl = client.agent_templates.get(template_id)` | | `agent.wait_until_ready` | `create_agent.py` | `agent.wait_until_ready(timeout_ms=120_000)` | -| `agent.refresh` | — | `agent.refresh()` | +| `agent.refresh` | `agent_auto_resume.py` | `agent.refresh()` | | `agent.sandbox` | `create_agent.py` | `sandbox = agent.sandbox()` | | `agent.update` | `create_agent.py` | `agent.update({"resources": {"cpu": 2, "memory_gb": 4}})` | | `agent.pause` / `agent.delete` | `create_agent.py` | `agent.pause(); agent.delete()` | -| `agent.resume` | — | `agent.resume()` — not shown in `create_agent.py`; see [getting-started.md](./getting-started.md#create-an-agent) | +| `agent.resume` | `agent_auto_resume.py` | `agent.resume()` — then `wait_until_ready()` | | `agent.to_json` | — | `agent.to_json()` | | `client.raw.request` | `raw_request.py` | `data = client.raw.request("GET", path, query={...})` | | `sandbox.wait_until_ready` | tier-1 (except `raw_request.py`), `processes.py`, `process_pool.py`, `agent_patterns/*`, `workflow_examples/*` | `sandbox.wait_until_ready(timeout_ms=120_000)` — after `connect_url` is set in process examples | @@ -89,7 +89,8 @@ examples themselves, see [`examples/README.md`](../examples/README.md). | `sandbox.files.upload` | — | `sandbox.files.upload("big.bin", data, chunk_size=512 << 10)` — `write()` uses it above 1 MiB | | `sandbox.files.download_file` | `upload_download.py` | `sandbox.files.download_file("payload.bin", copy)` → `{"bytes_written": n}` | | `sandbox.metrics` | `sandbox_lifecycle.py`, `sandbox_metrics.py` | `metrics = sandbox.metrics()` | -| `sandbox.pause` | `sandbox_lifecycle.py` | `sandbox.pause()` | +| `sandbox.pause` | `sandbox_lifecycle.py`, `auto_resume.py` | `sandbox.pause()` | +| `sandbox.resume` | `auto_resume.py` | `sandbox.resume()` — then `wait_until_ready()` | | `sandbox.delete` | all examples that create sandboxes | `sandbox.delete()` / `await sandbox.delete()` | | `sandbox.to_json` | `sandbox_lifecycle_controller.py` | `sandbox.to_json()` | | `sandbox.id` / `.phase` / `.connect_url` | tier-1, `processes.py`, `process_pool.py`, `sandbox_lifecycle_controller.py`, `agent_patterns/utils/sandbox_tool.py`, `workflow_examples/*` | `print(sandbox.phase, sandbox.connect_url)` — polled until `connect_url` in process examples | @@ -103,6 +104,8 @@ examples themselves, see [`examples/README.md`](../examples/README.md). | Templates list & create | `examples/templates_list.py` | List templates, get by id, create sandbox, wait, delete | | Agent lifecycle | `examples/create_agent.py` | List agent templates, create agent, wait, sandbox exec, update, pause, delete | | Sandbox lifecycle | `examples/sandbox_lifecycle.py` | Create → wait → metrics → pause → delete | +| Auto-resume | `examples/auto_resume.py` | Create → pause → `exec` with no `resume()` → explicit `resume()` only on 429 while Paused → delete | +| Agent auto-resume | `examples/agent_auto_resume.py` | Create agent → pause → sandbox `exec` with no `resume()` → explicit `agent.resume()` only on 429 while Paused → delete | | Sandbox in-place update | `examples/sandbox_update.py` | Create → wait → resize → re-scope egress → verify → delete | | Sandbox labels | `examples/sandbox_labels.py` | Create two labelled sandboxes → list by one label → narrow by two → delete | | Crash reporting | `examples/last_crash.py` | Create → mark file → force OOM → poll `last_crash` → check `storage_reset` → delete | diff --git a/examples/README.md b/examples/README.md index 48b6acd..7c0c843 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,7 +1,7 @@ # Examples -Runnable scripts for the NeevCloud SDK for Python (`neevai`). Each one creates real -sandboxes and cleans them up when it finishes. +Runnable scripts for the NeevCloud SDK for Python (`neevai`). Most create real +sandboxes or agents and clean them up when they finish. ## Contents @@ -10,6 +10,7 @@ sandboxes and cleans them up when it finishes. - [Agents](#agents) - [Agent tools](#agent-tools) - [Workflows](#workflows) +- [Step-by-step: run every example](#step-by-step-run-every-example) - [Environment variables](#environment-variables) - [Notes](#notes) @@ -32,7 +33,12 @@ Run any example from the repository root: uv run python examples/