Skip to content

Bug Report: Thread Messages Not Loading in CopilotKit v2 #54

@julesale

Description

@julesale

Bug Report: Thread Messages Not Loading in CopilotKit v2

Issue Summary

When navigating to a thread page (e.g., /t/[thread_id]), the existing thread messages from LangGraph are not being loaded and displayed in the chat UI, despite the threadId being correctly passed to CopilotChatConfigurationProvider and useAgent.

Environment

  • CopilotKit Version: 1.50.0-beta.4
  • AG-UI LangGraph: 0.0.19
  • Next.js: 16.0.1
  • Framework: React with TypeScript

Expected Behavior

  1. User navigates to /t/abc123 where abc123 is an existing thread with messages
  2. CopilotChatConfigurationProvider receives the threadId
  3. useAgent hook automatically loads existing messages from that thread
  4. Messages appear in the chat UI

Actual Behavior

  • threadId is correctly passed to CopilotChatConfigurationProvider
  • useAgent hook is called with correct agentId
  • No messages are loaded from the thread
  • Chat appears empty despite thread having messages in LangGraph backend

Configuration

Page Setup (/t/[thread_id]/page.tsx)

export default function ThreadPage({ params }: { params: Promise<{ thread_id: string }>; }) {
  const { thread_id } = use(params);
  const setCurrentThread = useStore((state) => state.setCurrentThread);

  useEffect(() => {
    if (thread_id) {
      console.log("Setting thread ID:", thread_id);
      setCurrentThread(thread_id);
    }
  }, [thread_id, setCurrentThread]);

  return (
    <CopilotKitProvider
      runtimeUrl="/api/copilotkit"
      showDevConsole={true}
    >
      <CopilotChatConfigurationProvider
        threadId={thread_id}
        agentId={agent_id}
      >
        <HomeContent />
      </CopilotChatConfigurationProvider>
    </CopilotKitProvider>
  );
}

Chat Component (chat-content.tsx)

export function ChatContent() {
  // Get threadId from CopilotChatConfigurationProvider
  const chatConfig = useCopilotChatConfiguration();
  const threadId = chatConfig?.threadId || useStore((state) => state.currentThread);
  
  console.log("Thread ID from config:", threadId);

  const graphId = process.env.NEXT_PUBLIC_AGENT_ID || "pricing_agent";
  
  // useAgent should automatically pick up threadId from context
  const { agent } = useAgent({ 
    agentId: graphId,
    updates: [UseAgentUpdate.OnMessagesChanged] 
  });

  // Debug logging
  useEffect(() => {
    console.log("Agent messages updated:", agent.messages.length, "messages");
    console.log("Messages:", agent.messages);
  }, [agent.messages]);
  
  // ... rest of component
}

Backend Configuration (/api/copilotkit/[[...slug]]/route.ts)

const runtime = new CopilotRuntime({
  agents: {
    "pricing_agent": new LangGraphAgent({
      deploymentUrl: process.env.LANGGRAPH_DEPLOYMENT_URL || "http://localhost:2024",
      graphId: "pricing_agent",
      langsmithApiKey: process.env.LANGSMITH_API_KEY || ""
    }),
  }
});

const app = createCopilotEndpoint({ 
  runtime, 
  basePath: "/api/copilotkit" 
});

export const GET = handle(app);
export const POST = handle(app);

Console Logs

When navigating to thread page:

Setting thread ID: abc123
Thread ID from config: abc123
CopilotKit: {...}
Agent messages updated: 0 messages
Messages: []

Note: agent.messages always shows as empty array, never populates with thread messages.

What We've Tried

Attempt 1: Manual Message Loading

Added useEffect to manually fetch and set messages:

useEffect(() => {
  const loadThreadMessages = async () => {
    if (!threadId) return;

    const response = await fetch(`/api/langgraph/threads?threadId=${threadId}`);
    const threadState = await response.json();
    const messages = threadState?.values?.messages || [];
    
    if (messages.length > 0) {
      const formattedMessages = messages.map((msg: any) => ({
        id: msg.id || crypto.randomUUID(),
        role: msg.type === "human" ? "user" : 
              msg.type === "ai" ? "assistant" : 
              msg.type || "assistant",
        content: msg.content || "",
      }));
      
      agent.setMessages(formattedMessages);
    }
  };

  loadThreadMessages();
}, [threadId]);

Result: Messages are loaded from API but agent.setMessages() doesn't persist them or trigger re-render.

Attempt 2: Check AgentConfig Interface

Checked if threadId should be passed directly to useAgent:

interface AgentConfig {
    agentId?: string;
    description?: string;
    threadId?: string;  // ← This exists in interface
    initialMessages?: Message[];
    initialState?: State;
    debug?: boolean;
}

Issue: useAgent hook from @copilotkit/react-core/v2 doesn't accept threadId parameter (TypeScript error).

Attempt 3: Using Updates Flag

const { agent } = useAgent({ 
  agentId: graphId,
  updates: [UseAgentUpdate.OnMessagesChanged] 
});

Result: Still no messages loaded.

Questions

  1. Is CopilotChatConfigurationProvider supposed to automatically load thread messages? Or is it just for passing threadId metadata?

  2. Should useAgent automatically fetch messages when threadId changes? Or does this require explicit implementation?

  3. Is there a method on the agent object to explicitly load thread history? We found setMessages but it doesn't seem to work as expected.

  4. Does AG-UI LangGraphAgent integration support thread persistence out of the box? Or does this need custom implementation?

Workaround Needed

Currently, we need a way to:

  1. Load existing messages from a LangGraph thread
  2. Display them in the CopilotKit chat UI
  3. Continue the conversation in that thread context

Additional Context

  • LangGraph Backend: Running at http://localhost:2024
  • Thread API: /api/langgraph/threads?threadId=X returns valid thread state with messages
  • New messages: Work fine when creating new threads
  • Thread creation: New threads are created successfully
  • Thread switching: Problem only occurs when navigating to existing threads

Related Code References

  • Thread Page: src/app/(dashboard)/t/[thread_id]/page.tsx
  • Chat Component: src/components/chat/chat-content.tsx
  • API Route: src/app/api/copilotkit/[[...slug]]/route.ts
  • Backend Config: LangGraph server with AG-UI integration

Screenshots/Logs

Console when navigating to thread with existing messages:

✓ Setting thread ID: abc123
✓ Thread ID from config: abc123  
✓ Loading thread state for: abc123
✓ Thread state loaded: { values: { messages: [5 messages] } }
✓ Messages from thread: 5 [Array with actual messages]
✓ Setting formatted messages: [5 formatted messages]
✗ Agent messages updated: 0 messages  ← Problem: Should be 5
✗ Messages: []  ← Problem: Should contain 5 messages

The thread state is successfully loaded from the backend, messages are formatted correctly, but they never appear in agent.messages.

Impact

  • Severity: High
  • Frequency: Always
  • User Impact: Cannot view or continue existing conversations
  • Workaround Available: No

Requested Solution

Documentation or guidance on the correct way to:

  1. Load and display existing thread messages when using CopilotKit v2 with LangGraph
  2. Properly integrate thread persistence between CopilotKit UI and LangGraph backend
  3. Handle thread navigation and message history in AG-UI integration

Created: December 11, 2024
Reporter: Development Team
Priority: High

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions