Skip to main content

Mesedi Python SDK

Status: v0.5.3. Live on PyPI.

The Mesedi SDK observes autonomous AI agent runs and ships them to the Mesedi backend for failure-class detection and analysis. The v1 surface:

  • mesedi.configure(api_key=...): set up the module-level client
  • @mesedi.wrap: decorate any function as an "agent execution". The SDK records start, completion (or crash), wall-clock duration, and a stable crash signature suitable for grouping identical exceptions.
  • @mesedi.tool: decorate any function as an observed tool call. Emits tool_call events into the surrounding execution context, including the function's docstring (see "Tool descriptions" below).
  • Framework adapters for LangChain, LangGraph, OpenAI Agents SDK, and CrewAI (see below).

Install

pip install mesedi

Quickstart

import mesedi

mesedi.configure(api_key="mesedi_sk_...")

@mesedi.wrap
def run_my_agent(query: str) -> str:
    # ... your agent logic here ...
    return "answer"

run_my_agent("hello")

For local backend development against localhost:8080, pass an explicit base_url=. Otherwise the SDK posts to the Mesedi production backend.

What lands in the backend

For each @wrap-decorated call:

  • On entry: POST /executions with execution_id, status="started", sdk_language="python", sdk_version (from mesedi.__version__).
  • On normal return: PATCH /executions/{id} with status="completed", ended_at, duration_ms.
  • On exception: PATCH /executions/{id} with status="crashed", crash_signature (SHA-256-derived stable hash of exception type + top of traceback), then the original exception is re-raised.

Network failures during observation NEVER block the wrapped function. The SDK is fail-open: a Mesedi outage degrades to invisibility, not to broken production code.

Tool descriptions

@mesedi.tool reads the decorated function's docstring and sends it as tool_description on each tool_call event. Nothing to configure:

@mesedi.tool
def lookup_docs(library: str) -> dict:
    """Look up documentation for a library. Returns the doc snippet."""
    return {"library": library, "snippet": "..."}

Why this exists. A tool's contract has two halves: the shape it returns, and the description the model reads when deciding whether and how to call it. Mesedi's tool_schema_drift detector watches both. When a description changes away from a stable baseline you get a failure group with a signature like lookup_docs:desc:1a2b3c4d, distinct from a return-shape change so you can tell which half moved.

That matters most under MCP, where descriptions come from a third-party server and are not sanitised. It is the mechanism behind CVE-2026-75130 (Context7 MCP server, published 2026-08-18): a compromised server puts instructions in what reads to the model as help text, the agent follows them, and the tool's return shape never changes. Without the description, nothing about that call looks unusual.

Two details worth knowing:

  • The docstring is read at call time, not when the decorator runs. A description swapped at runtime, which is exactly what a compromised MCP server does, is therefore visible.
  • A tool with no docstring omits the field entirely rather than sending an empty string, and description drift never fires for it. Nothing else changes.

Descriptions are truncated at 2000 characters with an inline ...[truncated] marker, and are only ever hashed for comparison.

Optional: hard-halt with local budgets

Cap a single execution across four axes: input tokens, output tokens, wall-clock seconds, and step count. Pass any subset; unset fields impose no limit on that axis. When any budget is exceeded, the SDK raises MesediHalt at the next safe boundary (between LLM calls, tool calls, or explicit checkpoint()s), never mid-call, so try/finally cleanup runs and open resources release.

from mesedi import wrap, Budget

@wrap(budget=Budget(
    max_wall_clock_seconds=600,   # 10 min real time
    max_steps=30,                  # 30 tool/LLM/checkpoint boundaries
    max_tokens_in=200_000,
    max_tokens_out=50_000,
))
def my_agent(query: str):
    ...

When a budget is supplied, the SDK also opens an SSE subscription to GET /executions/{id}/halt-stream. Operators can halt a running execution from the dashboard. If the SSE connection fails (backend unreachable, 4xx/5xx, network partition), the reader logs and returns. The wrapped agent keeps running with local budgets still enforced client-side. Mesedi never decides to halt on its own; operator intent or your own budget rules are the only triggers. MesediHalt inherits from BaseException (not Exception), so broad except Exception handlers do not swallow it.

Framework integrations

If your agent is built on LangChain, LangGraph, the OpenAI Agents SDK, or CrewAI, you don't have to wrap every function with @mesedi.tool by hand. Adapter modules under mesedi.integrations.* translate each framework's native callback or hook surface into Mesedi telemetry. They're optional: importing mesedi itself never requires any framework to be installed.

The pattern is the same across frameworks: your function gets @mesedi.wrap for the execution boundary, and a one-line adapter does the in-execution event emission.

LangChain

pip install mesedi[langchain]
import mesedi
from mesedi.integrations.langchain import MesediCallbackHandler

@mesedi.wrap
def run_agent(question: str) -> str:
    chain = build_chain()
    result = chain.invoke(
        {"input": question},
        config={"callbacks": [MesediCallbackHandler()]},
    )
    return result["output"]

The callback handler subscribes to LangChain's standard on_llm_start / on_llm_end / on_tool_start / on_tool_end (etc.) hooks and emits llm_call and tool_call events with the same wire format as a hand-written mesedi.emit_llm_call() + @mesedi.tool pair. Detectors (drift, identical/similar-call loops, tool-failures, cost-velocity, prompt-injection) see no difference.

LangGraph

LangGraph builds on langchain-core, so the LangGraph handler subclasses the LangChain one. Install the langchain extra alongside LangGraph itself; there is no separate mesedi[langgraph] extra.

pip install mesedi[langchain] langgraph
import mesedi
from mesedi.integrations.langgraph import instrument_langgraph

graph = build_my_graph()              # a CompiledStateGraph
graph = instrument_langgraph(graph)   # patched in place

@mesedi.wrap
def run_my_graph(question: str) -> str:
    result = graph.invoke({"question": question})
    return result["answer"]

instrument_langgraph patches invoke, ainvoke, stream and astream to inject the handler into the callback config, without discarding callbacks you already pass. It returns the same graph object, so re-assigning in place is the intended usage. Alongside llm_call and tool_call it emits a checkpoint at every node entry, carrying the node name and a hash of the canonical state so semantic_loop can catch a graph revisiting the same logical state, plus an agent_handoff when the graph invokes a compiled sub-graph.

Not covered yet: async streaming hooks (astream_events), LangGraph's Checkpointer persistence layer (Mesedi emits parallel to it rather than reading it), and interrupt(), where you bridge to mesedi.pause_for_human yourself.

OpenAI Agents SDK

The adapter implements the SDK's RunHooks interface. There is no Mesedi extra for this one; install the OpenAI Agents SDK itself.

pip install mesedi openai-agents
import mesedi
from agents import Runner
from mesedi.integrations.openai_agents import MesediRunHooks

@mesedi.wrap
async def run_my_agent(question: str) -> str:
    result = await Runner.run(
        triage_agent,
        question,
        hooks=MesediRunHooks(),
    )
    return result.final_output

MesediRunHooks emits a checkpoint on every agent start and end, an agent_handoff on every transfer between agents, and a tool_call per tool invocation.

It does not emit llm_call events: the Agents SDK dispatches model calls through its own runner and exposes no per-call hook. So drift, identical-call and similar-call loops, and cost_velocity, which all read llm_call, do not fire on an OpenAI-Agents-only deployment. For Anthropic-backed runs, adding mesedi.instrument_anthropic() restores that surface.

CrewAI

pip install mesedi[crewai]
import mesedi
from mesedi.integrations.crewai import instrument_crew

@mesedi.wrap
def run_my_crew(question: str) -> str:
    crew = build_crew()
    instrument_crew(crew)
    return str(crew.kickoff(inputs={"question": question}))

instrument_crew is one line that does three things, all idempotent:

  1. Attaches a Mesedi MesediCallbackHandler to each agent's LLM. Same LLM/tool telemetry as the LangChain integration above, because CrewAI uses LangChain under the hood.
  2. Sets crew.step_callback to emit crewai.agent_action / crewai.agent_finish checkpoint events per agent step.
  3. Sets crew.task_callback to emit crewai.task_completed checkpoint events per finished task.

Result: the dashboard timeline shows LLM/tool detail interleaved with CrewAI's higher-level reasoning rhythm.

Releases

This SDK is published to PyPI via OIDC Trusted Publishing from the release-sdk-python.yml GitHub Actions workflow, with no long-lived PYPI_TOKEN secret. Every release carries the PyPI "verified" provenance badge linking it to a specific commit in mesedi-ai/mesedi.

To cut a new release, bump version in pyproject.toml, commit, then:

git tag -a sdk-python-v0.X.Y -m "Release sdk-python v0.X.Y"
git push origin sdk-python-v0.X.Y

The workflow type-checks, builds, validates with twine, and publishes.

Release files for mesedi 0.7.0

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

Source distribution (sdist)

Source distribution for mesedi 0.7.0
File Size Uploaded
mesedi-0.7.0.tar.gz 115.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mesedi 0.7.0
File Interpreter ABI Platform
mesedi-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 253.1 kB

Release files / mesedi-0.7.0.tar.gz

Download URL mesedi-0.7.0.tar.gz
Size 115.7 kB
Tags Source
SHA-256 checksum
How to use checksums
fc87b84dc095b8a2f011ee5b822af97ee58d9878fcbf2678fae896cc7041445e
BLAKE2b-256 checksum
How to use checksums
36b9d763b4f7ce5a362804f353f841de44e7997dd3ae94c13b83bc61fc8adf4b
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 15, 2026.

Transparency log

Release files / mesedi-0.7.0-py3-none-any.whl

Download URL mesedi-0.7.0-py3-none-any.whl
Size 137.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aad79f8f5730faeb17216537896427a2c517e9dd34a27e5507b4650e75fc135b
BLAKE2b-256 checksum
How to use checksums
9d3aabece52377514c2b7a75894e129c0fc7dbc1283147b1c4769ded803b0092
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 15, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

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