Skip to main content

mubit-sdk

The Python client for Mubit. Version 1.0.6.

Mubit learns from the model calls your agents already make. Send your OpenAI, Anthropic or Gemini calls through Mubit, and it:

  • records each call and groups the calls into tasks;
  • collects and rates training examples for each task;
  • fine-tunes a smaller model for a task and tests it on examples it never trained on;
  • serves a model that passes on a share of the task's traffic first, then on all of it, and rolls it back whenever you ask;
  • forms lessons from the traffic.

You see and control all of this in the console at https://app.mubit.ai. This package lets your code and your agents do the same.

Install

pip install mubit-sdk openai          # add anthropic if you call Claude

openai and anthropic aren't dependencies of this package: install the ones you use. Python 3.10 or newer.

Keys

Mubit uses two kinds of key. You create both in the console at https://app.mubit.ai.

Key Starts with Environment variable What it's for
Inference key mw_ MUBIT_API_KEY Sending model calls through Mubit. Each key belongs to one project.
Management key mwm_ MUBIT_MANAGEMENT_KEY Managing your organization from code: everything under "Manage Mubit from code".

Your code needs the key for the job it does. To send model calls through Mubit, it needs an inference key. To manage Mubit from code, it needs a management key. Code that does both needs both.

Only an admin of your organization can create keys. If you aren't an admin, ask an admin of your organization to create the key for you. The console shows a new key once, so copy it when it appears. If you lose a key, create a new one.

Create an inference key

  1. Sign in at https://app.mubit.ai.
  2. Open the project the key is for. In the sidebar, select Mubit keys.
  3. Select Create key.
  4. Enter a Name, such as the name of your app. Leave Permission on Inference: calls this project.
  5. Select Create key, and copy the key.

The key works for that project only. For another project, create a key in that project.

You can also get an inference key when you create a project: in New project, keep Create an inference key selected. The Connect page has a Create key button too.

Create a management key

  1. Sign in at https://app.mubit.ai.
  2. Open All projects. In the sidebar, under Workspace, select Management keys.
  3. Select Create management key.
  4. Enter a Key name, and choose a Role. The table below shows what each role can do.
  5. Optional: choose a Project scope to limit the key to one project. The default is All projects (organization-wide).
  6. Select Create management key again. Select Copy key, save the key, and select Done.
Role What the key can do
read Read everything except the list of management keys
member Also rate calls, review training examples and import past calls
admin Everything

Set the keys

export MUBIT_API_KEY=mw_...
export MUBIT_MANAGEMENT_KEY=mwm_...

Mubit() reads both keys from the environment. You can also pass them in: Mubit(api_key="mw_...", management_key="mwm_..."). The base URL is https://api.mubit.ai.

Send model calls through Mubit

Your code keeps using the provider's own client. Mubit hands you one that already points at Mubit and carries your inference key. Mubit records each call and forwards it to the provider with the provider key stored for your project. Your calls, the tasks they form and the models trained from them then show in the console.

OpenAI

from mubit import Mubit

client = Mubit()
openai = client.calls.openai()        # a stock openai.OpenAI client

reply = openai.chat.completions.create(
    model="gpt-5-mini",
    messages=[{"role": "user", "content": "Classify this ticket: the invoice total is wrong."}],
)
print(reply.choices[0].message.content)

Anthropic

client.calls.anthropic() gives you a stock anthropic.Anthropic client. You call it exactly as you would call Anthropic directly:

from mubit import Mubit

client = Mubit()
claude = client.calls.anthropic()     # a stock anthropic.Anthropic client

reply = claude.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=512,
    messages=[{"role": "user", "content": "Classify this ticket: the invoice total is wrong."}],
)
print(reply.content[0].text)

Async

AsyncMubit returns the async clients, openai.AsyncOpenAI and anthropic.AsyncAnthropic:

from mubit import AsyncMubit

client = AsyncMubit()
claude = client.calls.anthropic()     # anthropic.AsyncAnthropic

reply = await claude.messages.create(model="claude-sonnet-5-5", max_tokens=512, messages=[...])

Client options

calls.openai() and calls.anthropic() take the provider client's own options, such as timeout, max_retries and default_headers, and pass them through unchanged:

claude = client.calls.anthropic(timeout=30, max_retries=3)

Other providers, or your own client setup

Any provider client works when you point it at Mubit's base URL for that provider and give it your inference key as its API key:

Provider Base URL
OpenAI https://api.mubit.ai/openai/v1
Anthropic https://api.mubit.ai/anthropic
Google Gemini https://api.mubit.ai/gemini
OpenRouter, Groq, Together, Mistral (OpenAI-compatible) https://api.mubit.ai/compat/<provider>/v1, for example https://api.mubit.ai/compat/groq/v1
import os
import anthropic

claude = anthropic.Anthropic(base_url="https://api.mubit.ai/anthropic", api_key=os.environ["MUBIT_API_KEY"])

Neon AI Gateway

Each Neon branch has its own AI Gateway. If a project has a Neon AI Gateway key, Mubit sends the project's OpenAI, Anthropic and Gemini calls to that gateway whenever the project has no key of its own for the provider. Your code stays as it is: it keeps using the base URLs above.

Today, Neon AI Gateway keys are available on the EU shared workspace at https://app.mubit.ai only. Elsewhere the console does not list them.

Add the key in the console. Only an admin of your organization can.

  1. Sign in at https://app.mubit.ai.
  2. Open All projects. In the sidebar, under Workspace, select Provider keys.
  3. Select Add key, and choose Neon AI Gateway as the Provider.
  4. In Gateway URL, enter your branch's AI Gateway URL: https:// and the branch's host, with no path, port, user or query after it, such as https://br-example-123456-api.ai.c-2.us-east-2.aws.neon.tech.
  5. In Token, enter a Neon token that starts nt_live_… and has the ai_gateway:invoke scope.
  6. Select Check and save. Mubit checks the token with your branch's gateway before it saves anything.

For a call on the OpenAI, Anthropic or Gemini base URL, Mubit uses the first of these that exists:

  1. the project's own key for that provider;
  2. the project's Neon AI Gateway key;
  3. Mubit's starter-credit key, if the project has the starter credit.

The OpenAI-compatible base URLs (https://api.mubit.ai/compat/<provider>/v1) never go to Neon. Mubit records a call that goes to Neon under the provider neon, and sends the token only to the gateway URL saved with it.

Manage Mubit from code

With a management key, your code can do everything you do in the console. The one exception is organization members, which you manage in the console.

from mubit import Mubit

client = Mubit()

for task in client.tasks.list():                 # every task, across all pages
    print(task["id"], task["name"], task["stage"])

task_id = "task_triage12"
calls = client.calls.list(task=task_id, limit=20)
client.calls.feedback(calls.data[0]["id"], rating="down", comment="Missed the sales tax line.")

client.tasks.train(task_id)                      # train a new version now

version = client.tasks.versions(task_id).data[0]
client.versions.rollout(version["id"], canary_percent=10)   # serve it on 10% of the task's calls
client.versions.promote(version["id"])           # then on all of them
client.versions.rollback(version["id"])          # or go back to the previous version

What you can do, by area:

Organization and projects

You can Python
See your organization client.org.get()
List and open projects client.projects.list(), client.projects.get(id)
Create, rename and delete a project client.projects.create(name=...), client.projects.rename(id, name=...), client.projects.delete(id)

Keys

You can Python
List, create, rotate and revoke a project's inference keys client.keys.list(project=...), client.keys.create(project=..., name=...), client.keys.rotate(id), client.keys.revoke(id)
List, add, rotate and delete the provider keys Mubit calls providers with client.providers.list(), client.providers.add(...), client.providers.rotate(id, ...), client.providers.delete(id)
List, create, rotate and revoke management keys client.management_keys.list(), client.management_keys.create(name=..., role=...), client.management_keys.rotate(id), client.management_keys.revoke(id)

Calls

You can Python
List calls, filtered by project, task, model, status and time client.calls.list(...)
Open a call client.calls.get(id)
Rate a reply up or down, with a comment or a corrected answer client.calls.feedback(id, rating="up", comment=..., correction=...)
Delete everything stored for one session client.calls.forget_session(session_id)

Tasks

You can Python
List tasks, and open one: its stage, what it waits for and why client.tasks.list(), client.tasks.get(id)
Read a task's timeline client.tasks.timeline(id)
Find out why a task isn't training or serving yet client.tasks.diagnose(id)
Review its training examples: keep or drop each one client.tasks.examples(id), client.tasks.review_example(id, example_id, action=...)
Train a new version now client.tasks.train(id)
Pause and resume a task's learning client.tasks.pause(id), client.tasks.resume(id)
Turn automatic routing to the task's trained models off or on client.tasks.set_serving(id, on=False)
Stop all of a task's trained models at once client.tasks.stop(id, reason=...)

Trained models (versions)

You can Python
List a task's versions, and open one with its test results client.tasks.versions(id), client.versions.get(id)
Run a version silently beside the current model, or serve it on a share of the calls client.versions.rollout(id, shadow_percent=..., canary_percent=...)
Promote, demote or roll back a version client.versions.promote(id), client.versions.demote(id), client.versions.rollback(id)
Read a task's promotion history client.tasks.history(id)

Settings

Your plan sets the outer limits. Within them, you can make a setting stricter or cheaper, but not looser.

You can Python
Read a project's settings, and who set each value client.settings.get(project=...)
Change the project settings you see in the console: approval mode, silent test, partial rollout, live checks, grading, when new versions train, the longest example, how long calls are kept and the pass bar client.settings.update(project=..., ...)
Fine-tuning, per task: base model, retrain schedule, rows needed to train, the daily rating cap and the rating rubric client.tasks.update_settings(id, ...)
Routing, per task: when a trained model takes traffic, the silent-test and partial-rollout shares, the audit rate, and the quality bar it must hold client.tasks.update_settings(id, ...)
Lessons, per project: lesson injection on or off, its token budget, and the daily cap on reflections client.settings.update(project=..., ...)
Spend: a daily cap on audit spend client.settings.update(project=..., ...)
Read the audit of every settings change client.settings.audit(project=...)
Read a task's settings client.tasks.settings(id)

Lessons, imports, usage and activity

You can Python
List and open what Mubit learned client.lessons.list(), client.lessons.get(id)
Import past calls from Langfuse, Braintrust or Logfire, follow the import, or cancel it client.imports.create(...), client.imports.list(), client.imports.cancel(id)
See usage: calls and tokens client.usage.get()
See your balance and credit client.billing.get()
Read a project's activity client.activity.list()
Follow a long-running job, such as a training run or an import client.jobs.get(id), client.jobs.wait(id, timeout=...)

Answers are the API's JSON as Python dicts.

Pages, retries and safe repeats

  • Lists come in pages. A list call returns its first page, as page.data and page.next_cursor. Loop over the result and the client fetches the next pages for you.
  • Busy or failing calls are retried. On a 429 or 5xx answer, the client waits (honouring the server's Retry-After when it sends one) and retries, up to max_retries times (2 by default).
  • A retried write isn't applied twice. Every POST carries an Idempotency-Key header. The client makes one for you, or you can pass your own with idempotency_key=....
  • Async works the same way. AsyncMubit has the same namespaces: page = await client.tasks.list(), or async for task in client.tasks.list():.

Errors

Every error the client raises is a mubit.MubitError, so catching that one class catches everything. To handle a specific case, catch its subclass:

What went wrong Error
No key, or a bad option mubit.ConfigurationError
Mubit couldn't be reached (DNS, connection refused, TLS) mubit.APIConnectionError
The call took too long mubit.APITimeoutError
The request was malformed (400) mubit.BadRequestError
The key is missing or wrong (401) mubit.AuthenticationError
The key isn't allowed to do this (403) mubit.PermissionDeniedError
The thing doesn't exist (404) mubit.NotFoundError
It conflicts with the current state (409), or is gone (410) mubit.ConflictError, mubit.GoneError
The request is too large (413) mubit.PayloadTooLargeError
Too many requests (429), even after the retries mubit.RateLimitError
A server error (500 and other 5xx), or Mubit is unavailable (503) mubit.InternalServerError, mubit.UnavailableError

Errors from the API carry status_code, code (a short reason, such as not_found), request_id (quote it when you contact support), retry_after and body:

import mubit

client = mubit.Mubit()
try:
    client.tasks.get("task_triage12")
except mubit.NotFoundError as err:
    print(err.code, err.request_id)

Errors from model calls you send through Mubit are the provider client's own, for example openai.APIError.

Metadata

Release files for mubit-sdk 1.0.6

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

Source distribution (sdist)

Source distribution for mubit-sdk 1.0.6
File Size Uploaded Provenance Actions
mubit_sdk-1.0.6.tar.gz 374.6 kB Without provenance Details for mubit_sdk-1.0.6.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mubit-sdk 1.0.6
File Interpreter ABI Platform Actions
mubit_sdk-1.0.6-py3-none-any.whl Python 3 none any Details for mubit_sdk-1.0.6-py3-none-any.whl

Total release size: 762.4 kB

Release files / mubit_sdk-1.0.6.tar.gz

Download URL mubit_sdk-1.0.6.tar.gz
Size 374.6 kB
Tags Source
SHA-256 checksum
How to use checksums
57e123dd268f8a888b913b03b90933a9781418d7161ab06d48ccc1ad984caa1c
BLAKE2b-256 checksum
How to use checksums
d9817dc4dbc483099640c1d205bbb05d17ce88ebcdbdf8eeaf5bcd397930c3b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / mubit_sdk-1.0.6-py3-none-any.whl

Download URL mubit_sdk-1.0.6-py3-none-any.whl
Size 387.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
35c0ac3313b6ead63ddc1799c9da1445767e84bb9d1120cc03af533c4ce1ac07
BLAKE2b-256 checksum
How to use checksums
86f789d90943845201b92908dfe540e8a29ac93032ebdf3c6781073fd6f97840
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for mubit-sdk 1.0.6

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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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