The chatbot is a LangGraph ReAct agent that enables users to query stored memories conversationally via a CopilotKit sidebar. It runs as a separate LangGraph server process and is connected to the main backend via a CopilotKit proxy.
Frontend (CopilotSidebar)
│
│ WebSocket / HTTP (CopilotKit protocol)
▼
Backend (/copilotkit endpoint)
│
│ copilotRuntimeNodeHttpEndpoint → LangGraphAgent
▼
LangGraph Server (port 2024)
│
│ StateGraph → reactNode (createReactAgent)
▼
ChatOpenAI (gpt-4o-mini)
│
│ Tool calls
▼
cau-ram (RedisAgentMemory singleton)
→ Cloud RAM API
The chatbot runs in a separate LangGraph process (port 2024). The main backend proxies:
- Backend side (
copilotkit-langgraph.ts): Creates aCopilotRuntimewith aLangGraphAgentpointing to the LangGraph deployment URL. The/copilotkitExpress route forwards all requests. - LangGraph side (
graph.ts): Defines and compiles the state graph. Since it's a separate process, it independently initializesRedisAgentMemoryandAppStateon first invocation.
START → reactNode → END
Single-node graph where reactNode wraps a prebuilt createReactAgent:
- Loads dataset config, initializes RAM (if not already done)
- Creates
ChatOpenAILLM instance (temperature: 0) - Builds tools via
createMemoryTools() - On each invocation:
- Builds system prompt from dataset config
- Extracts CopilotKit readables from state (session ID, user ID)
- Prepends system + readable messages to conversation
- Invokes the ReAct agent
- Returns only new messages (slices off input)
const StateAnnotation = Annotation.Root({
...MessagesAnnotation.spec,
copilotkit: Annotation<CopilotKitState>({
reducer: (_, next) => next,
default: () => ({}),
}),
});The copilotkit field carries CopilotKit context (readables, actions) injected by the frontend.
useCopilotReadable({ description: "Active session ID for the current meeting playback", value: sessionId ?? "none" });
useCopilotReadable({ description: "User ID for memory scoping", value: config?.userId ?? "" });These values flow through the CopilotKit protocol into state.copilotkit.context.
const runtime = new CopilotRuntime({
agents: {
default: new LangGraphAgent({
deploymentUrl: ENV.LANGGRAPH_DEPLOYMENT_URL,
graphId: "memoryAgent",
langsmithApiKey: ENV.LANGSMITH_API_KEY,
}),
},
});Uses ExperimentalEmptyAdapter (LLM calls happen in LangGraph, not in the runtime).
Dynamically built from DatasetConfig. Key sections:
- Context: Dataset name, user ID, participants list
- Active Session Context: Explains how CopilotKit readables appear as system messages
- Capabilities: Lists what the agent can access (LTMs, session memory)
- Session vs All-Data Routing: Decision tree for which tool to use:
- Overview of current session →
getMemoryContext - Specific search within session →
searchMemoriesBySession - Cross-session question →
searchMemories - Find a specific meeting →
listSessions→ then use other tools
- Overview of current session →
- Response Rules: Formatting guidelines (cite scope, be concise, use structure)
Five tools available to the ReAct agent:
- Purpose: Semantic search across all LTMs
- When: Broad cross-session questions about facts/preferences/events
- Params:
query(required),memoryType?,topics?,limit?(default: 50) - Scoping: Always filters by
ownerId: userId
- Purpose: Search LTMs linked to a specific session
- When: Questions about a particular meeting
- Params:
sessionId(required),query? - Scoping: Filters by
sessionId
- Purpose: Full hydrated memory prompt (session + LTM combined)
- When: Primary tool for session-scoped questions, overview questions
- Params:
query(required),sessionId?,includeAllLongTermMemories?(default: true) - Calls:
ram.buildMemoryPrompt()internally
- Purpose: Lists all available session IDs
- When: User references a specific meeting by date/name
- Params:
limit?(default: 100)
- Purpose: Get session metadata (event count, owner)
- When: User asks about session details
- Params:
sessionId(required)
{
"graphs": {
"memoryAgent": "./src/chatbot-agent/graph.ts:compiledGraph"
}
}The LangGraph CLI dev server picks up this graph and serves it at http://localhost:2024.
demo-langgraph:
command: npx @langchain/langgraph-cli@1.1.17 dev --port 2024 --host 0.0.0.0
environment:
- OPENAI_API_KEY
- RAM_ENDPOINT
- RAM_API_KEY
- RAM_STORE_ID
- LLM_MODEL
- LANGSMITH_API_KEY
- MEETING_MEMORY_ACTIVE_DATASETThe CLI version is pinned to 1.1.17 to avoid breaking changes in newer versions.
- User types in CopilotKit sidebar
- CopilotKit sends message + readables to backend
/copilotkit - Backend forwards to LangGraph server
- LangGraph builds state with
copilotkitcontext + messages - System prompt + readable messages prepended
- ReAct agent reasons and calls tools (e.g.,
searchMemories) - Tools query cloud RAM via
cau-ram - Agent formulates response
- Response streams back through CopilotKit to sidebar
| Variable | Used For |
|---|---|
OPENAI_API_KEY |
ChatOpenAI LLM in ReAct agent |
LLM_MODEL |
Model selection (default: gpt-4o-mini) |
RAM_ENDPOINT / RAM_API_KEY / RAM_STORE_ID |
Cloud RAM access (tools) |
LANGGRAPH_DEPLOYMENT_URL |
Backend proxy target (default: http://localhost:2024) |
LANGSMITH_API_KEY |
Optional tracing for debugging |
MEETING_MEMORY_ACTIVE_DATASET |
Which dataset config to load |