Already using the Anthropic or OpenAI SDK? Ship your agent to production in one call.

See the quickstart

Python SDK

The official Jettson SDK for Python. httpx-backed, sync today, async in the next release.

Three lines, one agent. The Python SDK is the fastest path from pip install to a running agent.

Install

bash
pip install jettson

Requires Python 3.9 or later. One runtime dep (httpx).

Quickstart

python
import os
from jettson import Jettson

client = Jettson(api_key=os.environ["JETTSON_API_KEY"])

agent = client.agents.spawn(
    task="Browse https://news.ycombinator.com and return the top story title."
)

result = client.agents.wait(agent.agent_id)
print(result.final_result)

Get an API key at /console/api-keys.

Constructor

python
Jettson(
    api_key: str,                           # required
    base_url: str = "https://jettson.dev/api/v1",
    max_retries: int = 3,
    timeout_seconds: float = 60.0,
)

Use as a context manager to release the HTTP connection pool on exit:

python
with Jettson(api_key=os.environ["JETTSON_API_KEY"]) as client:
    agent = client.agents.spawn(task="…")
    final = client.agents.wait(agent.agent_id)

Agents

agents.spawn(task, ...)

python
agent = client.agents.spawn(
    task="Research linear.app",
    name="research-run-001",
    region="lhr",                       # "iad" | "lhr" | "syd"
    idempotency_key="spawn:abc:1",      # dedupe accidental retries
)

Returns immediately with status="spawning".

agents.wait(agent_id, ...)

python
result = client.agents.wait(
    agent.agent_id,
    timeout_seconds=300,
    poll_interval_seconds=1.0,
    max_poll_interval_seconds=5.0,
)

Polls until status is completed / error / stopped. Raises AgentTimeoutError if the deadline lapses.

agents.get(agent_id) / agents.list(...) / agents.cancel(agent_id)

python
agent = client.agents.get("ag_…")

cursor = None
while True:
    page = client.agents.list(limit=50, cursor=cursor)
    for a in page.data:
        print(a.agent_id, a.status)
    cursor = page.next_cursor
    if not cursor:
        break

client.agents.cancel("ag_…")

Memory

memory.put(...)

python
client.memory.put(
    key="brand_color",
    value="Brand primary color is #FF5733",
    namespace="user_profile",
    tags=["brand"],
    importance=8,
    expires_in_days=90,
)

memory.get(key, namespace=)

python
m = client.memory.get("brand_color", namespace="user_profile")
if m:
    print(m.value)

Returns None (not an exception) if no memory matches.

memory.search(...)

python
results = client.memory.search(
    query="what color is the brand?",
    namespace="user_profile",
    mode="hybrid",     # "hybrid" | "semantic" | "keyword"
    limit=10,
    min_score=0.4,
)

for r in results:
    print(f"{r.key}: {r.value} (score={r.score:.2f})")

memory.list / delete / dedupe / consolidate / namespaces / export / import_

All ten public-API memory endpoints are covered. Signatures mirror the Memory API reference.

python
# Note the trailing underscore — `import` is a Python keyword.
result = client.memory.import_([
    {"key": "brand_color", "value": "#FF5733", "namespace": "user_profile"},
])
print(result.imported, result.failed)

Error handling

Every HTTP failure raises a typed exception. Catch the base class for any Jettson-side failure, or narrow:

python
from jettson import (
    JettsonAuthError,
    JettsonRateLimitError,
    JettsonQuotaExceededError,
    JettsonValidationError,
    JettsonNotFoundError,
    JettsonServerError,
    JettsonNetworkError,
    AgentTimeoutError,
)

try:
    client.agents.spawn(task="…")
except JettsonRateLimitError as err:
    print(f"Backing off {err.retry_after_seconds}s")
except JettsonQuotaExceededError as err:
    print(f"Hit quota: {err.used}/{err.limit} on {err.plan}")

Idempotent spawns

python
client.agents.spawn(
    task="…",
    idempotency_key=f"spawn:{user_id}:{request_id}",
)

The server returns the same agent for repeat calls inside a short window.

Regions

Multi-region warm pool is live in iad / lhr / syd. Pin a region per spawn:

python
client.agents.spawn(task="…", region="lhr")

If you don't specify one, the server tries iad first then falls back to other regions before cold-spawning.

Retries

Automatic retries on:

  • 429 — honors Retry-After header (3 attempts)
  • 5xx — exponential backoff 1s → 2s → 4s (3 attempts)
  • Network failure — one retry after the initial backoff
python
# Disable retries
Jettson(api_key=..., max_retries=0)

Type hints

The SDK is fully typed. All dataclasses are frozen + hashable:

python
from jettson import Agent, Memory, MemorySearchResult, AgentStatus, Region

def is_completed(agent: Agent) -> bool:
    return agent.status == "completed"

Async (coming soon)

AsyncJettson ships in the next release with the same surface area. Until then, the sync client integrates cleanly with asyncio.to_thread:

python
import asyncio

async def spawn_async(task: str) -> str:
    agent = await asyncio.to_thread(client.agents.spawn, task=task)
    final = await asyncio.to_thread(client.agents.wait, agent.agent_id)
    return final.final_result or ""

Source

github.com/jettsondev/jettson-sdk-python — MIT, ~1k LOC + tests.