Skip to main content

m8tes Python SDK

PyPI Tests Python 3.11+ License: MIT

Run agents from Python with 190+ integrations, memory, streaming, and per-user isolation.

Install

pip install -U "m8tes>=4.32.1"

Quick start

  1. Create an account and save your API key.
  2. Set the key in your terminal:
export M8TES_API_KEY=m8_your_key_here
  1. Stream a reply using the $1 test credit included with new API accounts. No card or provider sign-in is required:
from m8tes import M8tes

client = M8tes()
for text in client.runs.stream_text(
    message="Draft a warm reply to a customer asking to cancel.",
    user_id="hello_world",
    model="deepseek-v4-1-flash",
    raise_on_error=True,
):
    print(text, end="", flush=True)

The test credit covers deepseek-v4-1-flash, with one run in flight at a time. Keep strict mode on and pass a distinct user_id for each customer. Top up for the full model catalog and sustained traffic. Platform/web signups start with a $0 prepaid balance.

For personal development on your own model subscription, follow the optional provider setup guide. That flow connects a provider and explicitly disables strict scope checks account-wide; customer-facing apps should keep strict mode enabled.

Next step Guide
Stream text and tool events Runs
Connect Stripe, Slack, or another app Tools
Scope agents, tasks, and memory Users
Configure built-in management and feedback tools Built-in tools
Check report claims or get bounded second opinions Jev judgments

Auth & usage

Rotate your API key with POST /api/v2/token. That endpoint returns a new API key and invalidates the previous one.

Check current plan, run usage, and cost limits with client.billing.usage() (or client.auth.get_usage()). A billable run is one execution that completes with output — manual, scheduled, webhook, email, reply, or retry. Self-meter spend and control overage:

usage = client.billing.usage()
print(usage.plan, usage.runs_used, usage.runs_limit, usage.overage_used_cents)

# Browse Hobby, Individual ($20 with your model subscription), and team plans
for plan in client.billing.plans(include_free=True):
    print(plan.slug, plan.display_name, plan.included_runs, plan.monthly_price_cents)

# Platform-inference team plans expose plan.overage_available=true and can opt in
# to usage overage with a monthly spend cap.
client.billing.set_overage(enabled=True, monthly_cap_cents=5000)  # $50 cap

New API accounts include $1 test credit for deepseek-v4-1-flash; platform/web signups start unfunded. For personal development, connect a model subscription to activate the $0 Hobby plan immediately (150 runs every 30 days), choose Individual for $20/month and 1,000 runs using that subscription, or choose a team plan starting at $1,000/month with inference included.

Enable an @notifications.m8tes.ai inbox per agent with email_inbox=True on client.agents.create(...) or call client.agents.enable_email_inbox(agent_id) later.

Need iMessage-triggered runs? Configure BlueBubbles on your account, then set inbound_imessage_enabled=True and imessage_chat_guid="..." on client.agents.create(...) or client.agents.update(...). Use a dedicated 1:1 chat unless you intentionally want everyone in that thread to trigger the agent and receive its replies.

Inspect account request history with client.audit_logs.list(...):

page = client.audit_logs.list(method="POST", resource_type="run", limit=10)
for log in page.data:
    print(log.created_at, log.method, log.path, log.status_code)

Use cases

Revenue reporting. Pull MRR from Stripe, update the tracking sheet, post weekly delta to Slack. No more manual Monday reporting.

Support triage. Classify inbound tickets, draft replies, escalate blockers. Runs 24/7 on a schedule.

Ad spend monitoring. Check Google Ads weekly, pause low-converting campaigns, alert the team.

Customer-facing agents. Give each user their own agent with isolated memory, tools, and permissions. Multi-tenant without custom plumbing.

vs. eve, LangChain, CrewAI, and other frameworks

eve, LangChain, CrewAI, and the OpenAI Agents SDK are agent frameworks. They help you build one production agent — but you still write, deploy, and operate the agent application, and execution, OAuth, scheduling, memory, approval flows, and tenant isolation are all yours to build and host.

eve / LangChain / CrewAI / OpenAI SDK m8tes
An agent is Code you write and deploy An API resource created at runtime
Agent execution Local or your cloud — you host it Hosted sandbox
Multi-tenancy Build isolation yourself One user_id parameter
Tool integrations Build and maintain 190+ managed integrations with OAuth
Scheduling & triggers Write your own Built in
Memory DIY persistence layer Per-user memory out of the box
Human-in-the-loop Build approval flows Three modes built in
Real-time streaming Roll your own SSE out of the box
Infrastructure Your problem Our problem

m8tes is not a framework. It's the layer above one: a framework gives you a codebase to build an agent; m8tes gives you an API to give every customer one. The Python SDK is the client on top.

Models

Pick the model per agent or per run via model=. List what's available (with prices) instead of hardcoding:

for m in client.models.list().data:
    print(m.id, m.provider, m.pricing.input_per_mtok, "→", m.pricing.output_per_mtok, "/Mtok")

bot = client.agents.create(name="Ops", model="sonnet")  # or per run: runs.create(..., model="opus")

Today that's the Claude models sonnet, opus, and fable (Fable 5.1 — curated picker; ~2x Opus cost); OpenAI gpt-6-astra (frontier, curated picker) / gpt-5.5 / gpt-5.4 / gpt-5.4-pro / gpt-5.4-mini / gpt-5.4-nano / gpt-5.6-sol / gpt-5.6-terra / gpt-5.6-luna; Google gemini-3.8-flash / gemini-3.7-flash / gemini-3.6-flash / gemma-4-31b / gemma-4-26b; xAI grok-4.6 (curated) / grok-4.5 / grok-4.3; Meta muse-spark-1.3 (no ZDR host — API-only) / muse-glimmer-30b; Tencent hy3; and open-source glm-5.3 / glm-5.3-flash / glm-5.2 / minimax-m3 / minimax-m2-7 / deepseek-v4-pro-0813 / deepseek-v4-pro / deepseek-v4-1-flash (platform default, curated) / deepseek-v4-flash-0731 / deepseek-v3-2 / kimi-k2-7-code / kimi-k2-6 / kimi-k2-thinking / kimi-k3 / qwen3.8-max / qwen3.8-27b / qwen3.8-flash (no ZDR) / qwen3.7-max / qwen3.7-plus (no ZDR) / qwen3.7-flash (no ZDR) / mimo-v2.5-pro / mimo-v2.5 / nemotron-3-120b / nemotron-3-ultra-nvfp4 / nemotron-lightning-3.5-30b / step-3-7-flash. Zero-data-retention support is per model and changes over time, so never assume it from the model name: read zdr_supported on GET /api/v2/models, or filter with ?zdr=true, before sending customer data — claude-fable-5-1 in the curated picker and muse-spark-1.3 / the Qwen flash+plus siblings on the API are the documented exceptions with no ZDR host. models.list() is the live source of truth; omit model to use the default.

Own provider subscription

Connect a personal Claude, Codex, Grok, or Gemini plan under Account → Model connections so matching account-scoped runs bill that provider instead of prepaid credits. The credential never attaches to a run created with user_id.

# Codex / Grok: device code, then poll until connected
auth = client.model_connections.authorize("openai")  # or "xai"
print(auth.authorization_url, auth.user_code)
status = client.model_connections.authorization_status("openai", auth.state)

# Gemini: paste the code from Google (no device code)
auth = client.model_connections.authorize("gemini")
print(auth.authorization_url)  # user_code is None
client.model_connections.complete_authorization("gemini", auth.state, code="...")

print([c.provider for c in client.model_connections.list().data])

Runs

Streaming (default)

for event in client.runs.create(
    message="pull MRR from Stripe, compare to last month, post the delta to #revenue",
    tools=["stripe", "slack"],
):
    match event.type:
        case "text-delta":
            print(event.delta, end="")
        case "tool-call-start":
            print(f"\n  {event.tool_name}")
        case "tool-result-end":
            print(f"  > {event.result[:100]}")
        case "done":
            print(f"\n  {event.stop_reason}")

Non-streaming

run = client.runs.create(message="generate quarterly report", stream=False)
result = client.runs.poll(run.id)  # blocks until complete
print(result.output)

# or use the convenience wrapper
result = client.runs.create_and_wait(message="generate quarterly report")

Context manager

with client.runs.create(message="summarize inbox") as stream:
    for event in stream:
        print(event.type)
print(stream.text)  # full accumulated text

Reply to a run

for event in client.runs.reply(run.id, message="also break it down by region"):
    print(event.type, event.raw)

# or block until complete
result = client.runs.reply_and_wait(run.id, message="also break it down by region")

Stream text only

for chunk in client.runs.stream_text(message="summarize inbox"):
    print(chunk, end="")

Need the run ID or accumulated text after? Use iter_text() instead:

with client.runs.create(message="summarize inbox") as stream:
    for chunk in stream.iter_text():
        print(chunk, end="", flush=True)
print(stream.run_id, stream.text)

Detect a failed stream

A run can fail mid-stream (expired credential, model rate limit, quota). The default iter_text() / stream.text path drops error events, so either opt into raising or check after iterating:

# Raise RunFailedError if the run fails mid-stream
for event in client.runs.create(message="...", raise_on_error=True):
    ...

# Or check without raising
with client.runs.create(message="...") as stream:
    for chunk in stream.iter_text():
        print(chunk, end="")
    if stream.has_errors:
        print("run failed:", stream.errors)

Provider error results are included in stream.errors, even when the stream ends with a completion frame. raise_on_error=True raises RunFailedError for these too.

Resume a dropped stream

If the connection drops mid-run (proxy idle-timeout, network blip), rejoin with the run_id captured from the metadata event. runs.stream(run_id) replays the run's full history then live deltas, so reset any local accumulation on reconnect:

stream = client.runs.create(message="long autonomous task")
run_id = None
try:
    for event in stream:
        run_id = stream.run_id
        ...
except Exception:  # connection dropped mid-run
    if run_id:
        for event in client.runs.stream(run_id):  # re-attach and replay
            ...

The server emits a 15s keepalive on the streaming path so a long-silent tool call doesn't trip the read timeout; raise it for very long runs with M8tes(timeout=...).

Human-in-the-loop

Pass callbacks to wait(). Approval pauses are handled inline: Use PermissionMode constants to avoid string typos.

from m8tes import PermissionMode

run = client.runs.create(
    message="draft and send the weekly report",
    human_in_the_loop=True,
    permission_mode=PermissionMode.APPROVAL,
    task_setup_tools=False,  # keep this run limited to public tools only
    stream=False,
)
run = client.runs.wait(
    run.id,
    on_approval=lambda req: "allow",
    on_question=lambda req: {"Which channel?": "#general"},
)
print(run.output)

Or create and wait in a single call:

run = client.runs.create_and_wait(
    message="draft and send the weekly report",
    human_in_the_loop=True,
    permission_mode=PermissionMode.APPROVAL,
    on_approval=lambda req: "allow",
)

Low-level control

pending = client.runs.permissions(run.id)
client.runs.approve(run.id, request_id="req_123", decision="allow")
client.runs.answer(run.id, answers={"Which channel?": "#general"})

Switch permission mode on an existing run

run = client.runs.update_permission_mode(run.id, permission_mode=PermissionMode.APPROVAL)
print(run.permission_mode)  # "approval"

Switch mode while the run is still active, including awaiting_approval. Switching to PermissionMode.AUTONOMOUS auto-approves pending tool approval requests and resumes a paused tool approval run. AskUserQuestion and plan approvals still wait for client.runs.answer().

Computer use

When your account has sandbox execution enabled, agents run inside a full Linux desktop. No changes to your code — you get the same run API. The agent gains three extra tools automatically: computer (mouse/keyboard/screenshots), bash (shell), and str_replace_based_edit_tool (file editing).

with client.runs.create(
    agent_id=...,
    message="open chromium, go to example.com, and return the page title",
) as stream:
    for event in stream:
        if event.type == "tool_result":
            for block in event.content or []:
                if block.get("type") == "image":
                    # base64 PNG screenshot after each desktop action
                    screenshot_data = block["source"]["data"]
        if event.type == "text-delta":
            print(event.delta, end="")

Extra events in the stream:

Event When
sandbox-connecting Desktop environment starting
sandbox-connected Desktop ready (duration_ms included)

Triggers

# schedule — every weekday at 9am (shortcut on tasks.create, no separate call needed)
task = client.tasks.create(agent_id=..., instructions="...", schedule="0 9 * * 1-5")

# webhook — POST to a URL to trigger runs
task = client.tasks.create(agent_id=..., instructions="...", webhook=True)
print(task.webhook_url)  # POST here to trigger (shown once)

# email — give the agent an inbox at creation time
mate = client.agents.create(name="inbox bot", email_inbox=True)
print(mate.email_address)  # forward emails here

# iMessage — route one BlueBubbles chat to an agent
messages_bot = client.agents.create(
    name="messages bot",
    inbound_imessage_enabled=True,
    imessage_chat_guid="iMessage;-;+15551231234",
)
print(messages_bot.imessage_chat_guid)  # use a dedicated 1:1 chat unless group access is intended

# on demand — run a saved task directly
for event in client.tasks.run(task.id):
    print(event.type, event.raw)

Multi-tenancy

Give each user their own AI agent with isolated memory, tools, and permissions.

# create a user profile
client.users.create(user_id="cust_123", name="Acme Corp", email="admin@acme.com")

# give them their own agent
bot = client.agents.create(
    name="acme assistant",
    tools=["gmail", "slack"],
    user_id="cust_123",
)

# seed their memory
client.memories.create(user_id="cust_123", content="prefers email over slack")

# pre-approve tools
client.permissions.create(user_id="cust_123", tool="gmail")

# run on their behalf — memory, permissions, history, and internal management tools all scoped
run = client.runs.create_and_wait(
    agent_id=bot.id,
    message="check inbox for urgent items",
    user_id="cust_123",
)

The same rule applies to saved tasks and follow-up runs:

task = client.tasks.create(
    agent_id=bot.id,
    instructions="review urgent inbox items",
)

# inherits cust_123 from the scoped agent
run = client.tasks.run(task.id, stream=False)
assert run.user_id == "cust_123"

Apps & connections

Inspect the app catalog first, then use the helper that matches the app's auth type.

apps = client.apps.list(user_id="cust_123")
for app in apps.data:
    print(app.name, app.auth_type, app.connected)

# OAuth app
start = client.apps.connect_oauth(
    "gmail",
    redirect_uri="https://app.example.com/oauth/callback",
    user_id="cust_123",
)
print(start.authorization_url)

# after your redirect handler gets the callback
client.apps.connect_complete("gmail", start.connection_id, user_id="cust_123")

# API key app
client.apps.connect_api_key("gemini", api_key="sk_live_...", user_id="cust_123")
client.apps.disconnect("gemini", user_id="cust_123")

# Platform-provisioned app (auth_type "platform_provisioned", e.g. twilio):
# the platform allocates a dedicated resource (a phone number) for you.
result = client.apps.provision("twilio", user_id="cust_123")
print(result.phone_number)  # "+15551234567"
client.apps.release("twilio", user_id="cust_123")  # release it back

Recursive Teams

Organize Mates into a hierarchy and grant a role across one subtree:

marketing = client.groups.create(name="Marketing")
paid_ads = client.groups.create(name="Paid Ads", parent_id=marketing.id)
google = client.groups.create(name="Google", parent_id=paid_ads.id)
client.agents.update(agent.id, group_id=google.id)

invite = client.groups.invite(marketing.id, email="ada@example.com", role="runner")
members = client.groups.members(google.id)  # includes inherited roles
client.groups.update_member(marketing.id, members.data[0].member_id, role="editor")

New invitations default to editor; choose viewer for read access or runner for read plus run/chat/reply/cancel/approve. Editors can also edit Mates, tasks, documents, and work inside the subtree. Existing grants remain viewer. Roles inherit through child Teams. Editors cannot manage members or roles, self-escalate, reorganize Teams, or move a Mate out of the shared scope.

Team sharing does not make someone an organization member. Runs use the shared Mate owner's bound tools and billing while auditing the human requester separately; credentials stay opaque. Group CRUD accepts user_id for end-user isolation, while membership and invitation methods do not. groups.share() remains the separate legacy bulk operation for direct Mates' visibility.

Resources

Resource Key methods Description
client.agents create list get update delete reset enable_webhook disable_webhook enable_email_inbox disable_email_inbox enable_fetchmail disable_fetchmail Agent personas with tools and instructions
client.agent_templates list Pre-built agent template catalog (slugs for agents.create(from_template=...))
client.runs create stream poll wait create_and_wait reply reply_and_wait stream_text get list cancel retry permissions approve answer update_permission_mode list_files download_file Execute agents and stream results
client.judgments create, get Platform-funded typed judgments, scoped source evidence, idempotent retries, and saved-result retrieval; advisory, not proof or approval
client.audit_logs list Account-scoped API request history
client.tasks create list get update delete run run_and_wait lessons delete_lesson clear_lessons Reusable task definitions (+ lesson curation)
client.tasks.triggers create list delete Schedule, webhook, and email triggers
client.apps list is_connected connect connect_oauth connect_api_key connect_complete provision release list_triggers disconnect Tool catalog and end-user app connections
client.bridges create list get update rotate_secret delete Per-account BlueBubbles (iMessage) bridges
client.groups create list get update delete members update_member remove_member invites invite cancel_invite preview_invite accept_invite share Recursive Teams and inherited viewer, runner, or editor access
client.memories create list delete Per-user persistent memory
client.permissions create list delete Pre-approve tools for end-users
client.users create list get update delete End-user profile management
client.webhooks create list get update delete list_deliveries verify_signature Webhook endpoints and delivery tracking
client.settings get update Account configuration
client.billing usage plans set_overage Run usage, plan catalog, and opt-in overage controls
client.value create_use_case list_use_cases get_use_case update_use_case link_runs create_observation list_observations confirm_observation report Evidence-backed customer outcomes and ROI by inferred use case
client.model_connections list authorize authorization_status complete_authorization cancel_authorization disconnect Account-level Claude, Codex, Grok, and Gemini plans
client.auth get_usage resend_verify Account usage and verification helpers

Pagination

# standard page
page = client.runs.list(limit=50)
for run in page.data:
    print(run.id, run.status)

# auto-paginate through all results
for run in client.runs.list(user_id="customer_123").auto_paging_iter():
    print(run.id, run.status)

Webhooks

# register an endpoint
hook = client.webhooks.create(
    url="https://example.com/hook",
    events=["run.completed", "run.failed"],
)
secret = hook.secret  # save this — only shown once

# verify incoming webhooks (e.g. in Flask/FastAPI)
from m8tes import Webhooks

is_valid = Webhooks.verify_signature(
    body=request.body,
    headers=dict(request.headers),
    secret=secret,
)

Files

files = client.runs.list_files(run_id=42)
for f in files:
    print(f.name, f.size)

content = client.runs.download_file(run_id=42, filename="report.csv")

Error handling

from m8tes import M8tes, NotFoundError, RateLimitError, AuthenticationError

try:
    client.agents.get(999)
except NotFoundError:
    print("agent not found")
except RateLimitError as e:
    print(f"rate limited, retry after {e.retry_after}s")
except AuthenticationError:
    print("invalid API key")

Run-level failures

Exceptions above cover problems reaching the API. A run can also fail upstream — an expired Claude credential, an exhausted plan quota, a model rate limit. By default, create_and_wait() returns the failed run without raising: status is "failed", and run.error_code can hold a machine-readable class (e.g. oauth_revoked, subscription_quota_exhausted, rate_limited). Pass raise_on_error=True to raise RunFailedError, or check the returned status and error code before trusting output:

run = client.runs.create_and_wait(agent_id=mate.id, message="...")
if run.status == "failed" or run.error_code:
    print(f"run failed upstream: {run.error_code} — {run.output}")
else:
    print(run.output)

Configuration

Variable Description Default
M8TES_API_KEY API key for authentication —
M8TES_BASE_URL API endpoint https://api.m8tes.ai/api/v2
client = M8tes(api_key="m8_...", timeout=300)  # custom timeout in seconds

CLI

With SDK 4.32.1+, use the same API key and starter path from your terminal:

m8tes agent task "Say hello" --user-id hello_world --model deepseek-v4-1-flash

Omit the agent ID for a scoped quick-start run; V2 finds or creates the scoped agent. To target an existing agent, add its ID before the message. agent chat also accepts --user-id and --model; replies and resumed runs keep the original run's scope and model.

m8tes auth login                    # authenticate
m8tes auth usage                    # account limits and current usage
m8tes apps connect-api-key gemini KEY
m8tes agent create --non-interactive --name "messages bot" --tools gmail --instructions "Help via iMessage" --enable-imessage --imessage-chat-guid "iMessage;-;+15551231234"
m8tes run set-permission-mode 42 approval
m8tes agent task ID "message"       # run a task
m8tes agent chat ID                 # interactive chat

mate is a permanent alias (m8tes mate task … still works).

m8tes run set-permission-mode also works while a run is paused. Switching to autonomous resumes pending tool approvals, but AskUserQuestion still waits for an explicit answer.

See CLI documentation for all commands and options.

Contributing

Bug reports and feature requests are welcome — open an issue; we review weekly. We don't currently accept external pull requests: this repo is synced from our internal monorepo, so changes land through our own pipeline. If something blocks you, an issue (or support@m8tes.ai) is the fastest path to a fix.

License

MIT — see LICENSE for details. The m8tes name and logo are trademarks of m8tes; the MIT license does not grant trademark rights.

Release files for m8tes 4.41.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for m8tes 4.41.0
File Size Uploaded
m8tes-4.41.0.tar.gz 199.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for m8tes 4.41.0
File Interpreter ABI Platform
m8tes-4.41.0-py3-none-any.whl Python 3 none any Details

Total release size: 421.6 kB

Release files / m8tes-4.41.0.tar.gz

Download URL m8tes-4.41.0.tar.gz
Size 199.2 kB
Tags Source
SHA-256 checksum
How to use checksums
4b0097aaae0509438a1dc5c74ba6594be2ac89b7ce6263fdef0b76d73bf2792a
BLAKE2b-256 checksum
How to use checksums
32992892982d51456497f881dddef3c1057be14d5baa482598b6f13b01ecb7ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / m8tes-4.41.0-py3-none-any.whl

Download URL m8tes-4.41.0-py3-none-any.whl
Size 222.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2011668cff370bc24220e7359bec7320f8229527b5b76cd189bb8bd87ebb3a84
BLAKE2b-256 checksum
How to use checksums
c8b6bf18f832220753cd40948fd68b5667941d16f4223de8d03d480dbe633b6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

4.41.0 This release

2 release files

4.40.0

2 release files

4.39.0

2 release files

4.38.0

2 release files

4.37.0

2 release files

4.36.0

2 release files

4.35.0

2 release files

4.34.0

2 release files

4.33.0

2 release files

4.32.1

2 release files

4.31.0

2 release files

4.30.0

2 release files

4.27.0

2 release files

4.26.0

2 release files

4.25.0

2 release files

4.24.0

2 release files

4.23.0

2 release files

4.22.2

2 release files

4.18.1

2 release files

4.18.0

2 release files

4.17.1

2 release files

4.17.0

2 release files

4.16.0

2 release files

4.15.1

2 release files

4.15.0

2 release files

4.14.0

2 release files

4.10.0

2 release files

4.9.1

2 release files

4.9.0

2 release files

4.8.0

2 release files

4.7.1

2 release files

4.7.0

2 release files

4.6.1

2 release files

4.6.0

2 release files

4.5.0

2 release files

4.4.0

2 release files

4.3.0

2 release files

4.2.0

2 release files

4.1.0

2 release files

4.0.0

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.1

2 release files

3.0.0

2 release files

2.10.0

2 release files

2.9.0

2 release files

2.8.0

2 release files

2.7.3

2 release files

2.7.1

2 release files

2.7.0

2 release files

2.6.0

2 release files

2.5.1

2 release files

2.5.0

2 release files

2.4.0

2 release files

2.3.0

2 release files

2.2.1

2 release files

2.2.0

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.25.0

2 release files

1.24.0

2 release files

1.22.0

2 release files

1.21.0

2 release files

1.20.0

2 release files

1.19.0

2 release files

1.18.0

2 release files

1.17.0

2 release files

1.16.0

2 release files

1.15.0

2 release files

1.14.0

2 release files

1.13.0

2 release files

1.12.1

2 release files

1.12.0

2 release files

1.11.0

2 release files

1.10.0

2 release files

1.9.2

2 release files

1.9.1

2 release files

1.9.0

2 release files

1.8.0

2 release files

1.7.0

2 release files

1.6.0

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page