Python SDK Skill
Create a python-sdk/SKILL.md file with this content.
---name: python-sdkdescription: Build with the Runta Python SDK. Use when Codex needs to write Python code that creates, lists, inspects, resizes, pauses, resumes, stops, boots, deletes, or restores Runta runtimes; executes commands; reads, writes, uploads, or downloads files; configures egress; manages secrets and secret stubs; creates checkpoints; or handles Runta Python SDK errors.---
# Runta Python SDK
## Operating Rules
Use this skill for Python projects, scripts, notebooks, async services, and user requests that explicitly ask for Python. Match the repo's package manager and async style.
Use `AsyncRunta` for async apps and `Runta` for sync scripts. Prefer context managers so HTTP resources close cleanly.
Never hardcode real tokens. The SDK reads `RUNTA_TOKEN` from the environment:
```bashexport RUNTA_TOKEN=rt...```
Use Python names and result fields. Do not mix in TypeScript camelCase:
| Concept | Python || --- | --- || Package | `runta-sdk` || Client | `Runta`, `AsyncRunta` || Create memory | `memory_mib` || Idle timeout | `idle_suspend_after_secs` || Cached info | `cached_info` || stdout text | `stdout_text` || stderr text | `stderr_text` || Egress policy fields | `allowed_hosts`, `denied_hosts` |
## Install
```bashpip install runta-sdk```
When developing the Python SDK itself from source:
```bashuv pip install -e .```
## Client Patterns
Async:
```pythonimport asynciofrom runta import AsyncRunta
async def main(): async with AsyncRunta() as runta: runtime = await runta.runtimes.create( "demo", vcpus=2, memory_mib=2048, idle_suspend_after_secs=300, ) result = await runtime.exec(["sh", "-lc", "pwd && python3 --version"], timeout=30) print(result.exit_code) print(result.stdout_text) await runtime.delete()
asyncio.run(main())```
Sync:
```pythonfrom runta import Runta
with Runta() as runta: runtime = runta.runtimes.create("demo", vcpus=2, memory_mib=2048) result = runtime.exec("echo hello world") print(result.stdout_text) runtime.delete()```
Common runtime interfaces:
```pythonruntimes = runta.runtimes.list(status=["running", "paused"])runtime = runta.runtimes.get("<runtime_id_or_name>")runtime.start()runtime.pause()runtime.resume()runtime.stop()runtime.resize_memory(4096)runtime.refresh_info()runtime.delete()```
## Commands
Buffered commands accept a shell string or argv list:
```pythonresult = runtime.exec( ["sh", "-lc", "cat input.txt && echo $APP_ENV"], cwd="/workspace", env={"APP_ENV": "dev"}, stdin="hello\n", timeout=30, max_output_bytes=1024 * 1024,)print(result.exit_code)print(result.stdout_text)print(result.stderr_text)```
Use `runtime.exec_detached(command, ...)` when the SDK process should start a command and await or poll later.
```pythontask = runtime.exec_detached("sleep 5 && echo done")print(task.id)print(task.wait().stdout_text)```
## Files
```pythonruntime.files.write("/tmp/message.txt", "hello")print(runtime.files.read("/tmp/message.txt").decode())runtime.files.upload("local-file.txt", "/tmp/local-file.txt")runtime.files.download("/tmp/local-file.txt", "./downloaded-file.txt")```
`runtime.files.read()` returns bytes. Decode to text when needed.
## Egress
Egress hosts are hostnames or wildcard host patterns, not URLs. `denylist` with an empty denied list is the default open policy. `allowlist` permits only matching allowed hosts.
```pythonfrom runta import EgressMode, EgressPolicy
runtime.egress.set_policy( EgressPolicy( mode=EgressMode.ALLOWLIST, allowed_hosts=["pypi.org", "*.pythonhosted.org"], denied_hosts=[], ))policy = runtime.egress.get()```
## Secrets
Stored secret values live at `runta.secrets`. Runtime-scoped stubs live at `runtime.secrets`. Default stubs live at `runta.secrets` and are copied to new runtimes.
```pythonfrom runta import SecretStubConfig
secret = runta.secrets.set("github-token", "secret-value", cache_ttl_secs=300)stub = runtime.secrets.set_secret_stub( "https://api.github.com", path="/repos/*", config=SecretStubConfig( credential="github-token", header="Authorization", value="Bearer ${credential}", ),)defaults = runta.secrets.list_default_secret_stubs()```
Use `list`, `get`, and `delete` helpers for stored secrets. Use `list_secret_stubs`, `get_secret_stub`, and `delete_secret_stub` for runtime stubs.
## Checkpoints
```pythoncheckpoint = runtime.checkpoints.create(name="demo-checkpoint")checkpoints = runta.checkpoints.list(include_system=True)restored = runta.runtimes.create("restored-demo", checkpoint_id=checkpoint.id)runta.checkpoints.delete(checkpoint.id)```
## Errors
The SDK raises `ConfigError`, `ApiError`, and `CommandError`.
```pythonfrom runta import ApiError, CommandError, ConfigError, Runta
try: runta = Runta() runtime = runta.runtimes.get("missing-runtime")except ApiError as exc: print(exc.status_code, exc.code, str(exc))except ConfigError: print("Check RUNTA_TOKEN")except CommandError as exc: print(exc.result.exit_code)```
For missing token errors, set `RUNTA_TOKEN`. For HTTP 401, check whether the token is missing, expired, or rejected. For readiness timeouts, increase the wait timeout or inspect runtime state before retrying.