Docs / TypeScript SDK

TypeScript SDK reference.

Published to npm as mesedi. Source at mesedi-ai/mesedi/sdk-typescript.

Built on Node 18+ native fetch and AsyncLocalStorage. Zero runtime dependencies. Feature parity with the Python SDK for the v1 surface.

Install

npm install mesedi

configure(opts)

Sets up the module-level client. Call once at process start. For local backend development, pass baseUrl; otherwise the SDK posts to the Mesedi production backend.

import { configure } from "mesedi";

configure({
  apiKey: process.env.MESEDI_API_KEY!,
  // baseUrl: "http://localhost:8080",   // for local dev
});

wrap()

Decorate any async function as an agent execution. The SDK records start, completion (or crash), wall-clock duration, and a stable crash signature so identical errors cluster into a single failure group.

import { wrap } from "mesedi";

const runAgent = wrap(async (query: string) => {
  return "answer";
});

await runAgent("hello");

For each wrap()-decorated call:

  • On entry: POST /executions with status="started", sdk_language="typescript".
  • On normal return: PATCH /executions/{id} with status="completed", duration_ms.
  • On thrown error: PATCH with status="crashed" and a stable crash_signature. The original error is re-thrown with its original stack.

All HTTP is async via a single in-process queue plus a setInterval drainer. Network failures during observation never throw back into the wrapped agent. The SDK is fail-open.

tool()

Wrap any async function as an observed tool call. Emits a tool_call event into the surrounding execution context, with sequence number, tool name, sanitized args, success or failure, and result summary (or exception fields).

import { tool, wrap } from "mesedi";

const searchWeb = tool(
  { name: "search_web" },
  async (q: string) => ["result1", "result2"],
);

const runAgent = wrap(async (query: string) => {
  const results = await searchWeb(query);
  return `found ${results.length} results`;
});

flush()

Blocks until the in-process queue drains. Call at end-of-script in short-lived processes (CLI tools, test suites, cron jobs) where the Node process would exit before the async shipper has shipped.

import { flush } from "mesedi";

await runAgent("hello");
await flush();

Hard-halt (local budgets + SSE remote channel)

Optional. Cap a single execution across four axes: input tokens, output tokens, wall-clock seconds, and step count (tool calls + LLM calls + explicit checkpoint()s). Pass any subset — unset fields impose no limit on that axis. When any budget is exceeded, the SDK throws MesediHalt at the next safe boundary — between LLM calls, tool calls, or checkpoint()s, never mid-call — so your try/finally cleanup runs and open resources release. MesediHalt carries an internal Symbol marker so wrap() detects it even if user code accidentally re-wraps it.

import { wrap } from "mesedi";

const runAgent = wrap(
  {
    budget: {
      maxWallClockSeconds: 600,   // 10 min real time
      maxSteps: 30,                // 30 tool/LLM/checkpoint boundaries
      maxTokensIn: 200_000,
      maxTokensOut: 50_000,
    },
  },
  async (query: string) => { ... },
);

When a budget is supplied, the SDK also opens an SSE subscription to GET /executions/{id}/halt-stream. When an operator clicks Halt on the dashboard, the reader signals the BudgetTracker and the next safe-boundary check throws MesediHalt with trigger: "remote_signal". Mesedi never decides to halt on its own — operator intent (or local budget exhaustion) is always the trigger.

Fail-open by design. If the SSE subscription fails — Mesedi backend unreachable, 4xx/5xx response, network partition — the reader logs and returns. The wrapped agent keeps running with local budgets still enforced client-side. A Mesedi outage cannot break your production agent.

Framework adapters

Five framework adapters ship with the TypeScript SDK. Each is behind an optional peer dependency — installing mesedi pulls in none of them by default, so non-users pay no install cost. Each has its own dedicated page with wire-up examples and callback / event mapping tables.

  • LangChain MesediLangChainCallbackHandler extends BaseCallbackHandler. Attach to any runnable's callbacks: slot; emits llm_call and tool_call for every invocation inside a wrap().
  • LangGraph instrumentLangGraph(graph) attaches the Mesedi handler across every node. Emits checkpoint at each node entry / exit, agent_handoff on sub-graph invocations, plus llm_call and tool_call.
  • OpenAI Agents SDK MesediRunHooks implements the RunHooks interface. Emits checkpoint at every agent enter / exit, agent_handoff between agents, and tool_call per tool invocation.
  • Vercel AI SDK wrapGenerateTextis a drop-in replacement for Vercel's generateText. Emits one llm_call per step and one tool_call per tool invocation, matching the multi-step ReAct wire shape.
  • Mastra MesediExporter plugs into Mastra's Observability config. No wrap()required; Mastra's root spans own the execution boundary. Emits full agent-run, workflow, model, tool, and MCP telemetry.

What's next?

Python SDK reference covers the matching surface for Python and its framework adapters (LangChain, LangGraph, OpenAI Agents, CrewAI).

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.