I can’t seem to disable the stream from agents. I’ve tried different combinations of streaming: false, disableStreaming: true, and tags: [“nostream”]. The final messages of this agent are not saved to the messages state, since I return an empty state update, but the message chunks are still being streamed to the frontend. This leads to a weird chat behavior where messages appear for a second (as chunks) and then disappear once the stream finishes.
// graph.ts
import {
END,
MessagesAnnotation,
START,
StateGraph,
} from "@langchain/langgraph";
import { autonamer } from "./agents/autonamer.js";
import { supervisor } from "./agents/supervisor.js";
const workflow = new StateGraph(MessagesAnnotation)
// Define nodes
.addNode("supervisor", supervisor)
.addNode("autonamer", autonamer)
// Define edges
.addEdge(START, "supervisor")
.addEdge("supervisor", "autonamer")
.addEdge("autonamer", END);
export const graph = workflow.compile();
// agents/autonamer.ts
import { RunnableConfig } from "@langchain/core/runnables";
import { Command, END } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { createAgent } from "langchain";
import { z } from "zod";
import chatServiceClient from "../clients/chatServiceClient.js";
import env from "../constants/env.js";
import { ensureConfiguration } from "../state/configuration.js";
import { State } from "../state/state.js";
export const SYSTEM_PROMPT = `
You are an autonamer AI that generates short, descriptive titles for chat threads based on their content.
Your titles should be concise (3-5 words), relevant to the main topic of the conversation, and engaging.
Focus on capturing the essence of the discussion in a way that is easy to understand at a glance.
Avoid generic titles; instead, aim for specificity and clarity.
`;
const ResponseFormat = z.object({
name: z.string().describe("The name of the generated title"),
});
const autonamerAgent = createAgent({
systemPrompt: SYSTEM_PROMPT,
name: "Autonamer",
model: new ChatOpenAI({
model: "gpt-4.1-mini",
openAIApiKey: env.OPENAI_API_KEY,
temperature: 0.7,
streaming: false,
disableStreaming: true,
tags: ["nostream"],
}),
responseFormat: ResponseFormat,
});
export async function autonamer(
state: State,
config: RunnableConfig,
): Promise<StateUpdate> {
const configuration = ensureConfiguration(config);
const messages = state.messages;
// Check if only one user message exists
const userMessages = messages.filter((m) => m.type === "human");
if (userMessages.length % 5 === 1) {
const response = await autonamerAgent.invoke({
messages: messages,
});
console.log("Autonamer generated name:", response.structuredResponse.name);
console.log("Full response:", response);
let thread = await chatServiceClient.threads.get(configuration.thread_id);
await chatServiceClient.threads.update(configuration.thread_id, {
...thread,
metadata: { ...thread.metadata, name: response.structuredResponse.name },
});
console.log("Thread name updated successfully.");
}
return {};
}
Here’s the package versions I’m using:
"@langchain/core": "^1.0.4",
"@langchain/langgraph": "^1.0.2",
"@langchain/langgraph-checkpoint-postgres": "^1.0.0",
"@langchain/mcp-adapters": "^1.0.0",
"@langchain/openai": "^1.1.0",
"@langchain/tavily": "^1.0.1",
"langchain": "^1.0.4",
Client Side
On the client-side I’m using useStream. I’ve tried changing the streamMode, but haven’t seen any changes.
const thread = useStream<{ messages: Message[] }>({
apiUrl: import.meta.env.VITE_CHAT_SERVICE_URL,
defaultHeaders: {
Authorization: `Bearer ${token}`,
},
assistantId: "assistant",
threadId,
});
const sendPrompt = async (message: string) => {
thread.submit(
{ messages: [{ type: "human", content: message }] },
);
};
I’ve considered filtering messages on the frontend, but I can’t find any distinguishing key to use. I’ve named each of the agents, but the name doesn’t appear on the message chunks.
[
{
"content": "Hello! What's your name?",
"additional_kwargs": {},
"response_metadata": {},
"id": "d9b2a6d1-6f65-4f96-8c8a-9a13a9fc95f9",
"type": "human"
},
{
"content": "Hello! My name is Helpy. I’m here to help. How can I help?",
"additional_kwargs": {},
"tool_call_chunks": [],
"id": "chatcmpl-CleZLNJvsMp2BLMjNLyoIqAKtchMQ",
"tool_calls": [],
"invalid_tool_calls": [],
"name": "Helpy",
"type": "ai"
},
{
"id": "chatcmpl-CleZMJVPnpGqg7gkRry9Emsg1gmVH",
"content": "{\"name\":\"Introduction and Greeting\"}",
"additional_kwargs": {},
"type": "ai",
"tool_calls": [],
"invalid_tool_calls": [],
"tool_call_chunks": []
}
]