Skip to main content
The overmind package instruments your LLM stack over OpenTelemetry and exports spans to Overmind. One init() call captures every supported provider call automatically; run() brackets one agent run; decorators trace the code around the model calls; a few one-line calls declare what the run was asked to do and what it delivered, which is what trace scoring judges.
The base package is the CLI and the OpenAI-compatible inference client. Tracing is the one extra: import overmind; overmind.init() on a bare install raises with the install line to run. There are no other extras.

init()

Call once at process startup, before any LLM call. Idempotent and re-entrant — calling again with more providers enables them without tearing down the tracer. Without an API key it logs once, returns False, and every decorator and helper below becomes a no-op, so the integration is safe to ship in apps where Overmind is optional; set OVERMIND_STRICT_MODE=true to make a missing key raise.
Environment variables: OVERMIND_API_KEY, OVERMIND_API_URL, OVERMIND_SERVICE_NAME, OVERMIND_ENVIRONMENT, OVERMIND_CAPABILITY_ID, OVERMIND_CAPABILITY_NAME, OVERMIND_PROJECT_ID, OVERMIND_STRICT_MODE; OVERMIND_SPAN_FLUSH_INTERVAL_MS (default 2000) and OVERMIND_SPAN_MAX_EXPORT_BATCH_SIZE (default 256) tune the batch exporter. In a synced local repository the SDK reads the project key, API URL, and project id from overmind.toml plus the ignored .overmind/credentials.toml sidecar. Deployments should provide credentials through their runtime secret configuration. After init(), calls made with the OpenAI, Anthropic, Google Gemini, Agno, and LangChain client libraries produce llm_call spans automatically, capturing messages and tool calls, model and request parameters, token usage, latency, and errors. Spans export via a batching OTLP/HTTP exporter to POST {base_url}/api/v1/traces. The resource carries vcs.ref.head.revision, read from the environment or .git/HEAD, so a unit binds to the task contract analysed at that commit.

run() — the run boundary

Every agent execution needs exactly one run boundary. run() is the one scope that covers it: capability identity, the entry-point span (overmind.unit_kind = "run"), the intent, the conversation id, tags, error status, and a flush on exit. Use it as a context manager or as a decorator on the entry point:
As a decorator, every parameter except name also accepts a callable receiving the wrapped call’s arguments, resolved per invocation. The run span carries the function’s code.namespace / code.function.name, so one decoration also satisfies the entry-point anchor capability discovery expects. The return value is not delivered automatically: call deliver() (or the handle’s run.deliver()) inside the unit that produced it. Spans that would start their own trace outside a run boundary are suppressed as orphan fragments (the SDK warns once). If a trace is missing, add the bracket — do not reach for export_orphan_spans.

deliver() — the terminal deliverable

Captures the run’s result on its own child span, stamped overmind.delivery = true. Trace scoring judges this span as the unit’s terminal. grounded_by names the evidence spans the deliverable rests on; when omitted, the environment-provenance spans (tools, retrieval) collected in the current trace are used, so call it inside the run. A KeyboardInterrupt or cancellation flushes the run span before re-raising, so interrupted runs still land.

Tracing your own code

Auto-instrumentation only sees model calls. Wrapping the code around them — tools, retrieval steps, the phases of a run — turns flat spans into a tree that mirrors your agent’s structure, and gives trace scoring the anchors it binds to.

Span types

Decorators

@observe is the general decorator; @entry_point, @workflow, @tool, and @retrieval are typed shortcuts. All work on sync and async functions, record duration and status, and re-raise exceptions after recording them.
Captured payloads are scrubbed automatically: secret-named keys are redacted, base64 or data-URL blobs and byte strings over 256 bytes are replaced with placeholders, and attribute values are coerced to OTLP-safe primitives; text is kept in full. For code that handles credentials, use capture="none" — and prefer masking values before they reach traced functions. normalize_messages is exported for callers that build chat evidence themselves. The span name may be a callable receiving the call’s arguments — for a polymorphic dispatcher, each invocation then emits its own tool span and tool.name follows the resolved action:
Decorate every function capability discovery anchors on. An undecorated anchor emits no code.namespace / code.function.name, so the task it belongs to never binds and its step judges skip it.

Instrumenting a synced repository

When capability sync finds missing telemetry, the get_instrumentation_plan MCP tool returns exact instrumentation tickets from the capability’s task registry. Each ticket names the capability, task, source file and line, required scope, and decorator. Apply those placements verbatim so the resulting spans bind to the synced contracts; the /overmind ensure-tracing command does exactly this. Verification is a bounded, read-only MCP smoke: flush the spans, find the new trace by a correlation value, read it, and hand the spans to verify_instrumentation, which checks capability attribution, nesting, inputs and outputs, usage, and timing without writing traces or scores.

task() — carve a run into units

task(key, unit="turn") makes a phase an independently scored unit bound to a declared task; key is the task’s slug from the capability’s trajectory map. Re-entering the same key re-uses the still-open turn span, so a re-entrant phase (a tool loop, debate rounds) lands in one unit. Without unit, task() only pins the spans inside to that task.
Rules that matter: call deliver() inside the unit that produced the deliverable; internal fan-out, retries, and loop bodies must not declare unit.

capability() — multi-capability agents

capability(name=None, id=None) declares that all work inside belongs to one capability: every span created inside carries overmind.capability.id / .name, and the outer identity is restored on exit. id — the capability’s UUID from the Console — is the binding; a name-only scope labels the spans and leaves them unbound. Entering a different capability (by id) mid-trace is a handoff — the first span of the new scope is stamped as a turn, so the platform scores it as a new unit against that capability’s eval set. Only declared identities are stamped; nothing is created.

start_span() — blocks and loops

A context manager for regions that aren’t whole functions. It opens a child span under whatever span is active and captures nothing automatically — attach metadata via attributes or set_tag().

LangChain / LangGraph

providers=["langchain"] (or "auto") mounts the LangChain instrumentor that ships with overmind[tracing], which covers LangGraph: every chain, model, and tool invocation gets a span with model, token, and cost evidence. For the scoring semantics no instrumentor can know, overmind.integrations.langgraph.bind maps graph nodes to task units — call it on the StateGraph after add_node(), before compile():

Runtime expectations

These declare evidence the platform evaluates server-side; each is a span event on the current run and a no-op before init().
How the platform uses them is on Trace scoring.

Context helpers

All operate on the current span or trace — call them inside a traced function or request handler.

PromptString — explicit prompt structure

Passing prompts as plain strings forces Overmind to infer which parts are template versus dynamic input. PromptString declares that structure, giving capability discovery a stable signal:
Use the same id for logically identical prompts across providers and versions, and Overmind groups them as one capability. Use one PromptString per LLM call — the SDK raises an error if it detects more.

Full example

One trace: the handle_support_query run → lookup_order (tool, environment evidence) → the OpenAI llm_call → the deliver span, attributed to the Support Triage capability, grouped into the user’s session, with the question as its intent. Trace scoring binds it to the capability’s triage task and judges the delivered answer against the eval set.