Open-source TypeScript. Every message, tool call, and response — captured automatically and streamed to Slack, Postgres, or anywhere.
User messages, assistant responses, tool calls, and errors. Captured automatically with one wrapper function.
Watch AI conversations appear in your team's Slack channel as they happen. No dashboard to check.
npm install, add your Slack token, done. MIT licensed TypeScript. No hosted service, no vendor lock-in.
Breadcrumb wraps your AI SDK calls and streams events to any sink.
Configure where traces go — Slack, Postgres, or your own custom sink.
const bc = createBreadcrumb({ sinks: [slackSink({ channel: "#ai-traces" })] });
One function wraps streamText or generateText. No changes to your prompts or tools.
const traced = wrapStreamText(streamText, trace);
Every user message, tool call, and assistant response flows to your sinks in real time.
trace.end(); // → Slack, Postgres, anywhere
A complete API route with the Vercel AI SDK.
import { createBreadcrumb } from "breadcrumb-chat"; import { slackSink } from "breadcrumb-chat/sinks/slack"; import { wrapStreamText } from "breadcrumb-chat/adapters/ai-sdk"; import { streamText } from "ai"; import { openai } from "@ai-sdk/openai"; const bc = createBreadcrumb({ sinks: [slackSink({ token: process.env.SLACK_TOKEN, channel: "#ai-traces" })], }); const trace = await bc.trace({ userId: "u_123" }); const traced = wrapStreamText(streamText, trace); const result = await traced({ model: openai("gpt-4o"), messages, }); result.finishReason.then(() => trace.end()); return result.toDataStreamResponse();
Sinks are pluggable destinations. Use the built-in ones or write your own.
Threaded messages in any channel. See conversations as they happen.
slackSink({ token, channel: "#ai-traces" })
Structured storage for traces. Query conversations with SQL.
postgresSink({ client: db })
In-memory store for development and testing. No setup required.
memorySink()Implement three async methods to send traces to any destination.
{ onTraceStart, onEvent, onTraceEnd }Breadcrumb captures every event type in the conversation lifecycle.
import { createBreadcrumb } from "breadcrumb-chat"; import { slackSink } from "breadcrumb-chat/sinks/slack"; const bc = createBreadcrumb({ sinks: [slackSink({ token: process.env.SLACK_TOKEN, channel: "#ai-traces" })], });
const trace = await bc.trace({ userId: "u_123" }); const traced = wrapStreamText(streamText, trace); const result = await traced({ model: openai("gpt-4o"), messages });