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.
Metadata
Release files for tama-sdk 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tama_sdk-0.1.3.tar.gz | 31.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tama_sdk-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.8 kB
Release files / tama_sdk-0.1.3.tar.gz
| Download URL | tama_sdk-0.1.3.tar.gz |
|---|---|
| Size | 31.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4d3010b58ff215b4b537fd07bf49b6a7113578d8734ffcc79ecc8fb05008940a
|
|
BLAKE2b-256 checksum How to use checksums |
9dd004426b033e2e7406513ce8dcb57b3999b03d5d945f1d82285407319e8817
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.4
|
Release files / tama_sdk-0.1.3-py3-none-any.whl
| Download URL | tama_sdk-0.1.3-py3-none-any.whl |
|---|---|
| Size | 34.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
48a13b6b97552710e53096421c21b08e2a8e43281e42a6c48b33fb43c00b533f
|
|
BLAKE2b-256 checksum How to use checksums |
d59d34ba3b0f24cc97ac8b5c47491364851ac293983e4ac8ac7536455833af4c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.6.4
|
Security for tama-sdk 0.1.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.