Skip to main content

Modus

Modus Python SDK

PyPI Python versions License: MIT

Official Python client for Modus — your organization's context layer for AI.

What is Modus?

Modus is your organization's context layer: it connects assistants to curated knowledge about your data, systems, and workflows so answers use org-specific context instead of generic guesses.

  • Modus — your org-wide assistant (same capability as the Modus home page)
  • Scopes — published assistants you chat with, each with its own context and tools
  • Workflows — automations that run on a schedule or trigger
  • Context items — curated knowledge Modus composes at runtime when answering

Two clients in one package

modus.Modus() is what most people need. Use it to chat with Modus, run scopes, browse context, and inspect workflow runs — the same things you do in the Modus app day to day.

modus.management.ModusManagement() is for org setup: create, update, and deploy scopes, workflows, and context — the CRUD operations you would use in the Modus UI as an admin.

If you are getting started, use Modus() only. Reach for ModusManagement() when you are automating configuration.

Async variants: AsyncModus and AsyncModusManagement.

Installation

pip install modus-sdk

Requires Python 3.10+.

Getting started

import modus

# Reads MODUS_API_KEY env var, or pass api_key= explicitly
client = modus.Modus()

for scope in client.scopes.list():
    print(scope.name, scope.status)

scope = client.scopes.get("revenue-analysis")
print(scope.name, scope.description)

for item in client.context.items.list():
    print(item.uid, item.context_type, modus.context_item_label(item))

Authentication

Create an API token in the Modus app (Settings → API Tokens on your Modus home page). Prefer an environment variable over hardcoding keys in source:

export MODUS_API_KEY=modus_xxx
client = modus.Modus(api_key="modus_xxx")

Using Modus

Modus vs scopes

Surface SDK Use when
Modus (org-wide) client.modus.* Full-environment assistant — same as the Modus home page
Scope client.scopes.* A specific published scope and its configured context/tools

Use client.modus.chat() for native Modus — not scopes.chat(0) or any other scope id shortcut.

Org-wide Modus assistant

MODEL = "claude-sonnet-5"

result = client.modus.chat("What were our top revenue drivers last quarter?", model=MODEL)
print(result.content, result.thread_id)

follow_up = client.modus.chat(
    "Break that down by region.",
    model=MODEL,
    thread_id=result.thread_id,
)
print(follow_up.content)

with client.modus.chat_stream("Summarize this week", model=MODEL) as stream:
    for chunk in stream.text_stream:
        print(chunk, end="")

ctx = client.modus.get_context("What tables describe customer churn?", limit=10)
print(ctx.original_count, ctx.session_id)

for row in client.modus.conversations.list(kind="modus", page_size=10):
    print(row.thread_id, row.first_message)

Scopes

MODEL = "claude-sonnet-5"

result = client.scopes.chat(scope_id, "Hello", model=MODEL)
print(result.content, result.thread_id)

with client.scopes.chat_stream(scope_id, "Hi", model=MODEL) as stream:
    for chunk in stream.text_stream:
        print(chunk, end="")

Context

for item in client.context.items.list():
    print(item.uid, modus.context_item_label(item))

Workflows

workflow = client.workflows.get(workflow_id)
for run in client.workflows.runs.list(workflow_id, page_size=20):
    print(run.id, run.status)

Workflow chat is not on the public PAT surface. Use client.modus.chat() for org-wide conversation or client.scopes.chat() for a published scope.

Managing your org

from modus.management import ModusManagement

mgmt = ModusManagement()  # reads MODUS_API_KEY
scope = mgmt.scopes.create(name="Analyst", model="claude-sonnet-5")
mgmt.scopes.deploy(scope.id)

# Create returns context_item_id (also available as .uid); list/get use .uid
note = mgmt.context.create_note("Title", "Body")
print(note.context_item_id, note.uid)  # same UUID

upload = mgmt.context.files.upload("report.pdf")
print(upload.upload_id, upload.status)

result = mgmt.context.files.upload_dir("./reports")
print(len(result.uploaded), len(result.failed))

Requires a token with write access to scopes and workflows (same as the Modus UI).

Pagination

List endpoints return a Page[T]. Iterate the current page, or use .auto_paging_iter() for all pages:

for scope in client.scopes.list().auto_paging_iter():
    print(scope.name)

client.modus.conversations.list() accepts kind="modus", "skills", or "all" (default).

Async

import asyncio
import modus

async def main():
    async with modus.AsyncModus() as client:
        result = await client.modus.chat("Hello", model="claude-sonnet-5")
        print(result.content)

        async for scope in client.scopes.list().auto_paging_iter():
            print(scope.name)

asyncio.run(main())

Error handling

try:
    scope = client.scopes.get(999)
except modus.NotFoundError:
    print("Scope not found")
except modus.AuthenticationError:
    print("Check your MODUS_API_KEY")
except modus.RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except modus.ModusError as e:
    print(f"API error {e.status_code}: {e.message}")

Examples

Runnable scripts ship with the package:

  • examples/scripts/quickstart.py — list scopes and context (Modus)
  • examples/scripts/modus_chat.py — buffered and streaming Modus chat, context compose, conversations
  • examples/scripts/chat.py — buffered scope chat with thread follow-up
  • examples/scripts/manage_skill.py — create and deploy a scope (ModusManagement, --write optional)

Optional Streamlit demo: examples/apps/modus_skill_chat/ (streaming vs buffered scope chat side by side).

Docs

Full guides: docs.getmodus.com/guides/sdk (Python page: sdk-python).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

modus_sdk-0.6.0.tar.gz (201.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

modus_sdk-0.6.0-py3-none-any.whl (144.3 kB view details)

Uploaded Python 3

File details

Details for the file modus_sdk-0.6.0.tar.gz.

File metadata

  • Download URL: modus_sdk-0.6.0.tar.gz
  • Upload date:
  • Size: 201.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for modus_sdk-0.6.0.tar.gz
Algorithm Hash digest
SHA256 8fab556163c5c8bdc5808fd5d9fd77e1d986b48a0324de96e070f58b39c8b3b3
MD5 96c011c98a6092500f46b224874fa4d9
BLAKE2b-256 62f6e9f8fb22d41f54aeb68b8098965b8c81affa00bc61eb96f61b1359c2be53

See more details on using hashes here.

File details

Details for the file modus_sdk-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: modus_sdk-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 144.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for modus_sdk-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2b234ff2707064b013451c325e18d660705ff9d0acace1870b80d17af7af74b2
MD5 88500722426c15cd2cc6f9b90def6837
BLAKE2b-256 c87de432dfb4f03a64df0c31694914725964bdb29a3e666cace48b9908047566

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page