Pythonic SDK for the Mantis visualization platform. It talks to the Mantis backend over REST and drives the Mantis frontend through Playwright browser automation.
python -m venv venv && source venv/bin/activate # Windows: .\venv\Scripts\activate
pip install -e . # core (REST only)
pip install -e ".[browser]" # + Playwright browser automation
pip install -e ".[dev]" # + test/lint/type tooling
# only if you installed the browser extra:
python -m playwright install chromiumTwo ways to authenticate:
- Session cookie (user context). Log into Mantis, open devtools → Network, copy the
cookieheader from any authenticated request, and pass it ascookie. Required keys includenext-auth.session-tokenandsessionid. - Internal-service (backend-to-backend). Set
config.internal_user_id(orMANTIS_INTERNAL_USER_ID); the SDK then sendsX-Internal-Service: true+X-Internal-User-Idinstead of a cookie.
MantisClient.from_env() reads MANTIS_HOST, MANTIS_BACKEND_HOST, MANTIS_COOKIE,
MANTIS_BASE_URL, and MANTIS_INTERNAL_USER_ID.
import pandas as pd
from mantis_sdk import MantisClient, ConfigurationManager, DataType, ReducerModels, SpacePrivacy
config = ConfigurationManager().update({
"host": "https://mantisdev.csail.mit.edu",
"domain": "mantisdev.csail.mit.edu",
"backend_host": "https://mantiscluster.csail.mit.edu",
})
client = MantisClient("/api/proxy/", cookie=COOKIE, config=config)
df = pd.DataFrame({
"Symbol": ["AAPL", "GOOGL", "MSFT"] + [f"CO{i}" for i in range(100)],
"Market Cap": [2000, 1500, 1300] + [i * 10 for i in range(100)],
"Description": ["Apple", "Alphabet", "Microsoft"] + [f"Company {i}" for i in range(100)],
})
space = client.spaces.create(
"Stock data", df,
{"Symbol": DataType.Title, "Market Cap": DataType.Numeric, "Description": DataType.Semantic},
reducer=ReducerModels.UMAP, privacy_level=SpacePrivacy.PRIVATE,
show_progress=True,
)
print(space.space_id, space.map_id)
print(space.get_annotations())Local backend must run via Docker for space creation to work (
cd docker && docker compose up -d --build).
| Group | Highlights |
|---|---|
client.spaces |
create(...), from_github(repo_url), get_all(), aopen(space_id) |
client.maps |
list(space_id), list_idea_ids(map_id), get_ideas(ids) |
client.notebooks |
resolve_map_to_project, create, from_map |
client.agents |
session(...), run_sync(...), providers(email), set_provider(email, provider) |
client.annotations |
list(map_id), create(map_id, payload) |
client.search |
cluster_questions(...) (backend route currently disabled) |
Legacy flat methods (create_space, get_spaces, open_space, get_annotations,
getClusterQuestions) still work but emit DeprecationWarning.
create_space now returns a SpaceHandle (a dict subclass, so ["space_id"] still works) with
.list_maps(), .get_annotations(), .points (lazy paginated iterator), .aopen(), .delete().
project_id = client.notebooks.resolve_map_to_project(map_id)
nb = client.notebooks.create(project_id, name="Analysis", user_id=USER_ID)
cell = nb.add_cell("import numpy as np; print(np.arange(5))")
cell.execute()
print(cell.text)
plot = nb.add_cell("import matplotlib.pyplot as plt; plt.plot([1,2,3]); plt.show()")
plot.execute()
open("plot.png", "wb").write(plot.image_png_bytes())
nb.checkpoint("after-plot") # snapshot kernel state
nb.list_checkpoints()Run a coding agent scoped to a space, streaming its output. Two runtime providers:
Provider.OpenCode (the default, available to everyone) and Provider.ClaudeCode
(opt-in — the user must have bedrock_enabled capabilities; the SDK checks this up front and
raises ProviderUnavailableError rather than silently downgrading).
The agent runtime identifies the user by email (set config.user_email or pass user_email=),
not user_id.
from mantis_sdk import Provider
async with client.agents.session(space_id, provider=Provider.OpenCode, user_email=email) as run:
async for ev in run.ask("Summarize the outlier cluster", active_map_id=map_id):
if ev.type == "text": print(ev.text, end="")
elif ev.type == "tool_use": print("→", ev.tool_name)
result = run.result() # full text + events; result.provider asserts the runtime used
# sync convenience
result = client.agents.run_sync("What patterns are here?", space_id, provider=Provider.OpenCode,
user_email=email)
# capability management
client.agents.providers(email) # {providers, default, current}
client.agents.set_provider(email, Provider.ClaudeCode)Event types: text, tool_use, tool_result, thinking, init, typing, complete, fail.
async with await client.spaces.aopen(space_id) as space:
dims = await space.get_available_dimensions()
hits = await space.general_search("inflation", search_type="semantic", limit=10)
await space.add_bag("my bag", [p["id"] for p in hits])
png = await space.render_plot("x", "y")
await space.command("any_executor_name", arg1, arg2) # generic escape hatchDataType.Title, Semantic, Numeric, Categoric, Date, Links, CustomModel, Image,
Geospatial, Coordinate1, Coordinate2, Connection, Vector, Delete. Values mirror the
backend serializer keys exactly (e.g. CustomModel == "custom_model").
All errors derive from MantisError: AuthenticationError, NotFoundError, RateLimitError,
APIStatusError(status_code, body), APIConnectionError, SpaceCreationError,
FeatureUnavailableError, ExecutionError.
See examples/ for runnable scripts.