samai-sdk
v0.3.4 · 8 providers · MIT licensed

One API in.
A real agent runtime out.

samai-sdk unifies OpenAI, Anthropic, Gemini, and 5 more providers behind one interface — then adds the parts every team rebuilds anyway: tool calling, MCP, guardrails, handoffs, sessions, RAG, voice, and full tracing.

Get started
your appguardrailanthropic()tool loophandoffguardrailtraced output
run trace — live
model-callclaude-sonnet-4-6 · 340ms
tool-callget_weather({ city: "Tokyo" })
guardrailpii-input · allowed
handoffrouter → specialist
run-completed3 calls · 812 tokens
01 — swap providers, not code

Change one line. Keep every tool, guardrail, and trace.

Every provider — Anthropic, OpenAI, Gemini, Bedrock, Groq, Mistral, Azure OpenAI, or a free local model via Ollama — implements the same interface. Your agent definitions, tools, and guardrails don't know or care which one is running underneath.

See all 8 providers
const client = createClient({
provider: anthropic(...),
});
const result = await generate(client, { model, messages });
// everything below this line — tools, guardrails, handoffs, tracing — stays identical
02 — the runtime, not just the wrapper

Everything a production agent needs, already wired in

Most SDKs stop at the API call. samai-sdk ships the orchestration layer every real agent eventually needs — so you build the agent, not the plumbing underneath it.

Guardrails & approval

Block PII and prompt-injection on input, validate output against a schema, cap spend per session, and gate risky tools behind human approval — fail-closed by default.

Multi-agent handoffs

Define specialist agents and let the model route between them mid-conversation, instead of one sprawling system prompt.

Tool loop, built in

defineTool() with full type inference from a zod or valibot schema. Args are validated before execute() ever runs.

MCP client

createMCPClient() turns any local (stdio) or remote (HTTP/SSE) MCP server's tools into ordinary tools your agent can call.

Sandboxed code execution

An isolated temp dir for an agent to write and run real JS/Python/bash — minimal env, real timeouts, no leaked API keys.

Voice — pipeline, engine & realtime

pipelineVoice({ stt, llm, tts }) composable with any Provider, deterministic ConversationEngine (confidence-gated barge-in), Deepgram/ElevenLabs adapters, WebRTC transport, and useVoiceAgent() — plus createRealtimeSession() over WebSocket.

Sessions & RAG

Redis, SQLite, or in-memory session persistence, plus a retrieval pipeline for grounding agents in your own documents.

Tracing you can read

Every model call, tool call, retry, and handoff recorded to a RunTrace — render it as HTML or export via OpenTelemetry.

Structured output

generateObject() and streamObject() return validated, typed data — with an automatic repair prompt on schema mismatch.

Resilience

withRetry() and withFallback([...]) wrap any provider, plus withConcurrencyLimit() and withRateLimit() to stay under caps.

Resumable runs

Checkpoint after every turn and resume after a crash or process restart — no tool call is ever re-executed.

A real CLI

Scaffold a project, inspect a trace file, or replay a usage ledger — samai-sdk create / trace / usage.

Graph memory

Per-user Neo4j knowledge graph with a background sweep, timestamped/contradiction-aware facts, self-correction, and hybrid feed ranking.

03 — the rest of the toolkit

Full docs for every part of the runtime

MCP, sandboxed code execution, voice, RAG, graph memory, resumable runs, OpenTelemetry export, batch structured output, and framework hooks for React, Vue, and Svelte — all documented, all in the same package.

agent.ts
import { createClient, anthropic, defineAgent, defineTool, runAgent } from "samai-sdk";
import { z } from "zod";

const client = createClient({
  provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),
});

const getWeather = defineTool({
  name: "get_weather",
  description: "Get the current weather for a city",
  parameters: z.object({ city: z.string() }),
  execute: async ({ city }) => `18°C and cloudy in ${city}`,
});

const agent = defineAgent({
  name: "weather_agent",
  instructions: "Answer weather questions using get_weather.",
  model: "claude-sonnet-4-6",
  tools: [getWeather],
});

const result = await runAgent(client, agent, "What's the weather in Nairobi?");
console.log(result.output);
04 — a tool call is 6 lines

Full type inference, zero manual typing

defineTool() infers execute()'s argument types straight from your schema — zod, or any Standard Schema V1 validator like valibot. Args are validated before your code ever runs.

Read about tools & schemas

works the same across all 8 providers

AnthropicOpenAIGoogle GeminiAWS BedrockGroqMistralAzure OpenAIOllama

Wire up your first agent in under 10 minutes

Install the SDK, pick a provider, and follow the quick start — or scaffold a working project straight from the CLI.