Back to Copilotkit

Manually emitting messages

showcase/shell-docs/src/content/docs/integrations/langgraph/advanced/emit-messages.mdx

1.57.04.3 KB
Original Source

While most agent interactions happen automatically through shared state updates as the agent runs, you can also manually send messages from within your agent code to provide immediate feedback to users.

<video src="https://cdn.copilotkit.ai/docs/copilotkit/images/coagents/emit-messages.mp4" className="rounded-lg shadow-xl" loop playsInline controls autoPlay muted /> <Callout> This video shows the result of npx copilotkit@latest init with the implementation section applied to it! </Callout>

What is this?

In LangGraph, messages are only emitted when a node is completed. CopilotKit allows you to manually emit messages in the middle of a node's execution to provide immediate feedback to the user.

When should I use this?

Manually emitted messages are great for when you don't want to wait for the node to complete and you:

  • Have a long running task that you want to provide feedback on
  • Want to provide a status update to the user
  • Want to provide a warning or error message

Implementation

<Steps> <Step> ### Run and connect your agent <RunAndConnect /> </Step> <Step> ### Install the CopilotKit SDK <InstallSDKSnippet/> </Step> <Step> ### Manually emit a message The `copilotkit_emit_message` method allows you to emit messages early in a node's execution to communicate status updates to the user. This is particularly useful for long running tasks.
    <Tabs groupId="language_langgraph_agent" items={['Python', 'TypeScript']} default="Python" persist>
        <Tab value="Python">
            ```python
            from langchain_core.messages import SystemMessage, AIMessage
            from langchain_openai import ChatOpenAI
            from langchain_core.runnables import RunnableConfig
            from copilotkit.langgraph import copilotkit_emit_message # [!code highlight]
            # ...

            async def chat_node(state: AgentState, config: RunnableConfig):
                model = ChatOpenAI(model="gpt-5.4")

                # [!code highlight:2]
                intermediate_message = "Thinking really hard..."
                await copilotkit_emit_message(config, intermediate_message)

                # simulate a long running task
                await asyncio.sleep(2)

                response = await model.ainvoke([
                    SystemMessage(content="You are a helpful assistant."),
                    *state["messages"]
                ], config)

                return Command(
                    goto=END,
                    update={
                        # Make sure to include the emitted message in the messages history # [!code highlight:2]
                        "messages": [AIMessage(content=intermediate_message), response]
                    }
                )
            ```
        </Tab>
        <Tab value="TypeScript">
            ```typescript
            // ...

            async function chat_node(state: AgentState, config: RunnableConfig) {
                const model = new ChatOpenAI({ model: "gpt-5.4" });

                // [!code highlight:2]
                const intermediateMessage = "Thinking really hard...";
                await copilotkitEmitMessage(config, intermediateMessage);

                // simulate a long-running task
                await new Promise(resolve => setTimeout(resolve, 2000));

                const response = await model.invoke([
                    new SystemMessage({content: "You are a helpful assistant."}),
                    ...state.messages
                ], config);

                return {
                    // [!code highlight:2]
                    // Make sure to include the emitted message in the messages history
                    messages: [new AIMessage(intermediateMessage), response],
                };
            }
            ```
        </Tab>
    </Tabs>
</Step>
<Step>
    ### Give it a try!
    Now when you talk to your agent you'll notice that it immediately responds with the message "Thinking really hard..."
    before giving you a response 2 seconds later.
</Step>
</Steps>