Overmind
Overmind is two things in one package:
- Tracing SDK — drop-in observability for LLM agents. Decorate your code, get structured traces of every LLM call and tool invocation.
- Inference client and CLI —
overmind.Clientcalls models you deployed on Overmind through the OpenAI-compatible API; theovermindcommand scans, syncs, and moves datasets and checkpoints.
Documentation: Overmind guide
Console: console.overmindlab.ai
Install
pip install overmind # CLI (`overmind init`, sync, dataset/model files, optimiser)
pip install "overmind[tracing]" # OpenTelemetry tracing (optional extra)
The default install is the command-line tool. Tracing is a separate extra so an app that already pinned OpenTelemetry does not clash with ours.
uv tool install overmind
# or
pipx install overmind
Quick start (local setup)
export OVERMIND_API_KEY=<your-api-key>
export OVERMIND_API_URL=https://api.overmindlab.ai # or your console API host
pip install overmind
overmind init --ide cursor # or claude | opencode | codex
overmind sync
The pasted account key is a bootstrap credential for the current shell only.
init installs the skill and prepares the selected IDE; sync creates the
project, stores its project-scoped key in .overmind/credentials.toml, and
updates the local MCP config. Reload the IDE once after the first sync.
Then in your coding harness:
/overmind setup # scan → capabilities → evals → overmind.toml → sync
overmind sync # push overmind.toml, then pull reconciled ids
Tracing
Needs pip install "overmind[tracing]". Skip the extra if the app already
pinned OpenTelemetry — use the default install and fan-out (see the telemetry
skill). Wire up once at process start, then annotate the functions you want traced:
import overmind
# Reads OVERMIND_API_KEY or the credential saved by overmind sync. Without a key this logs once
# per process, returns False, and every decorator below becomes a no-op —
# safe to ship.
overmind.init(
service_name="my-agent",
capability_id="<capability-uuid>", # ingest maps traces by this id alone
capability="Support Triage", # display label; never resolves anything
providers="auto", # instrument every installed provider SDK
) # (or name them: providers=["openai", "anthropic"])
@overmind.entry_point() # run root (overmind.unit_kind = "run")
def run(request: dict) -> dict:
overmind.intent(request["question"]) # what the user asked for
answer = think(request)
overmind.deliver(answer) # terminal deliverable, auto-grounded
return answer
@overmind.tool(ignore=("session",)) # tool evidence; session never captured
def search(query: str, session) -> list[dict]: ...
@overmind.observe(type="llm", capture="messages") # full chat evidence
def call_model(messages: list[dict]) -> dict: ...
That is the whole integration: no init guards (everything no-ops without a key), no hand-rolled scrubbing (captured payloads redact secret-named keys and base64 blobs automatically, text is kept in full), and no evidence bookkeeping (deliver() grounds itself in the environment-provenance spans of the run — pass grounded_by=[...] to override). On KeyboardInterrupt/cancellation the entry-point span flushes before re-raising, so interrupted runs still land.
Decorators: entry_point, workflow, tool, retrieval, and the general observe (sync and async). All accept capture= ("auto" scrubbed args/result, "none", "messages"), ignore= (argument names never captured), format_input= / format_output= hooks for custom payload shapes, provenance=, unit=, and capability=. start_span(...) is the context-manager companion; set_tag, set_user, set_conversation_id, and capture_exception annotate the current span Sentry-style.
The span name may be a callable receiving the call's arguments — for polymorphic dispatchers, where one function executes named actions and each invocation must emit its own tool span (tool.name follows the resolved name):
class Tools:
@overmind.tool(name=lambda self, action, **params: action.name)
def act(self, action, **params): # executes navigate / extract / done / ...
...
Spans declare evidence provenance for the platform's evaluation judges: tool and retrieval spans are tagged overmind.provenance = "environment" and LLM spans "agent" automatically; pass provenance= (user / agent / environment / harness) to override. @entry_point spans are run roots (overmind.unit_kind = "run") — one per trace: a run declared inside an open trace resolves to turn. unit="turn" marks an independently scorable decision cycle — each turn becomes one scored task execution. Internal fan-out or iteration spans (parallel sub-queries, retries, loop bodies) must not declare unit; handoffs stamp their own turn automatically. A function span that starts a trace outside any run boundary is an orphan fragment and is not exported by default (init(export_orphan_spans=True) overrides).
The wire-level attribute contract is pinned in docs/tracing-attributes.md; nothing there is renamed. The telemetry skill (skills/overmind/references/telemetry.md) is the integrator's guide — run vs. turn, deliver placement, handoffs, and the anchor-decoration rule. When traces don't show up: init(debug=True) prints the endpoint, identity, enabled instrumentors, and export mode.
Multi-capability agents scope identity with overmind.capability — a context manager or decorator that stamps overmind.capability.id / .name on every span created inside and restores the outer identity on exit (capability="..." on any decorator is shorthand for the name-only scope):
with overmind.capability("DOM Element Locator", id="..."): # id optional
locate(prompt) # every span here belongs to the locator capability
Entering a different capability mid-trace is a handoff: the first span of the new scope is stamped overmind.unit_kind = "turn", so the platform scores it as a new unit against that capability's evals. Only declared identities are stamped — nothing is auto-created. overmind.task("behaviour-slug") optionally pins spans to a declared Behaviour the same way.
Single-capability agents with multiple phases (graph nodes, debate rounds) carve a run into units with task(..., unit="turn") — the scope opens one turn span per behaviour per trace, re-entering the same key re-uses it even when a phase's activity is non-contiguous, and the span closes when the run ends:
with overmind.task("investment-debate", unit="turn"):
... # spans here nest under the behaviour's turn span
overmind.run(...) brackets a whole agent run in one scope — capability identity (args, else OVERMIND_CAPABILITY_ID / OVERMIND_CAPABILITY_NAME), the entry-point run span, intent, conversation id, tags, error status, and a flush on exit. The yielded handle delivers the terminal payload; call it inside the unit that produced it:
with overmind.run(
"trading-run", intent=f"Analyze {ticker}", conversation_id=f"{ticker}:{date}"
) as run:
final_state = app.invoke(state)
with overmind.task("portfolio-manager", unit="turn"):
run.deliver(final_state["final_trade_decision"])
It is also a decorator (sync or async) for method entry points. Every parameter except name accepts a callable receiving the wrapped call's arguments, resolved per invocation, and the run-boundary span carries the function's code.namespace / code.function.name — one decoration covers both the run bracket and a scan-contract anchor. The return value is not auto-delivered; call overmind.deliver() inside the unit that produced it:
class Agent:
@overmind.run(
intent=lambda self, *a, **k: self.task,
conversation_id=lambda self, *a, **k: self.task_id,
)
async def run(self): ...
LangChain / LangGraph
pip install 'overmind[tracing]', then providers=["langchain"] mounts the OpenInference LangChain instrumentor (covers LangGraph): every chain, LLM and tool invocation gets a span with usable model/token/cost evidence. For the scoring semantics no instrumentor can know, overmind.integrations.langgraph.bind maps graph nodes to behaviour turn units — call it on the StateGraph after the add_node calls, before compile():
from overmind.integrations import langgraph as overmind_langgraph
overmind.init(providers=["openai", "langchain"], capability_id="<capability-uuid>")
workflow = build_state_graph()
overmind_langgraph.bind(
workflow,
# Default key per node: slugified node name ("Market Analyst" → "market-analyst").
# Override where the scanned task map groups nodes differently; None opts a node out.
behaviours={
"Bull Researcher": "investment-debate",
"Bear Researcher": "investment-debate",
"Msg Clear Market": None,
},
deliver="Portfolio Manager", # optional: this node's completion delivers its return value
)
app = workflow.compile()
Each node invocation runs inside task(key, unit="turn") (re-entrant phases share one unit) and function-backed nodes carry their code.namespace / code.function.name identity for contract anchoring.
Skills
Use these from Cursor, Codex, or Claude Code to scaffold agents and operate
Overmind without leaving your coding environment. Skills live at the repo-root
skills/ directory so agent installers can pick them up from this
repository (e.g. npx skills add overmind-core/overmind).
overmind skills list --verbose
overmind skills sync overmind
overmind init --ide codex
init prepares each vendor's project-scoped MCP config, leaving any other
configured servers untouched. sync installs the final project key:
--ide |
MCP config | Skill install |
|---|---|---|
cursor |
.cursor/mcp.json |
.cursor/skills |
claude / claude_code |
.mcp.json |
.claude/skills |
opencode |
opencode.json |
.opencode/skills |
codex |
.codex/config.toml |
.agents/skills |
Claude Code reads project MCP servers from a root-level .mcp.json; it does not
read .claude/mcp.json. MCP configs containing the project key and
.overmind/credentials.toml are added to the clone-local Git exclude file and
written with owner-only permissions. Sync refuses to put a key in a tracked
config. Codex loads project configuration only for trusted repositories.
| Skill | What it does |
|---|---|
Overmind |
Instrument tracing, inspect telemetry via MCP, upload datasets, run evals, fine-tune, and optimize. |
Anonymous usage analytics
The SDK and CLI send anonymous product-analytics events to PostHog so we can
see how the package is adopted. Each CLI process emits one cli.invoked event
on exit (command = full redacted argv like overmind skills list,
command_path = nested path like skills list, exit code, duration), via
Typer's call_on_close. Library calls
emit sdk_init / sdk_client_created / sdk_langgraph_bind. When an API key
is available the SDK identifies the user once (cached under ~/.overmind/) so
events join the same PostHog person as the Console.
This is not agent tracing: no prompts, span payloads, API keys, emails, or
dataset contents are included. Customer OTLP traces still go only to your
Overmind project via overmind.init().
Opt out with any of:
export OVERMIND_ANALYTICS_ENABLED=false
# or
export DO_NOT_TRACK=1
Analytics is also off when CI is set in env.
CLI reference
overmind init [OPTIONS] Skills, slash commands, MCP; seed overmind.toml
overmind sync [up|down] Push/pull overmind.toml with the server
overmind chassis [--root PATH] Print the AST chassis digest the local scan uses
overmind dataset upload FILE Upload a local dataset and start a build
(--split PERCENT lands a train and an eval dataset)
overmind dataset export DATASET Download committed rows as JSONL or CSV
overmind connector add TYPE Add a tracing connector from env or a TTY prompt
overmind model download-checkpoint DEPLOYMENT
Download an archived fine-tuned checkpoint
overmind optimise [OPTIONS] SDK loop the /overmind optimise skill drives
overmind skills list [--verbose] List installed/available skills
overmind skills sync <name>... Sync one or more skills to the latest version
Run overmind <command> --help for full flag documentation.
Release files for overmind 0.1.72
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| overmind-0.1.72.tar.gz | 382.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| overmind-0.1.72-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 526.4 kB
Release files / overmind-0.1.72.tar.gz
| Download URL | overmind-0.1.72.tar.gz |
|---|---|
| Size | 382.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54e3880d8f7e4812d6be56b7d574f9314a1c459a9c2cfc183cf920e1e881e6ee
|
|
BLAKE2b-256 checksum How to use checksums |
dd65788d1bd05f9cdd9bdc260b16566c979f84ed2bd0e295c3c362c3d4ba3869
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency logRelease files / overmind-0.1.72-py3-none-any.whl
| Download URL | overmind-0.1.72-py3-none-any.whl |
|---|---|
| Size | 143.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4695c1dcf5011768d4eb6d3abfd8ff8688d32d80e12b4f3c94019ac64b1b12c3
|
|
BLAKE2b-256 checksum How to use checksums |
086a9a2d805eec01ad31b4dfd95194c1a6776a1fa53493a35962b7dfdc6bd4c5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 18, 2026.
Transparency log