Python SDK
Single-file SDK ships in two flavors: vxsdk (sync, stdlib only) and vxsdk_async (httpx). Available as `import vxsdk` or as the brand-alias `import vxcloud` — both resolve to the same Client class. Same wire contract, same auth model, same error taxonomy as vxsdk-go and @vxcloud/sdk.
19 modules — every method shipped in 2026.8.17 is documented below with a runnable example.
Python SDK
Python 3.9+2026.8.17 · 19 modules
Single-file SDK ships in two flavors: vxsdk (sync, stdlib only) and vxsdk_async (httpx). Available as `import vxsdk` or as the brand-alias `import vxcloud` — both resolve to the same Client class. Same wire contract, same auth model, same error taxonomy as vxsdk-go and @vxcloud/sdk.
Install
pip install vxsdk # canonical namepip install vxsdk[async] # adds httpx for the async flavor# Brand-alias package — same code, just `import vxcloud`:pip install vxcloudpip install vxcloud[async]
Quickstart
import vxsdk# Or equivalently: `import vxcloud` (alias package — same code).# Auth: load credentials written by `vxcli auth login`c = vxsdk.Client.load_from_vxcli()# Equivalent aliases — all resolve to the same Client class:# c = vxsdk.VxCloud.load_from_vxcli()# c = vxsdk.vxcloud.load_from_vxcli()# Or explicit:# c = vxsdk.Client(api_key="xc_live_…", username="alice")# Provision a VM — `c.cloud.vm.provision(...)` mirrors the TypeScript SDK.# The legacy flat `c.cloud.create_vm(...)` also still works.vm = c.cloud.vm.provision(name="api-vm", cloud="aws", region="us-east-1",instance_type="t3.small", key_pair_name="AWSPRODKEY2")# Deploy a Docker container WITH HTTPS — single call.# Installs host nginx + Let's Encrypt cert in front of the first port (3000).# Requires grafana.example.com A record -> vm["public_ip"] already set.ssh = dict(host=vm["public_ip"], ssh_user="ubuntu",key_pair_name="AWSPRODKEY1") # keypair must be in Vaultsess = c.deploy.container(image="grafana/grafana:latest",name="grafana",ports=["3000:3000"],enable_ssl=True,domain="grafana.example.com",ssl_email="[email protected]",**ssh,)print(sess["session_id"], sess.get("ssl_certificate_status"))# Manage itprint(c.services.list(**ssh))print(c.services.status("grafana", **ssh))c.services.restart("grafana", **ssh)
Modules
- Client construction & authentication — 4 examples
- sessions — 1 example
- deploy (container + 14 stacks) — 8 examples
- install (catalog / script / compose) — 2 examples
- services (lifecycle + host ops) — 2 examples
- cicd (pipelines + builds) — 1 example
- marketplace (agents / models / solutions) — 3 examples
- cloud (vm / s3 / iam / network / database / kubernetes / serverless) — 6 examples
- agentcontrol (full /api/v2/agentcontrol/* surface — 22 sub-resources) — 10 examples
- metaldb (self-managed PostgreSQL over SSH) — 1 example
- salesshift (tracked email + the leads pool) — 6 examples
- networks (diagnostic scripts) — 1 example
- agents (AI orchestration) — 2 examples
- chat (multi-provider AI) — 2 examples
- observability (backups / migrations / sync) — 2 examples
- billing (multicloud + optimization) — 1 example
- workspace setup (35 endpoints) — 8 examples
- errors — 1 example
- Production notes & known issues — 4 examples
Client construction & authentication
Two constructors — explicit credentials or load from `~/.vxcloud/credentials.json` (the file `vxcli auth login` writes). Auto-refresh JWT on 401.
1import vxsdk2 3c = vxsdk.Client(4 api_key="xc_live_…",5 username="your-username",6 # optional overrides:7 # vxcloud_url="https://api.vxcloud.io",8 # node_url="https://node1.vxcloud.io",9)10print(c.whoami)sessions
List, inspect, replay, fetch, or tear down deploy/install sessions.
1# Recent sessions (server may use 'sessions' or default keys)2for s in c.sessions.list():3 print(s.get("session_id"), s.get("status"))4 5# Show details and contents of a specific session6detail = c.sessions.show("adc2d5c4-…")7 8# Replay a planned deploy (--dry-run was the previous run)9c.sessions.apply("adc2d5c4-…")10 11# Fetch terraform state + artifacts12artifacts = c.sessions.pull("adc2d5c4-…")13 14# Tear down15c.sessions.delete("adc2d5c4-…", force=True)deploy (container + 14 stacks)
Deploy any Docker image, or any of the 14 supported stacks (fastapi, react, nextjs, django, nodejs, python, golang, rust, cpp, php, static, angular, vuejs, expo, flask, java, laravel, metaldb). Single-command HTTPS via `enable_ssl` + `domain` (host-nginx+certbot for `container`; shared Traefik for stack deploys).
1# Installs host nginx + Let's Encrypt cert in front of the first port (3000).2# Requires: grafana.example.com A record -> 13.216.243.13 already set.3result = c.deploy.container(4 image="grafana/grafana:latest",5 name="grafana",6 ports=["3000:3000"],7 env=["GF_SECURITY_ADMIN_PASSWORD=changeme"],8 restart="unless-stopped",9 enable_ssl=True,10 domain="grafana.example.com",11 ssl_email="[email protected]",12 host="13.216.243.13", ssh_user="ubuntu",13 key_pair_name="AWSPRODKEY1",14)15print(result["session_id"], result.get("ssl_certificate_status"))install (catalog / script / compose)
Apply a custom shell installer or a docker-compose.yml on a remote VM. Catalog-by-tech is vxcli-only (it embeds the scripts).
1with open("./my-installer.sh", "rb") as f:2 script = f.read()3 4c.install.script(5 script=script, script_name="my-installer.sh",6 args=["--version=2.1"],7 host="h.vxcloud.io", ssh_user="ubuntu",8 key_pair_name="AWSPRODKEY1.PEM",9)services (lifecycle + host ops)
Start / stop / restart / remove / status of a Docker container, plus host-level reboot, cleanup, and diagnostics under `services.vm`.
1ssh = dict(host="203.0.113.24", ssh_user="ubuntu",2 key_pair_name="AWSPRODKEY1.PEM")3 4# List5for line in c.services.list(**ssh).get("output", "").splitlines():6 print(line)7 8# Status of one container9print(c.services.status("studio-backend", **ssh))10 11# Lifecycle12c.services.start("studio-backend", **ssh)13c.services.stop("studio-backend", **ssh)14c.services.restart("studio-backend", **ssh)15c.services.remove("studio-backend", **ssh)16# Logs (systemd unit only)17c.services.logs("ollama", tail=200, **ssh)cicd (pipelines + builds)
Manage CI/CD pipelines, trigger builds, inspect runs.
1for p in c.cicd.pipelines.list():2 print(p["id"], p.get("name"))3 4build = c.cicd.pipelines.trigger("studio-api", branch="main")5print("triggered:", build.get("build_id"))6 7# Inspect a build8print(c.cicd.builds.show("<build-id>"))marketplace (agents / models / solutions)
Browse and provision marketplace items — AI agents, AI models, Terraform-backed solution stacks.
1# Browse2for a in c.marketplace.agents.list():3 print(a["id"], a.get("name"))4 5# Deploy onto a remote VM6c.marketplace.agents.deploy(7 "prompt_agent",8 host="h.vxcloud.io", ssh_user="ubuntu",9 key_pair_name="AWSPRODKEY1.PEM",10)cloud (vm / s3 / iam / network / database / kubernetes / serverless)
Per-provider helpers covering VM lifecycle, storage, IAM, networking, managed databases, Kubernetes, and serverless functions. The `c.cloud.vm.*` namespace mirrors the TypeScript SDK; the flat `c.cloud.create_*(...)` methods are kept for back-compat.
1# Preferred: `c.cloud.vm.*` mirrors the TypeScript SDK.2vm = c.cloud.vm.provision(3 name="api-vm", cloud="aws", region="us-east-1",4 instance_type="t3.small", key_pair_name="AWSPRODKEY2",5 tags={"env": "staging"},6)7print(vm["public_ip"])8 9# Lifecycle control10state = c.cloud.vm.status(instance_id=vm["instance_id"], cloud="aws")11c.cloud.vm.action(instance_id=vm["instance_id"], action="restart", cloud="aws")12# action must be one of: start | stop | restart | reboot13 14# Legacy flat alias still works:15# vm = c.cloud.create_vm(name="api-vm", ...)agentcontrol (full /api/v2/agentcontrol/* surface — 22 sub-resources)
Full UI parity with the AgentControl dashboard at /dashboard/?tab=agentcontrol. Original surfaces (fine_tuning, training, knowledge, datasets, ac_agents, github) plus the new sub-resources: embeddings, tools, mcp, evals, code, models, deployments, web_assets, benchmarks, catalog, health, events, llm, deploy_targets, workflows, infra. Plus `runtime_metrics(endpoint)` to proxy a marketplace agent's /metrics scrape through the node. Every call sends `X-Tenant-ID` automatically; pass `tenant_id=` per call to override.
1# Top-level dashboard summary — counts, recent activity, etc.2summary = c.agentcontrol.summary()3print(summary.get("total_models"), summary.get("active_training_jobs"))4 5# Browse each surface6for j in c.agentcontrol.fine_tuning.list():7 print("FT:", j["id"], j.get("status"))8 9for t in c.agentcontrol.training.list():10 print("Train:", t["id"], t.get("status"))11 12for k in c.agentcontrol.knowledge.list():13 print("KB:", k["id"], k.get("name"))14 15for d in c.agentcontrol.datasets.list():16 print("DS:", d["id"], d.get("row_count"))metaldb (self-managed PostgreSQL over SSH)
Provision and verify a self-managed PostgreSQL instance on a customer VM. The platform installs Postgres, opens the firewall, creates the user/database, and stores the resulting connection string in workspace Vault under `metaldb/<resource>`. Use this when you want full DB lifecycle ownership instead of a managed RDS / Aurora.
1# Provision Postgres on an existing VM via SSH. Credentials are minted2# by the platform and written to Vault — no plaintext password leaves the3# call. Returns the connection string + Vault path.4result = c.metaldb.provision(5 resource_name="app-metaldb",6 host="203.0.113.24", ssh_user="ubuntu",7 key_pair_name="AWSPRODKEY1", # MUST be in Vault8 db_name="app", db_user="app",9 pg_version="16",10 port=5432,11 listen_address="0.0.0.0",12)13print(result["connection_string"], "·", result.get("vault_path"))14 15# Verify connectivity from the same node (does not require client psql)16ok = c.metaldb.test_connection(17 host="203.0.113.24",18 port=5432, db_name="app", db_user="app",19 vault_path=result["vault_path"], # password is fetched from Vault20)21print("reachable:", ok.get("connected"))salesshift (tracked email + the leads pool)
The SalesShift surface — 23 sync methods on `c.salesshift`, and 23 on the async client. Covers the four email/stats calls and the whole leads pool: 20 of SalesShift’s 306 routes, and none of its 57 messaging routes. Deals, sequences, quotes, contracts, invoices, calendar, deliverability and webmail have NO SDK method in any language — reach those over HTTP. Returns plain dicts and lists; the typed part is the exception tree. Verified: eight of these methods were called against a running control plane and all eight returned the documented shapes.
1import vxsdk2 3c = vxsdk.Client.load_from_vxcli()4 5# Dashboard counters — contacts, companies, open deals, email funnel.6stats = c.salesshift.get_stats()7print(stats["contacts"], stats["email_stats"]["opened"])8 9# Tracked outbound mail with engagement state.10for m in c.salesshift.list_emails("sent"):11 print(m["to_email"], m["status"], m["open_count"])12 13# Send one. Merge tags resolve against the contact record; suppressed14# recipients are rejected — that gate is not optional.15out = c.salesshift.send_email(16 to_email="[email protected]",17 subject="Following up, {{first_name}}",18 body_html="<p>Saw you shipped v2 — worth 15 minutes?</p>",19)20print(out["tracking_id"], out["provider"])21 22# The email worker runs on YOUR tenant node, not the control plane.23print(c.salesshift.get_worker_health()) # {"status": "healthy", …}networks (diagnostic scripts)
Catalog of DNS / bandwidth / port-check / security-audit scripts. Local execution is the caller’s job; remote ships through install.script.
1# Catalog (soft-fails to [] if server hasn't published the endpoint)2for s in c.networks.list():3 print(s.get("name"), s.get("description"))4 5# Run a script remotely on a target VM6script_bytes = open("./port-check.sh", "rb").read()7c.networks.run_remote(8 script_bytes, script_name="port-check.sh", args=["443"],9 host="h.vxcloud.io", ssh_user="ubuntu",10 key_pair_name="AWSPRODKEY1.PEM",11)agents (AI orchestration)
AI-agent surface mirroring `vxcli agent`. Coding / DevOps / Git / parallel + tool dispatch.
1# Generate code2out = c.agents.coding(3 "Write a FastAPI route that validates a JWT bearer token",4 lang="python",5)6print(out["output"])7 8# DevOps orchestration (uses git + docker + VM tools)9c.agents.devops("deploy main of api/ to staging and roll forward")10 11# Git operations12c.agents.git("draft commit messages for the staged diff")chat (multi-provider AI)
Provider envelope normalizes Anthropic / OpenAI / Google / OpenClaw / Deepseek / Qwen / Groq / Mistral / Perplexity / Hugging Face / Ollama / Hermes / Cohere / Azure-OpenAI / Gemini / Llama.
1out = c.chat.send(2 provider="anthropic",3 model="claude-opus-4-7",4 messages=[5 {"role": "system", "content": "You are concise."},6 {"role": "user", "content": "What is HCL terraform?"},7 ],8 max_tokens=500,9)10print(out["completion"])observability (backups / migrations / sync)
Snapshot backups, migration plans, batch resource discovery.
1bk = c.observability.backups.create(2 resource_id="rds-abc", resource_type="database",3 backup_name="pre-migration",4)5print(bk["id"], bk.get("status"))6 7for b in c.observability.backups.list():8 print(b["id"], b.get("size_gb"))9 10c.observability.backups.restore(backup_id=bk["id"], target_region="eu-west-1")billing (multicloud + optimization)
Cost reporting + AI-powered optimization recommendations.
1r = c.billing.multicloud(start_date="2026-04-01", end_date="2026-04-30")2print("Total USD:", r["total_usd"])3for cloud, usd in r.get("breakdown", {}).items():4 print(f" {cloud:8s} {usd:>10.2f}")5 6opt = c.billing.optimization(provider="aws")7for rec in opt.get("recommendations", []):8 print(rec["action"], "→", rec["resource"])workspace setup (35 endpoints)
Workspace + organization lifecycle, cloud-provider creds (Alibaba/AWS/Azure/Google Cloud/Linode), AI-provider creds (16 providers), API tokens, Git/payment/SMTP/SSL/OAuth/OKTA/CyberArk credential storage.
1c.workspace.create_workspace("my-org", region="us-east-1")2c.workspace.create_organization("acme-corp", plan="enterprise")3 4# Cloud-provider creds → stored in HashiCorp Vault server-side5c.workspace.store_aws_credentials(6 access_key_id="AKIA…",7 secret_access_key="…",8 region="us-east-1",9)10c.workspace.store_gcp_credentials(11 project_id="my-project", service_account_key='{"type":"service_account",…}',12)errors
Typed error tree — discriminate failure modes via `isinstance`. The transport layer maps HTTP status codes onto these classes.
1from vxsdk import (2 VxError, VxAuthError, VxValidationError, VxNotFoundError,3 VxRateLimitError, VxServerError, VxNetworkError,4)5 6try:7 c.deploy.container(image="…", name="…", host="…", ssh_user="ubuntu",8 key_pair_name="…")9except VxAuthError:10 print("re-run vxcli auth login")11except VxValidationError as e:12 print("bad input:", e)13except (VxRateLimitError, VxServerError, VxNetworkError):14 # these are isRetryable — back off + retry15 raiseProduction notes & known issues
Real failure modes you will hit at least once. Same content as the CLI "Operational gotchas" section, adapted to SDK usage.
1# c.deploy.stack("fastapi"/"react"/"nextjs"/...) resolves SSH keys ONLY2# from the workspace Vault. The server's form-validator rejects requests3# without `key_pair_name`, and `private_key_pem` is ignored. Upload first:4#5# vxcli configure setup vm --key-pair-name MYKEY --pem-file ./mykey.pem6#7# c.deploy.container DOES accept private_key_pem as a fallback.Was this page helpful?