Official Python SDK for MIOSA - the AI cloud platform for sandboxes, desktop computers, deployments, managed databases, S3 storage, and volumes.
Project description
miosa (Python)
Official Python SDK for MIOSA — the AI cloud platform for sandboxes, computers, deployments, and managed data.
Install
pip install miosa
# or
uv add miosa
# or
poetry add miosa
Requires Python 3.9+. Dependencies: httpx, pydantic v2.
Quickstart
from miosa import Miosa
miosa = Miosa(api_key="msk_live_...")
# Create or resume a persistent sandbox workspace, then work inside it.
sb = miosa.sandboxes.create_agent_workspace(
"my-build",
external_workspace_id="customer-workspace-123",
)
result = sb.exec.run("python --version")
print(result.stdout) # Python 3.12.x
sb.files.write("/workspace/hello.py", "print('hello from miosa')")
out = sb.exec.run("python /workspace/hello.py")
print(out.stdout) # hello from miosa
print(sb.preview.create(port=8000)["url"])
# https://8000-<slug>.sandbox.miosa.ai/
sb.snapshots.create("after-hello-world")
sb.pause()
What's included
| Resource | Description |
|---|---|
miosa.computers |
Firecracker microVMs — full lifecycle, exec, files, services |
miosa.sandboxes |
Lightweight code-execution VMs via the /sandboxes route |
miosa.deployments |
Versioned production releases with rollback |
miosa.databases |
Managed Postgres / Redis lifecycle |
miosa.storage |
S3-compatible object storage |
miosa.volumes |
Persistent block storage |
miosa.api_keys |
Programmatic API key management |
miosa.usage |
Usage reports per workspace, per external tenant |
miosa.settings |
Workspace config, branding, BYOK provider keys |
miosa.webhooks |
Outgoing tenant webhooks — CRUD, test, delivery history |
miosa.open_computers |
BYOC host management — register your own machines |
miosa.devices |
Unified device facade for sandbox/computer list, exec, files, previews |
miosa.connectors |
Provider credentials and short-lived runtime tokens |
miosa.runtime_env |
Inherited tenant/workspace/project runtime environment variables |
Computers and Desktop Access
computer is the user-facing product. miosa-desktop is the desktop computer
template/profile. The canonical fast desktop profile is:
computer = miosa.computers.create(
name="agent-desktop",
template_type="miosa-desktop",
size="small", # 2 vCPU / 4 GB
)
Authenticated platform desktop links do not need a viewer password. Raw
external viewer links such as *.computer.miosa.ai/desktop/index.html are
password-gated; rotate the password when you need to share that raw link:
status = computer.viewer_password()
rotated = computer.rotate_viewer_password()
print(rotated["viewer_password"])
Connect vs Egress
Use Connect when your product needs to manage provider credentials for agents, sandboxes, computers, or deployments. Connect owns the product-level contract: connectors, installations, project links, inherited defaults, short-lived tokens, white-label attribution, and runtime bindings.
Use Egress when you need the low-level security boundary: encrypted secret
storage, outbound host allowlists, placeholder token exchange, and audit logs.
Egress is the enforcement layer under Connect. Most white-label apps should
call miosa.connectors and runtime binding helpers first; only call
miosa.secrets, miosa.network, or miosa.audit when you are building
security/admin controls directly.
import os
connector = miosa.connectors.create(
"anthropic",
name="workspace-claude",
scope="workspace",
external_workspace_id="clinic-iq",
value=os.environ["ANTHROPIC_API_KEY"],
)
# Runtime-level materialization: the sandbox sees ANTHROPIC_API_KEY, but your
# app does not get the raw provider key back from MIOSA.
miosa.connectors.materialize_defaults(
workspace_id="workspace-id",
resource_type="sandbox",
resource_id=sb.id,
target="agent",
external_workspace_id="clinic-iq",
)
Agent workspaces
For AI builders, code assistants, and white-label agent products, the sandbox
is the development machine. Do not run builds on the user's laptop and upload
the result as the primary flow. Create or resume a stable sandbox workspace,
write files under /workspace, run package installs/tests/builds inside the
sandbox, expose previews from the sandbox, and publish from that sandbox.
sb = miosa.sandboxes.get_or_create(
"acme-marketing-page",
template_id="miosa-sandbox",
persistent=True,
timeout_sec=86_400,
idle_timeout_sec=1800,
snapshot_expiration_days=30,
keep_last_snapshots=1,
external_workspace_id="acme",
external_user_id="jane",
wait_until_ready=True,
)
sb.files.write_files([
{"path": "/workspace/package.json", "data": '{"scripts":{"dev":"vite --host 0.0.0.0"}}'},
{"path": "/workspace/index.html", "data": '<main id="app"></main>'},
])
for event in sb.exec_stream("cd /workspace && npm install && npm run dev -- --port 3000"):
print(event)
preview = sb.preview.create(port=3000)
print(preview["url"])
For platform agents that plan work outside the sandbox and then hand execution to a runtime inside the sandbox/computer, use the unified device API:
miosa.agent_runtime_profiles.create(
workspace_id="clinic-workspace",
name="ClinicIQ Claude Code",
runtime="claude-code",
is_default=True,
connectors=[
"anthropic/cliniciq",
{
"uid": "refero",
"type": "mcp",
"managed": True,
"server_url": "https://api.refero.design/mcp",
},
],
env={"ANTHROPIC_API_KEY": "miosa-managed:anthropic/cliniciq"},
metadata={"model": "claude-opus-4.8", "white_label_client": "cliniciq"},
)
miosa.devices.write_file(
sb.id,
"/workspace/PLAN.md",
content="# Build plan\nUse the customer profile and export /workspace/out.",
)
build = miosa.devices.exec(
sb.id,
"npm install && npm run build",
cwd="/workspace",
timeout_ms=600_000,
)
artifact = miosa.devices.read_file(sb.id, "/workspace/out/report.pdf")
create_agent_workspace() is a convenience wrapper around get_or_create()
with builder defaults: a 24-hour activity cap, thirty-minute idle
snapshot/pause, readiness waiting, 30-day snapshot-retention metadata,
keep-last-snapshot metadata, and metadata that marks the sandbox as an agent
workspace.
That mirrors the Vercel-style persistent-sandbox model without keeping CPU
running forever: activity extends the running session, idle workspaces are
checkpointed and paused, and later sessions resume from the checkpoint. Use
extend(86_400) before long builds, pause() when the user is done for now,
resume() for the next session, snapshots.create() for manual checkpoints,
and destroy() only when the workspace should be permanently deleted.
Agent SDK
The Python SDK includes a small agent loop plus provider adapters and a MIOSA tool catalogue. This is the quickest path when you want an LLM to operate MIOSA computers directly.
from miosa.agent import Agent, groq_provider
agent = Agent(
provider=groq_provider(
api_key="gsk_...",
model="moonshotai/kimi-k2-instruct-0905",
),
miosa_api_key="msk_live_...",
)
result = agent.run(
"Create a sandbox workspace, write /workspace/hello.py, run it, show me "
"the output, snapshot it, then pause the sandbox.",
max_iterations=10,
)
print(result.final_text)
Built-in agent tools expose the computer primitive in plain terms:
| Tool | Does |
|---|---|
create_sandbox |
Create/resume a persistent code sandbox workspace for shell/Python/Node/files. |
create_computer |
Boot a general MIOSA computer for GUI, services, previews, files. |
list_computers |
List active computers, sandboxes, and desktops. |
get_computer |
Fetch status, template, size, and public URL. |
exec / exec_python |
Run bash or Python inside the computer. |
read_file / write_file / list_files |
Work with files inside the computer. |
preview_url |
Get the public HTTPS URL for a service port. |
pause_sandbox / resume_sandbox |
Stop/resume a persistent workspace without deleting files. |
extend_sandbox |
Extend the activity timeout before long installs, builds, or agent tasks. |
snapshot_sandbox |
Create a checkpoint after dependency install or a good edit. |
deploy_sandbox |
Publish to normal MIOSA Deploy. |
deploy_docker |
Publish to the workspace App Engine appliance. |
destroy_computer |
Release compute resources when done. |
Provider factories include openai_provider, groq_provider,
deepseek_provider, openrouter_provider, together_provider,
fireworks_provider, mistral_provider, cerebras_provider,
perplexity_provider, xai_provider, ollama_provider, lm_studio_provider,
and openai_compatible_provider for custom routers.
Sandbox-first builder examples live in examples/:
See BUILDER_GUIDE.md for the full “build your own Lovable with MIOSA sandboxes” product pattern.
| Example | What it builds |
|---|---|
agent_sandbox_website_builder.py |
A Lovable-style website builder flow. |
agent_sandbox_app_builder.py |
A small app builder with a dev server and preview. |
agent_sandbox_artifact_builder.py |
Markdown/doc artifacts in /workspace/artifacts. |
agent_sandbox_slide_deck_builder.py |
A deck workspace under /workspace/deck. |
Set GROQ_API_KEY and MIOSA_API_KEY, then run one of the examples. They keep
the sandbox alive with miosa_tool_options={"allow_destroy": False} so your app
can show previews, inspect generated files, or publish later.
The agent should treat a MIOSA sandbox like the actual development machine:
write source files under /workspace, run package managers/tests/builds inside
the sandbox, start dev servers inside the sandbox, stream logs/tool results back
to your UI, and only publish after a sandbox preview passes a smoke check.
File operations
# Write / read
computer.files.write_file("/workspace/config.json", '{"key": "value"}')
text = computer.files.read_file("/workspace/config.json")
# Upload / download
computer.files.upload("/local/report.pdf", "/workspace/report.pdf")
raw_bytes = computer.files.download("/workspace/report.pdf")
# List / stat / mkdir / rename / chmod
entries = computer.files.list("/workspace")
stat = computer.files.stat("/workspace/config.json")
computer.files.mkdir("/workspace/output", recursive=True)
computer.files.rename("/workspace/old.txt", "/workspace/new.txt")
computer.files.chmod("/workspace/run.sh", 0o755)
Services (background processes)
svc = computer.services.create(
name="api",
command="uvicorn app:main --port 8080",
working_dir="/workspace",
env={"DEBUG": "1"},
port=8080,
)
for log in computer.services.logs(svc.id, follow=True):
print(log.stream, log.line)
computer.services.restart(svc.id)
computer.services.delete(svc.id)
Publish from sandbox
Sandbox previews are mutable builder URLs. Publishing creates a durable
deployment version with a stable url / public_url.
sb = miosa.sandboxes.create(name="clinic-intake", template_id="miosa-sandbox")
sb.files.write_file("/workspace/index.html", "<h1>Clinic intake</h1>")
result = sb.deploy(
name="clinic-intake",
output_path="/workspace",
entrypoint="index.html",
)
print(result["url"])
For full-stack/dynamic apps:
result = sb.deploy(
name="clinic-intake-api",
output_path="/workspace",
build_command="npm run build",
run_command="npm start",
port=3000,
health_check_path="/",
resources={
"database": {"auto": True, "engine": "postgresql", "size": "xs"},
"storage": {"auto": True},
},
domain="intake.apps.cliniciq.com",
)
If result["state"] == "building" for a dynamic app, poll
miosa.deployments.get(result["deployment_id"]) until it is running. Always
display the server-returned url / public_url; do not hardcode
preview.miosa.app, api.miosa.app, or <tenant>.miosa.app.
For workspace App Engine, publish from the same sandbox but choose the App Engine target:
result = sb.deploy_docker(
name="lead-magnet",
path="/workspace",
build_command="npm run build",
run_command="npm start",
port=3000,
)
print(result.get("url") or result.get("public_url"))
App Engine runs app containers inside the workspace's dedicated MIOSA App Engine appliance VM. It is separate from normal MIOSA dynamic runtime VMs and is useful when a workspace needs many small apps, funnels, lead magnets, APIs, or client sites.
Desktop control
screenshot = computer.screenshot() # PNG bytes
computer.click(640, 400)
computer.double_click(640, 400)
computer.type("hello world")
computer.key("Return")
computer.scroll("down", 3)
computer.drag(100, 100, 400, 400)
cursor = computer.cursor()
windows = computer.windows()
computer.launch("firefox")
Async usage
import asyncio
from miosa import AsyncMiosa
async def main():
async with AsyncMiosa(api_key="msk_live_...") as miosa:
computer = await miosa.computers.create(
name="async-build", template_type="miosa-sandbox"
)
await computer.files.write_file("/workspace/app.py", "print('async!')")
result = await computer.exec.run("python /workspace/app.py")
print(result.stdout)
await computer.destroy()
asyncio.run(main())
White-label / multi-tenant
Tag resources with external_workspace_id and external_user_id to attribute usage to your downstream customers:
computer = miosa.computers.create(
name="customer-build",
template_type="miosa-sandbox",
metadata={
"external_workspace_id": "dental-office-123",
"external_user_id": "dr-smith-456",
},
)
White-label URL layers are separate:
sandbox preview: https://<port>-<slug>.sandbox.<preview-domain>
durable deployment: https://<slug>.<deployment-domain>
custom domain: https://app.customer.com
Tenant preview-domain management is available through miosa.tenant. Tenant
deployment-domain routing exists server-side; clients should consume deployment
public_url instead of reconstructing it.
Error handling
from miosa import (
AuthenticationError, NotFoundError, RateLimitError, MiosaError
)
try:
computer = miosa.computers.get("cmp_doesnt_exist")
except NotFoundError:
print("Computer not found")
except RateLimitError as e:
print(f"Rate limited; retry after {e.retry_after}s")
except AuthenticationError:
print("Check your API key")
except MiosaError as e:
print(f"API error {e.status}: {e.message}")
Exception hierarchy: MiosaError > AuthenticationError (401), InsufficientCreditsError (402), PermissionError (403), NotFoundError (404), ValidationError (422), RateLimitError (429), ServerError (5xx), ConnectionError, TimeoutError.
Configuration
| Option | Env var | Default |
|---|---|---|
api_key |
MIOSA_API_KEY |
— |
base_url |
MIOSA_BASE_URL |
https://api.miosa.ai/api/v1 |
timeout |
— | 30s |
max_retries |
— | 3 |
Links
Phase 1-4 methods (v1.1.0)
Preview tokens and share URLs
# Mint a scoped preview token (e.g. for iframe embed)
token = sb.preview_token(expires_in=3600, scope="read")
print(token["url"]) # https://...?mt=mp_<token>
# Create a public share link (no API key required)
share = sb.share.create(expires_in=7200)
print(share["share_url"])
File tree and batch write
tree = sb.files.tree("/workspace", depth=2)
sb.files.write_many([
{"path": "/workspace/app.py", "content": "print('hello')"},
{"path": "/workspace/cfg.json", "content": b"{}"},
])
Tenant events stream and quotas
for event in client.events.stream(types=["sandbox.*"]):
print(event["_event_type"], event)
client.quotas.set("usr_abc", max_sandboxes=10, max_concurrent=3)
Webhook signature verification
from miosa.resources.webhooks import Webhooks
ok = Webhooks.verify_signature(request.body, request.headers["X-Miosa-Signature"], secret)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file miosa-1.3.1.tar.gz.
File metadata
- Download URL: miosa-1.3.1.tar.gz
- Upload date:
- Size: 279.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f7b20f033360bc9e2fb8d5e3c396c82e94adb00968a0409f3a45710325f7c873
|
|
| MD5 |
e5473ca4f53b7df5c75e9420edbe300b
|
|
| BLAKE2b-256 |
7bb8ff9d50a6181ec302f8e3135388cf20da23dafc1d70c2d816a8dc5ede3408
|
File details
Details for the file miosa-1.3.1-py3-none-any.whl.
File metadata
- Download URL: miosa-1.3.1-py3-none-any.whl
- Upload date:
- Size: 207.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dad696b256e2a7b6e04ae77b014fbfeda20d45bae914b7b185a1f73356bd0073
|
|
| MD5 |
387f526625cbb09560be87b857deecb8
|
|
| BLAKE2b-256 |
a0311c966009d2045afa25bfc16c2686294cb66137e8b5d7422366f154b7cb36
|