Tama Python SDK
Typed, synchronous, agent-friendly access to Tama machines. The SDK mirrors the Tama CLI while keeping actions scoped to Python objects.
Install
Python 3.10 or newer is required.
python -m pip install "tama-sdk==0.1.2"
The PyPI distribution is named tama-sdk; the Python import is tama_sdk.
Authenticate
The simplest local setup is to install the Tama CLI, run tama login, and let
the SDK reuse the selected CLI profile:
curl -fsSL https://tama.computer/install | sh
tama login
from tama_sdk import Tama
with Tama() as tama:
print(tama.identity().account.id)
In CI, set TAMA_TOKEN instead. Set TAMA_API_URL only when using a non-default
gateway.
export TAMA_TOKEN="..."
export TAMA_API_URL="https://gateway.tama.computer" # optional
You can also pass a token explicitly:
import os
from tama_sdk import Tama
tama = Tama(api_key=os.environ["TAMA_TOKEN"])
Configuration precedence is explicit constructor values, TAMA_* environment
variables, then the selected CLI profile. TAMA_PROFILE selects a named CLI
profile. The Python SDK uses TAMA_API_URL; the CLI's endpoint override is named
TAMA_API.
Safe end-to-end example
This creates a machine, runs a command and a Codex session, and always stops the
machine so billing pauses. stop() snapshots the machine and is reversible;
delete()/rm() destroys it.
from tama_sdk import Tama
with Tama() as tama:
machine = tama.new(name="python-sdk-example")
try:
result = machine.exec(["python", "--version"], check=True)
print(result.stdout, end="")
prompt = machine.prompt(
"Inspect /workspace and write a concise README for the project.",
agent="codex",
check=True,
)
print(prompt.output, end="")
finally:
machine.stop()
Tama is a context manager because it owns a gRPC channel. The context manager
closes that local channel; it does not stop remote machines. Keep the
try/finally cleanup when your script creates or starts billable resources.
Machines
The common workflows mirror the CLI: new, list, get, rm, stop,
start, fork, exec, logs, prompt, expose, unexpose, ports,
desktop, terminal, and enable_ssh.
from tama_sdk import Tama
with Tama() as tama:
for machine in tama.list(all=True):
print(machine.id, machine.name, machine.status)
machine = tama.get("worker")
machine.stop()
if machine.snapshot:
print(machine.snapshot.disk_snapshot_id)
print("warm checkpoint:", machine.snapshot.has_memory)
machine.start()
new() and start() wait for the machine to become ready by default. Pass
wait=False for detached provisioning. exec(..., check=True) and
prompt(..., check=True) raise CommandError when the remote command exits
non-zero. A detached prompt has no exit code to check yet, so
prompt(..., detach=True, check=True) is rejected instead of silently ignoring
check. Long commands have no artificial RPC deadline; pass
exec(..., timeout=300) when the caller needs a five-minute bound.
Docker
Docker is disabled by default. Opt in per machine with
tama.new(docker_enabled=True); the setting is available as
machine.docker_enabled and survives restart and fork. A runtime that cannot
checkpoint Docker's nested namespaces may cold-restore a machine while inner
containers are running.
Idle auto-stop
Auto-stop is disabled by default. Set auto_stop_seconds=900 when creating a
machine to snapshot and stop it after 15 minutes without Tama-visible activity.
The minimum enabled value is 60 seconds; 0 disables the policy.
machine = tama.new(name="worker", auto_stop_seconds=15 * 60)
print(machine.last_active_at, machine.auto_stop_at)
machine.keep_active() # explicit heartbeat for an external/direct workflow
CLI/SDK commands, SSH/tunnels, agent sessions, and traffic through published
HTTP or WebSocket ports refresh the deadline automatically. A process doing
background compute with no Tama-visible traffic can look idle; disable
auto-stop for that workload, or call keep_active() from its controller.
Complete public surface
An agent should prefer the object methods for one machine and the collections for secondary resources:
tama.identity() # account/workspace identity
tama.usage(days=30) # credit balance and metered usage
tama.offers() # available images, CPU, memory, and GPUs
tama.new(...) # create a machine
tama.list(all=True) # list, including stopped machines
tama.get("worker") # get by name or id
tama.keep_active("worker") # explicit idle-policy heartbeat
tama.rm("worker") # permanently delete
tama.stop("worker") # snapshot and stop
tama.start("worker") # start and wait until ready
tama.fork(snapshot_id, name="copy") # fork an immutable snapshot
tama.exec("worker", ["pytest", "-q"], check=True)
tama.prompt("worker", "Fix the tests", agent="codex", check=True)
tama.logs(session_id) # durable agent-session transcript
tama.logs(machine_id, pid) # low-level process log stream
tama.expose("worker", 8000) # publish a port; returns its URL
tama.unexpose("worker", 8000)
tama.ports("worker") # {port: public_url_or_none}
tama.desktop("worker") # start/get browser desktop URL
tama.terminal("worker") # start/get browser terminal URL
tama.enable_ssh("worker", public_key)
The same machine-scoped actions are available on Machine: refresh, keep_active, exec,
prompt, stop, start, delete, expose, unexpose, desktop,
terminal, and enable_ssh. Its most useful properties are id, name,
status, status_detail, docker_enabled, auto_stop_seconds, last_active_at,
auto_stop_at, data, and the restore point returned by a stop in snapshot.
Every secondary collection is explicit:
tama.machines.create(...) # also get/list/delete/stop/start
tama.snapshots.create("worker", label="baseline")
tama.snapshots.list(machine="worker", automatic=False)
tama.snapshots.fork(snapshot_id, name="experiment")
tama.templates.create("worker", name="base", description="...", public=False)
tama.templates.list()
tama.templates.delete(template_id)
tama.secrets.set("OPENAI_API_KEY", value) # values are never returned
tama.secrets.list()
tama.secrets.delete("OPENAI_API_KEY")
created = tama.tokens.create("ci") # created.secret is shown once
tama.tokens.list()
tama.tokens.revoke(created.id)
tama.sessions.list("worker")
tama.sessions.logs(session_id)
tama.files.list("worker", "/workspace")
start_credit_purchase(amount_cents) returns a Stripe checkout URL and
confirm_credit_purchase(session_id) refreshes the balance after the browser
returns. Most agents should send a human to the console rather than operating a
payment flow. tama.raw exposes the generated gRPC stub for forward
compatibility; normal code should use the typed helpers above.
Detached agent session
from tama_sdk import Tama
with Tama() as tama:
machine = tama.get("worker")
session = machine.prompt(
"Run the test suite, fix failures, and summarize the patch.",
agent="codex",
detach=True,
)
print("session:", session.id)
for event in tama.logs(session.id):
print(event.data, end="")
Closing the local script does not stop a detached agent session. Its transcript
is durable and can be followed later with tama.logs(session.id).
Snapshots, forks, templates, secrets, and tokens
Secondary resources live on discoverable collections:
from tama_sdk import Tama
with Tama() as tama:
snapshot = tama.snapshots.create("worker", label="baseline")
if snapshot is not None:
fork = tama.snapshots.fork(snapshot.id, name="experiment-1")
fork.stop()
tama.snapshots.list(machine="worker")
tama.templates.list()
tama.secrets.set("OPENAI_API_KEY", "...")
tama.tokens.create("ci")
Snapshots and templates pin the machine's complete root filesystem as one immutable disk snapshot. A normal stop may also seal a memory checkpoint against that disk state, allowing a warm resume. Secret values are never returned by the SDK.
Errors and retries
Catch TamaError for the SDK's complete error family, or a specific subclass
such as AuthenticationError, NotFoundError, ValidationError, or
CommandError.
Machine ids are immutable and never reassigned. After delete() succeeds,
every operation selecting that id raises NotFoundError with code
grpc.StatusCode.NOT_FOUND; reconcilers may treat that result as terminal
proven absence. A stopped machine is not absent: it remains visible through
list(all=True) and get() until it is deleted. Stopped machines accrue no
Tama managed-compute charge.
Read-only RPCs retry short UNAVAILABLE and DEADLINE_EXCEEDED failures with
bounded exponential backoff. Mutations are never retried automatically: a
timed-out create, exec, or snapshot may already be running server-side. After an
ambiguous mutation failure, inspect state with list(all=True) or get() before
trying it again.
The timeout= on Tama(...) bounds ordinary control-plane RPCs. Operations
that legitimately seal or move machine state—stop, snapshot, template capture,
delete, and exec—do not inherit that short deadline. exec(timeout=...) is the
explicit opt-in bound for a remote command.
The generated protobuf schema is available as tama_sdk.proto, and the raw
generated service stub is available as tama.raw when a new RPC lands before a
convenience wrapper.
Full documentation: https://tama.computer/docs/#python-sdk
Development
From sdks/python in the Tama repository:
uv sync --extra dev
uv run --extra dev python scripts/generate.py
uv run --extra dev pytest
uv run --extra dev ruff check .
uv run --extra dev mypy
The generated protobuf modules are committed, so installing the wheel does not
require protoc.
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 tama_sdk-0.1.3.tar.gz.
File metadata
- Download URL: tama_sdk-0.1.3.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.6.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d3010b58ff215b4b537fd07bf49b6a7113578d8734ffcc79ecc8fb05008940a
|
|
| MD5 |
64762c9c69f3d437687ffe37d3a61566
|
|
| BLAKE2b-256 |
9dd004426b033e2e7406513ce8dcb57b3999b03d5d945f1d82285407319e8817
|
File details
Details for the file tama_sdk-0.1.3-py3-none-any.whl.
File metadata
- Download URL: tama_sdk-0.1.3-py3-none-any.whl
- Upload date:
- Size: 34.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.6.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48a13b6b97552710e53096421c21b08e2a8e43281e42a6c48b33fb43c00b533f
|
|
| MD5 |
4325ed280d0856c7fa2548f3fd6ae7e6
|
|
| BLAKE2b-256 |
d59d34ba3b0f24cc97ac8b5c47491364851ac293983e4ac8ac7536455833af4c
|