CopilotKitDocs
  • Docs
  • Reference
  • Cookbook
Get Enterprise Intelligence free
CopilotKitDocs
DocsReferenceCookbook
DocsReferenceCookbook

Get Started

IntroductionQuickstartCopilotKit CLIBuild with agents

Concepts

ArchitectureGenerative UIWhich Hook for Which JobOSS vs Enterprise Intelligence Platform
Agentic Protocols

Build Chat UIs

Multimodal AttachmentsVoiceReasoning

Build Generative UI

Components as ToolsTool Call RenderingState Rendering
A2UI
MCP Apps

Add Agent Powers

Frontend Tools
Human-in-the-Loop
Sub-AgentsAgent ConfigProgrammatic Control

LangGraph (Python)

ReadablesInterruptsConfigurableSubgraphs

Runtime

Copilot RuntimeRuntime HTTP endpointsUse any model routerAgentRunner and persistenceSelf-managed agentsConnect AG-UI agentsDeploy to any runtimeAuthentication

Observe & Operate

InspectorVS Code Extension

Intelligence Platform

Enterprise Intelligence PlatformCloud-Hosted Enterprise IntelligenceSelf-Hosting Enterprise IntelligenceEnterprise Intelligence ArchitectureThreads & Persistence ArchitectureThreads

Bots

Bots
PersistenceTranscripts

Deploy

AWS AgentCore

Other

Anonymous Telemetry
LangGraph (Python)BotsTranscripts

Transcripts

Give your bot a cross-platform memory that follows users across Slack, Teams, and any other channel — with automatic context injection and GDPR-ready delete.


Where you're starting from: a bot that forgets the user entirely between messages. The agent has no awareness that this Slack user is the same person who asked a related question on Teams yesterday, or what they said there.

Where you're headed: one cross-platform memory indexed by user identity, automatically injected into every agent run, and deletable on request.

Configure identity and transcripts together#

Transcripts are indexed by a user key — a stable, platform-independent identifier you derive from the inbound author. Without an identity resolver the bot can't map a Slack user to a Teams user (or even to their own previous Slack messages under a different thread), so identity and transcripts are configured as a pair:

bot.ts
import { createBot } from "@copilotkit/bot";
import { createRedisStore } from "@copilotkit/bot-store-redis";

const bot = createBot({
  adapters: [/* ... */],
  agent: (threadId) => /* ... */,
  store: {
    adapter: createRedisStore({ url: process.env.REDIS_URL! }),
    // Map any platform's author object to a stable user key.
    // Return null to opt a user out of transcript tracking.
    identity: ({ author }) => author.email ?? null,
    transcripts: {
      retention: "30d",      // auto-delete entries older than 30 days
      maxPerUser: 200,       // keep at most 200 entries per user key
    },
  },
});

The author object is provided by the platform adapter — on Slack it includes the user's Slack profile fields including email if your bot has the users:read.email scope. Use whatever field gives you a stable, cross-platform identifier — email is the most common choice.

Transcripts require a durable store

MemoryStore does support the transcripts API for local development, but entries are lost on restart. Use Redis or PostgreSQL in production so transcript history actually persists. See Persistence for backend setup.

The easy path — runAgent with transcript injection#

Pass transcript: true to thread.runAgent() and the bot handles everything automatically:

  1. Fetches the user's prior messages (up to 50 entries by default, oldest-first).
  2. Injects them into the agent's context, labelled by platform and timestamp.
  3. Appends the current user turn.
  4. Captures the streamed assistant reply and appends it to the transcript.
bot.ts
bot.onMention(async ({ thread }) => {
  await thread.runAgent({ transcript: true }); 
});

To control how many prior messages are injected, pass a limit instead:

await thread.runAgent({ transcript: { limit: 20 } });

Don't also append manually

When transcript: true is set, runAgent appends both the user turn and the assistant reply automatically. Calling bot.transcripts.append() in the same handler doubles the entries. Use one or the other — the automatic path for the common case, the manual API when you need fine-grained control.

What the agent sees — platform-labelled context#

The injected history is formatted so the agent knows which platform each message came from. A user who asked a question on Teams and is now following up on Slack produces context like:

[teams | 2026-06-20T09:14:22Z] User: Can you pull the Q2 numbers from the dashboard?
[teams | 2026-06-20T09:14:35Z] Assistant: Here are the Q2 figures: …
[slack  | 2026-06-22T14:03:10Z] User: Actually, can you do that again but filter to EMEA only?

The agent sees the full cross-platform trail and can reference it naturally — "You asked on Teams last week about Q2 numbers — here's the EMEA slice." Each entry carries both platform and ts so you can build custom UIs, audit logs, or export pipelines on top of the raw data.

Manual control — append, list, and delete#

For cases where runAgent doesn't fit (proactive messages, non-agent flows, GDPR tooling), the full API is on bot.transcripts:

Append a message manually:

await bot.transcripts.append(thread, {
  role: "user",
  content: "Can you check on my open ticket?",
});
// Provide userKey explicitly if you're outside a request context:
await bot.transcripts.append(thread, msg, { userKey: "user@example.com" });

List a user's history (oldest-first, with filters):

const history = await bot.transcripts.list({
  userKey: "user@example.com",
  limit: 50,
  platforms: ["slack", "teams"],  // omit to include all platforms
  roles: ["user"],                // omit to include assistant turns too
  threadId: thread.id,            // omit to include all threads
});

for (const entry of history) {
console.log(`[${entry.platform} | ${entry.ts}] ${entry.role}: ${entry.content}`);
}

Delete all history for a user (GDPR right-to-erasure):

const result = await bot.transcripts.delete({ userKey: "user@example.com" });
console.log(`Deleted ${result.deleted} entries`);

createBot and Thread reference

The identity, transcripts, and runAgent options are documented in full at createBot and Thread.

You've reached point B. The bot now maintains a single cross-platform memory per user. The agent receives labelled history from every platform on every run, users can ask follow-up questions across channels, and you can delete all stored data for a user with one call.

6d9397c