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

@copilotkit/bot

ActionStoreBotNodeInteractionContext

@copilotkit/bot-slack

ReferencebotTypes

ActionStore

The persistence contract behind inline JSX handlers — action snapshots, cold-path rehydration, the in-memory default, and durability tiers.


Overview

ActionStore is the persistence contract behind inline interaction handlers. When you post JSX with an onClick, the engine mints a content-stable, opaque id for the control — mintId(componentName, path, props), a "ck:" + sha1(…) prefix — and stores an ActionSnapshot describing how to re-derive the handler. What's stamped on the native message is the opaque id plus the control's value prop (serialized — up to 2000 chars on Slack); handler code, other props, and bind() args never leave the process. Don't put secrets in a control's value.

On a click, the ActionRegistry resolves the handler from a hot in-memory cache; on a miss it rehydrates from the store — load the snapshot, re-render the named component with the frozen props, re-walk to the handler's path.

Contract

interface ActionStore {
  put(id: string, snap: ActionSnapshot, ttlMs?: number): Promise<void>;
  get(id: string): Promise<ActionSnapshot | undefined>;
  delete(id: string): Promise<void>;
}

Prop

Type

Prop

Type

Prop

Type

ActionSnapshot

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Prop

Type

Durability tiers

  1. Inline handlers — re-derivable from the component's serializable props alone; nothing extra to persist. This is why components must be pure functions of their props (see renderToIR).
  2. bind(handler, args) — attaches a handler-specific args payload, snapshotted as boundArgs. v1 caveat: the cold path does not yet inject boundArgs on rehydration — after a restart the handler is re-derived from props, so args must currently be derivable from props to survive one (see bind()).
  3. A durable store — required for actions to survive a process restart at all.

The in-memory default

The default is InMemoryActionStore — a Map with optional TTL. It is lost on restart: clicking a button posted before a restart raises ActionExpiredError internally, which createBot swallows rather than crashing the bot — the click is acked but nothing happens, and no message is posted.

A durable store (Redis, a database) is not shipped in v1 — implement the three-method contract against your own backend and pass it in:

const bot = createBot({
  adapters: [slack({ botToken, appToken })],
  actionStore: new RedisActionStore(redisClient), // your implementation
});

Related

  • createBot — the actionStore option
  • bind() — persisting handler-specific args
  • Button — where inline handlers live
570dd39