Skip to content

Python SDK Skill

Create a python-sdk/SKILL.md file with this content.

python-sdk/SKILL.md
---
name: python-sdk
description: 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:
```bash
export 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
```bash
pip install runta-sdk
```
When developing the Python SDK itself from source:
```bash
uv pip install -e .
```
## Client Patterns
Async:
```python
import asyncio
from 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:
```python
from 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:
```python
runtimes = 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:
```python
result = 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.
```python
task = runtime.exec_detached("sleep 5 && echo done")
print(task.id)
print(task.wait().stdout_text)
```
## Files
```python
runtime.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.
```python
from 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.
```python
from 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
```python
checkpoint = 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`.
```python
from 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.