Docs / Python SDK

Python SDK reference.

Published to PyPI as mesedi. Source at mesedi-ai/mesedi/sdk-python.

Importing mesedi never requires any framework (LangChain, CrewAI, Anthropic) to be installed. Framework integrations live behind optional extras and are tree-shaken out of the base install.

Install

pip install mesedi

configure(api_key=...)

Sets up the module-level client. Call once at process start. For local backend development against localhost:8080, pass an explicit base_url=. Otherwise the SDK posts to the Mesedi production backend.

import os
import mesedi

mesedi.configure(api_key=os.environ["MESEDI_API_KEY"])

# Or, for local dev:
# mesedi.configure(api_key="mesedi_sk_dev_local_only",
#                  base_url="http://localhost:8080")

@mesedi.wrap

Decorate any function as an agent execution. The SDK records start, completion (or crash), wall-clock duration, and a stable crash signature so identical exceptions cluster into a single failure group instead of paging you for every retry.

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

run_my_agent("hello")

For each @wrap-decorated call:

  • On entry: POST /executions with status="started".
  • On normal return: PATCH /executions/{id} with status="completed" and duration_ms.
  • On exception: PATCH with status="crashed" and a crash_signature (SHA-256-derived stable hash of exception type plus top of traceback). The original exception is then re-raised; @wrap does not swallow.

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.

@mesedi.tool

Decorate any function as an observed tool call. Emits a tool_call event into the surrounding execution context, with start time, end time, success or failure, and the exception class on failure. The tool-failures detector consumes these events to flag repeated failures of the same tool inside one execution.

@mesedi.tool
def fetch_user(user_id: str) -> dict:
    return db.query(...)

@mesedi.wrap
def run_my_agent(query: str) -> str:
    user = fetch_user("u_123")   # emits tool_call event
    return summarize(user)

Hard-halt (budgets + remote channel)

Optional. Cap a single execution by token spend, dollar cost, or wall-clock duration. When a budget is exceeded, the SDK raises mesedi.MesediHalt (inherits BaseException, not Exception, so broad except Exception handlers do not swallow it).

from mesedi import HardHaltPolicy

policy = HardHaltPolicy(
    max_usd=2.50,
    max_tokens_in=200_000,
    max_tokens_out=50_000,
    max_wall_seconds=60,
)

@mesedi.wrap(hard_halt=policy)
def run_my_agent(query: str) -> str:
    ...

Hard-halt also supports a remote channel over Server-Sent Events. When an operator clicks Halt on the dashboard, the running SDK sees the signal within a few seconds and raises MesediHalt in the wrapped function. No extra setup beyond enabling hard_halt on the wrapped function.

Anthropic auto-instrumentation

If your agent calls the Anthropic Python SDK directly, Mesedi can patch the client at import time so every messages.create() emits an llm_call event without any other code change. Cost-velocity and drift detectors light up the moment Anthropic calls start flowing.

import mesedi
mesedi.instrument_anthropic()

import anthropic
client = anthropic.Anthropic()

@mesedi.wrap
def run_my_agent(prompt: str) -> str:
    response = client.messages.create(
        model="claude-opus-4-6",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    )
    return response.content[0].text

LangChain adapter

Install the optional extra:

pip install mesedi[langchain]

Pass the callback handler to any LangChain invocation:

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 handler subscribes to LangChain's on_llm_start / on_llm_end / on_tool_start / on_tool_end hooks and emits llm_call and tool_call events with the same wire format as a hand-written @mesedi.tool pair. Detectors see no difference between the two paths.

CrewAI adapter

Install the optional extra:

pip install mesedi[crewai]

One line attaches Mesedi to a Crew:

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_crewis idempotent and does three things: attaches the LangChain callback handler to each agent's LLM (CrewAI uses LangChain under the hood), sets a step callback to emit crewai.agent_action / crewai.agent_finish checkpoint events per agent step, and sets a task callback to emit crewai.task_completedper finished task. The dashboard timeline ends up showing LLM and tool detail interleaved with CrewAI's higher-level reasoning rhythm.

Lower-level building blocks

The decorators are sugar over a lower-level client API. You rarely need it, but it's there:

  • mesedi.MesediClient: the HTTP client under configure().
  • mesedi.Event, mesedi.EventType: build event payloads directly.
  • mesedi.Execution, mesedi.Status: build execution payloads directly.
  • mesedi.flush(timeout=5.0): block until the background shipper drains. Useful in test suites and short-lived scripts where the process exits before the async shipper has shipped.

What's next?

TypeScript SDK reference covers the matching surface for Node and the Vercel AI SDK adapter.

HTTP API reference covers what the SDK posts on the wire, so you can instrument from any language.

Failure classes and playbooks explains what each detector is looking for in the telemetry the SDK ships.