Langgraph Studio doesn't show Chat tab if graph is built inside a class #369

Closed
opened 2026-02-15 18:16:15 -05:00 by yindo · 20 comments
Owner

Originally created by @shyamal890 on GitHub (Oct 13, 2025).

Checked other resources

  • I added a very descriptive title to this issue.
  • I searched the LangGraph.js documentation with the integrated search.
  • I used the GitHub search to find a similar question and didn't find it.
  • I am sure that this is a bug in LangGraph.js rather than my code.
  • The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package).

Example Code

class AgentTest{
agent: any;

initialize=() =>{

    const MessagesState = Annotation.Root({
        ...MessagesAnnotation.spec, // ← declares the chat "messages" key correctly
        llm_calls: Annotation<number>({
            reducer: (x, y) => (x ?? 0) + (y ?? 0),
            default: () => 0,
        }),
    });

    type MessagesStateType = typeof MessagesState.State;

    const echoNode = async (_state: MessagesStateType) => ({
        messages: [new AIMessage("Hello from the graph!")],
    });

    this.agent = new StateGraph(MessagesState)
        .addNode("echo", echoNode)
        .addEdge(START, "echo")
        .addEdge("echo", END)
        .compile({ checkpointer: new MemorySaver() });

    return this.agent;
}

}

export const graph = new AgentTest().initialize();

Error Message and Stack Trace (if applicable)

Getting following error:

Create a graph with a messages key to chat with

Description

Chat tab doesn't display if the graph is built inside a class.

System Info

ode version: v22.15.0
Operating system: win32 x64
Package manager: npm
Package manager version: N/A

@langchain/core -> @0.3.78, , @"^0.3.78", @">=0.3.58, @">=0.2.31, @">=0.3.68, @">=0.2.21
langsmith -> @0.3.72, , @"^0.3.67"
zod -> @3.25.76, , @"^3.25.32", @"^3.24.1", @"^3.23.8", @4.1.11, @"^4.1.11"
@langchain/langgraph -> @0.4.9, , @"^0.4.9"
@langchain/langgraph-checkpoint -> @0.1.1, , @"^0.1.1"
@langchain/langgraph-sdk -> @0.1.9, , @"~0.1.0"
langchain -> @0.3.35, , @"^0.3.35"

Originally created by @shyamal890 on GitHub (Oct 13, 2025). ### Checked other resources - [x] I added a very descriptive title to this issue. - [x] I searched the LangGraph.js documentation with the integrated search. - [x] I used the GitHub search to find a similar question and didn't find it. - [x] I am sure that this is a bug in LangGraph.js rather than my code. - [x] The bug is not resolved by updating to the latest stable version of LangGraph (or the specific integration package). ### Example Code class AgentTest{ agent: any; initialize=() =>{ const MessagesState = Annotation.Root({ ...MessagesAnnotation.spec, // ← declares the chat "messages" key correctly llm_calls: Annotation<number>({ reducer: (x, y) => (x ?? 0) + (y ?? 0), default: () => 0, }), }); type MessagesStateType = typeof MessagesState.State; const echoNode = async (_state: MessagesStateType) => ({ messages: [new AIMessage("Hello from the graph!")], }); this.agent = new StateGraph(MessagesState) .addNode("echo", echoNode) .addEdge(START, "echo") .addEdge("echo", END) .compile({ checkpointer: new MemorySaver() }); return this.agent; } } export const graph = new AgentTest().initialize(); ### Error Message and Stack Trace (if applicable) Getting following error: Create a graph with a messages key to chat with ### Description Chat tab doesn't display if the graph is built inside a class. ### System Info ode version: v22.15.0 Operating system: win32 x64 Package manager: npm Package manager version: N/A -------------------- @langchain/core -> @0.3.78, , @"^0.3.78", @">=0.3.58, @">=0.2.31, @">=0.3.68, @">=0.2.21 langsmith -> @0.3.72, , @"^0.3.67" zod -> @3.25.76, , @"^3.25.32", @"^3.24.1", @"^3.23.8", @4.1.11, @"^4.1.11" @langchain/langgraph -> @0.4.9, , @"^0.4.9" @langchain/langgraph-checkpoint -> @0.1.1, , @"^0.1.1" @langchain/langgraph-sdk -> @0.1.9, , @"~0.1.0" langchain -> @0.3.35, , @"^0.3.35"
yindo closed this issue 2026-02-15 18:16:15 -05:00
Author
Owner

@jdtzmn commented on GitHub (Nov 6, 2025):

It appears I'm having this issue with TypeScript graphs even when it's not within a class.

The example from https://github.com/langchain-ai/langgraphjs-studio-starter is not allowing the chat tab, even when messages are listed on the bottom:

Image
@jdtzmn commented on GitHub (Nov 6, 2025): It appears I'm having this issue with TypeScript graphs even when it's not within a class. The example from https://github.com/langchain-ai/langgraphjs-studio-starter is not allowing the chat tab, even when `messages` are listed on the bottom: <img width="890" height="989" alt="Image" src="https://github.com/user-attachments/assets/6a0c9fba-ca9d-49d7-b76c-b4c7a0e7c741" />
Author
Owner

@nckhell commented on GitHub (Nov 6, 2025):

Same issue here with a fairly basic agent setup

Image

Setup

import {
  AIMessage,
  BaseMessage,
  SystemMessage,
  ToolMessage,
} from "@langchain/core/messages";
import { ChatOpenAI } from "@langchain/openai";
import { toolsByName } from "./tools";
import { StateGraph, MessagesZodMeta, START, END } from "@langchain/langgraph";
import { registry } from "@langchain/langgraph/zod";
import { z } from "zod/v4";

const model = new ChatOpenAI({
  modelName: "gpt-5-2025-08-07",
});

const tools = Object.values(toolsByName);
const modelWithTools = model.bindTools(tools);

const AgentState = z.object({
  messages: z
    .array(z.custom<BaseMessage>())
    .register(registry, MessagesZodMeta),
  llmCalls: z.number().optional(),
});

const callModel = async (state: z.infer<typeof AgentState>) => {
  return {
    messages: await modelWithTools.invoke([
      new SystemMessage(
        "You are a helpful assistant tasked with performing arithmetic on a set of inputs."
      ),
      ...state.messages,
    ]),
    llmCalls: (state.llmCalls ?? 0) + 1,
  };
};

const toolNode = async (state: z.infer<typeof AgentState>) => {
  const lastMessage = state.messages.at(-1);

  if (lastMessage == null || !AIMessage.isInstance(lastMessage)) {
    return { messages: [] };
  }

  const result: ToolMessage[] = [];
  for (const toolCall of lastMessage.tool_calls ?? []) {
    const tool = toolsByName[toolCall.name];
    if (!tool) {
      throw new Error(`Tool ${toolCall.name} not found`);
    }
    const observation = await tool.invoke(toolCall);
    result.push(observation);
  }

  return { messages: result };
};

const shouldContinue = async (state: z.infer<typeof AgentState>) => {
  const lastMessage = state.messages.at(-1);
  if (lastMessage == null || !AIMessage.isInstance(lastMessage)) return END;

  // If the LLM makes a tool call, then perform an action
  if (lastMessage.tool_calls?.length) {
    return "toolNode";
  }

  // Otherwise, we stop (reply to the user)
  return END;
};

const agent = new StateGraph(AgentState)
  .addNode("agent", callModel)
  .addNode("tools", toolNode)
  .addEdge(START, "agent")
  .addConditionalEdges("agent", shouldContinue, ["tools", END])
  .addEdge("tools", "agent");

export const graph = agent.compile();
@nckhell commented on GitHub (Nov 6, 2025): Same issue here with a fairly basic agent setup <img width="300" alt="Image" src="https://github.com/user-attachments/assets/232c8396-1706-4ab4-baf1-59adb2a03c1f" /> ## Setup ```typescript import { AIMessage, BaseMessage, SystemMessage, ToolMessage, } from "@langchain/core/messages"; import { ChatOpenAI } from "@langchain/openai"; import { toolsByName } from "./tools"; import { StateGraph, MessagesZodMeta, START, END } from "@langchain/langgraph"; import { registry } from "@langchain/langgraph/zod"; import { z } from "zod/v4"; const model = new ChatOpenAI({ modelName: "gpt-5-2025-08-07", }); const tools = Object.values(toolsByName); const modelWithTools = model.bindTools(tools); const AgentState = z.object({ messages: z .array(z.custom<BaseMessage>()) .register(registry, MessagesZodMeta), llmCalls: z.number().optional(), }); const callModel = async (state: z.infer<typeof AgentState>) => { return { messages: await modelWithTools.invoke([ new SystemMessage( "You are a helpful assistant tasked with performing arithmetic on a set of inputs." ), ...state.messages, ]), llmCalls: (state.llmCalls ?? 0) + 1, }; }; const toolNode = async (state: z.infer<typeof AgentState>) => { const lastMessage = state.messages.at(-1); if (lastMessage == null || !AIMessage.isInstance(lastMessage)) { return { messages: [] }; } const result: ToolMessage[] = []; for (const toolCall of lastMessage.tool_calls ?? []) { const tool = toolsByName[toolCall.name]; if (!tool) { throw new Error(`Tool ${toolCall.name} not found`); } const observation = await tool.invoke(toolCall); result.push(observation); } return { messages: result }; }; const shouldContinue = async (state: z.infer<typeof AgentState>) => { const lastMessage = state.messages.at(-1); if (lastMessage == null || !AIMessage.isInstance(lastMessage)) return END; // If the LLM makes a tool call, then perform an action if (lastMessage.tool_calls?.length) { return "toolNode"; } // Otherwise, we stop (reply to the user) return END; }; const agent = new StateGraph(AgentState) .addNode("agent", callModel) .addNode("tools", toolNode) .addEdge(START, "agent") .addConditionalEdges("agent", shouldContinue, ["tools", END]) .addEdge("tools", "agent"); export const graph = agent.compile(); ```
Author
Owner

@adm-robinweston commented on GitHub (Nov 9, 2025):

Same for me. This stopped working a week or so ago

@adm-robinweston commented on GitHub (Nov 9, 2025): Same for me. This stopped working a week or so ago
Author
Owner

@i62navpm commented on GitHub (Nov 19, 2025):

Same issue for me. I'm running the quickstart example and the "Chat" button is still disabled.

import { createAgent, tool } from 'langchain';
import { z } from 'zod';

const getWeather = tool((input: { city: string }): string => `It's always sunny in ${input.city}!`, {
  name: 'get_weather',
  description: 'Get the weather for a given city',
  schema: z.object({
    city: z.string().describe('The city to get the weather for'),
  }),
});

const agent = createAgent({
  model: 'openai:gpt-4o-mini',
  tools: [getWeather],
  systemPrompt: `You are DiscoveryAgent, an agent that helps users discover information using various tools. Always introduce yourself as DiscoveryAgent when responding to user queries.`,
});

export const { graph } = agent;

Image
@i62navpm commented on GitHub (Nov 19, 2025): Same issue for me. I'm running the quickstart example and the "Chat" button is still disabled. ```typescript import { createAgent, tool } from 'langchain'; import { z } from 'zod'; const getWeather = tool((input: { city: string }): string => `It's always sunny in ${input.city}!`, { name: 'get_weather', description: 'Get the weather for a given city', schema: z.object({ city: z.string().describe('The city to get the weather for'), }), }); const agent = createAgent({ model: 'openai:gpt-4o-mini', tools: [getWeather], systemPrompt: `You are DiscoveryAgent, an agent that helps users discover information using various tools. Always introduce yourself as DiscoveryAgent when responding to user queries.`, }); export const { graph } = agent; ``` <img width="1270" height="1636" alt="Image" src="https://github.com/user-attachments/assets/838a3514-c0b2-49c6-9a46-2ca30cd9ba74" />
Author
Owner

@abs-mkl commented on GitHub (Nov 25, 2025):

Any news on this issue? I experience the same issue.

@abs-mkl commented on GitHub (Nov 25, 2025): Any news on this issue? I experience the same issue.
Author
Owner

@alitaghub commented on GitHub (Nov 25, 2025):

Me too

@alitaghub commented on GitHub (Nov 25, 2025): Me too
Author
Owner

@theguywhoburns commented on GitHub (Nov 27, 2025):

Same here, using re-act agent template

@theguywhoburns commented on GitHub (Nov 27, 2025): Same here, using re-act agent template
Author
Owner

@ddewaele commented on GitHub (Nov 27, 2025):

I was setting up a new langgraph project today and noticed the same issue.

I am on the latest versions and had to downgrade langchain to v1.0.3 (was on v1.1.1).

not working

  "dependencies": {
    "@langchain/core": "1.1.0",
    "@langchain/langgraph": "^1.0.2",
    "@langchain/langgraph-cli": "1.0.4",
    "@langchain/openai": "^1.1.3",
    "langchain": "1.1.1",
    "langsmith": "^0.3.82"
  }

working

  "dependencies": {
    "@langchain/core": "1.0.3",
    "@langchain/langgraph": "^1.0.2",
    "@langchain/langgraph-cli": "1.0.4",
    "@langchain/openai": "^1.1.3",
    "langchain": "1.0.3",
    "langsmith": "^0.3.82"
  }
@ddewaele commented on GitHub (Nov 27, 2025): I was setting up a new langgraph project today and noticed the same issue. I am on the latest versions and had to downgrade langchain to v1.0.3 (was on v1.1.1). not working ``` "dependencies": { "@langchain/core": "1.1.0", "@langchain/langgraph": "^1.0.2", "@langchain/langgraph-cli": "1.0.4", "@langchain/openai": "^1.1.3", "langchain": "1.1.1", "langsmith": "^0.3.82" } ``` working ``` "dependencies": { "@langchain/core": "1.0.3", "@langchain/langgraph": "^1.0.2", "@langchain/langgraph-cli": "1.0.4", "@langchain/openai": "^1.1.3", "langchain": "1.0.3", "langsmith": "^0.3.82" } ```
Author
Owner

@wangdongwu commented on GitHub (Nov 30, 2025):

Me too,Is there any solution?

@wangdongwu commented on GitHub (Nov 30, 2025): Me too,Is there any solution?
Author
Owner

@theguywhoburns commented on GitHub (Dec 3, 2025):

I was setting up a new langgraph project today and noticed the same issue.

I am on the latest versions and had to downgrade langchain to v1.0.3 (was on v1.1.1).
working

  "dependencies": {
    "@langchain/core": "1.0.3",
    "@langchain/langgraph": "^1.0.2",
    "@langchain/langgraph-cli": "1.0.4",
    "@langchain/openai": "^1.1.3",
    "langchain": "1.0.3",
    "langsmith": "^0.3.82"
  }

Tried downgrading, did not help, strange...

@theguywhoburns commented on GitHub (Dec 3, 2025): > I was setting up a new langgraph project today and noticed the same issue. > > I am on the latest versions and had to downgrade langchain to v1.0.3 (was on v1.1.1). > working > ``` > "dependencies": { > "@langchain/core": "1.0.3", > "@langchain/langgraph": "^1.0.2", > "@langchain/langgraph-cli": "1.0.4", > "@langchain/openai": "^1.1.3", > "langchain": "1.0.3", > "langsmith": "^0.3.82" > } > ``` Tried downgrading, did not help, strange...
Author
Owner

@slv commented on GitHub (Dec 5, 2025):

Same issue here

    "@langchain/langgraph": "^1.0.4",
    "@langchain/openai": "^1.1.3",
    "langchain": "^1.1.4"
@slv commented on GitHub (Dec 5, 2025): Same issue here ```json "@langchain/langgraph": "^1.0.4", "@langchain/openai": "^1.1.3", "langchain": "^1.1.4" ```
Author
Owner

@realduolaf commented on GitHub (Dec 10, 2025):

Same problem. I guess this is related to the compatibility of zod. I am extremely eager to see this problem solved.

@realduolaf commented on GitHub (Dec 10, 2025): Same problem. I guess this is related to the compatibility of zod. I am extremely eager to see this problem solved.
Author
Owner

@salvatoreolivieri commented on GitHub (Dec 15, 2025):

Same problem... looking forward to seeing how to resolve it. If I find something useful, I will send to you in this thread!

@salvatoreolivieri commented on GitHub (Dec 15, 2025): Same problem... looking forward to seeing how to resolve it. If I find something useful, I will send to you in this thread!
Author
Owner

@d2201 commented on GitHub (Dec 27, 2025):

Workaround

I had to use MessagesZodState from @langchain/langgraph.

To extend the state you'll have to use zod/v3.

This worked for me for "@langchain/langgraph": "^1.0.7"

Example

export const simpleGraph = new StateGraph(MessagesZodState)
  .addNode("responder", () => {
    return {
      messages: [new AIMessage({ content: "I'm not sure what to say." })],
    };
  })
  .addEdge(START, "responder")
  .addEdge("responder", END)
  .compile({
    checkpointer: new MemorySaver(),
  });
Image
@d2201 commented on GitHub (Dec 27, 2025): ## Workaround I had to use `MessagesZodState` from `@langchain/langgraph`. To extend the state you'll have to use `zod/v3`. This worked for me for `"@langchain/langgraph": "^1.0.7"` ## Example ```ts export const simpleGraph = new StateGraph(MessagesZodState) .addNode("responder", () => { return { messages: [new AIMessage({ content: "I'm not sure what to say." })], }; }) .addEdge(START, "responder") .addEdge("responder", END) .compile({ checkpointer: new MemorySaver(), }); ``` <img width="758" height="681" alt="Image" src="https://github.com/user-attachments/assets/d9559f05-fc0e-4023-b8cc-ffddc109be64" />
Author
Owner

@alialaa commented on GitHub (Jan 13, 2026):

Any news on this?

@alialaa commented on GitHub (Jan 13, 2026): Any news on this?
Author
Owner

@alan-tirado commented on GitHub (Jan 20, 2026):

Hey! So whats happening here? Seems like this has been opened for a while and there is no response. Is this something the community can help with? This makes the studio hard to use with TS apps

@alan-tirado commented on GitHub (Jan 20, 2026): Hey! So whats happening here? Seems like this has been opened for a while and there is no response. Is this something the community can help with? This makes the studio hard to use with TS apps
Author
Owner

@samecrowder commented on GitHub (Feb 2, 2026):

hey all, we've fixed this and it should be available as of version 1.1.3!

@samecrowder commented on GitHub (Feb 2, 2026): hey all, we've fixed this and it should be available as of version 1.1.3!
Author
Owner

@leonardo2204 commented on GitHub (Feb 3, 2026):

Hi, @samecrowder
Still not working using like this:

import { MessagesValue } from '@langchain/langgraph';
export const AgentState = new StateSchema({
  messages: MessagesValue,

Anyone got it working?

Image

--- EDIT ---

Bug: StateSchema with Zod v4 breaks Studio Chat tab detection

The problem: When using StateSchema with Zod v4, LangGraph Studio cannot detect the langgraph_type: "messages" metadata and the Chat tab never appears.

Root cause: Studio's schema introspection goes through getInputTypeSchema() → getExtendedChannelSchemas() → getInteropZodObjectShape(). This code path expects the graph's _schemaRuntimeDefinition to be a raw Zod v3/v4 object (z.ZodObject or z4.$ZodObject). However, StateSchema stores a StateSchema instance as _schemaRuntimeDefinition, which is neither — causing getInteropZodObjectShape() to throw "Schema must be an instance of z3.ZodObject or z4.$ZodObject".

Why PR #1932 doesn't fix it: That PR fixed StateSchema.getJsonSchema() (switching WeakMap → Map and including jsonSchemaExtra when base schema is undefined). But Studio never calls getJsonSchema() — it uses getExtendedChannelSchemas() which takes a completely different code path that requires a raw Zod object.

Additional issue: MessagesZodState (the built-in Zod helper) is internally built with Zod v3 (_def-based), so extending it with Zod v4 schemas silently produces an incomplete schema (extended fields don't appear).

Workaround: Define state as a plain z.object() and use withLangGraph() from @langchain/langgraph/zod to attach reducers and metadata to individual fields.

Expected fix: Either StateSchema should produce a _schemaRuntimeDefinition that getInteropZodObjectShape() can handle, or getExtendedChannelSchemas() should be updated to handle StateSchema instances.

@leonardo2204 commented on GitHub (Feb 3, 2026): Hi, @samecrowder Still not working using like this: ```ts import { MessagesValue } from '@langchain/langgraph'; export const AgentState = new StateSchema({ messages: MessagesValue, ``` Anyone got it working? <img width="592" height="508" alt="Image" src="https://github.com/user-attachments/assets/86244d94-7c74-4330-8207-d4367c30a753" /> --- EDIT --- Bug: StateSchema with Zod v4 breaks Studio Chat tab detection The problem: When using StateSchema with Zod v4, LangGraph Studio cannot detect the langgraph_type: "messages" metadata and the Chat tab never appears. Root cause: Studio's schema introspection goes through getInputTypeSchema() → getExtendedChannelSchemas() → getInteropZodObjectShape(). This code path expects the graph's _schemaRuntimeDefinition to be a raw Zod v3/v4 object (z.ZodObject or z4.$ZodObject). However, StateSchema stores a StateSchema instance as _schemaRuntimeDefinition, which is neither — causing getInteropZodObjectShape() to throw "Schema must be an instance of z3.ZodObject or z4.$ZodObject". Why PR #1932 doesn't fix it: That PR fixed StateSchema.getJsonSchema() (switching WeakMap → Map and including jsonSchemaExtra when base schema is undefined). But Studio never calls getJsonSchema() — it uses getExtendedChannelSchemas() which takes a completely different code path that requires a raw Zod object. Additional issue: MessagesZodState (the built-in Zod helper) is internally built with Zod v3 (_def-based), so extending it with Zod v4 schemas silently produces an incomplete schema (extended fields don't appear). Workaround: Define state as a plain z.object() and use withLangGraph() from @langchain/langgraph/zod to attach reducers and metadata to individual fields. Expected fix: Either StateSchema should produce a _schemaRuntimeDefinition that getInteropZodObjectShape() can handle, or getExtendedChannelSchemas() should be updated to handle StateSchema instances.
Author
Owner

@Goldinnovation commented on GitHub (Feb 10, 2026):

Facing the same issue with this approach - import { MessagesValue } from '@langchain/langgraph';
export const AgentState = new StateSchema({
messages: MessagesValue,

@Goldinnovation commented on GitHub (Feb 10, 2026): Facing the same issue with this approach - import { MessagesValue } from '@langchain/langgraph'; export const AgentState = new StateSchema({ messages: MessagesValue,
Author
Owner

@bsarel commented on GitHub (Feb 12, 2026):

Hey folks, ran into the same issue while upgrading to 1.x and wanted to share what worked for us in case it helps.

Even after upgrading to @langchain/langgraph@1.1.4 with the 1.1.3 fix, we still couldn't get the Chat tab to show up when using MessagesValue with StateSchema. After some digging, we found what seems to be two issues (at least in our setup):

1. MessagesValue uses z.custom() under the hood, which doesn't produce JSON Schema

From what we could tell, z.custom() doesn't have a JSON Schema representation, so the messages field ended up with no type: "array" in the schema — and was completely absent from the input_schema. This might be why people are still seeing the issue even after 1.1.3.

2. StateSchema.getInputJsonSchema() doesn't seem to include jsonSchemaExtra

Even after switching away from z.custom(), we noticed that langgraph_type: "messages" was showing up in state_schema and output_schema but not in input_schema. It looks like getInputJsonSchema() doesn't merge jsonSchemaExtra from ReducedValue fields. Studio seems to need it in the input schema too to enable the Chat tab.

What worked for us:

We ended up keeping Annotation.Root() for the state definition (to preserve TypeScript types) and patching the graph's _schemaRuntimeDefinition with a duck-typed schema object that includes langgraph_type: "messages":

const graph = new MyAgent().buildGraph();

// Patch schema so Studio detects the messages key and enables the Chat tab.
// Annotation.Root() doesn't support jsonSchemaExtra, so we attach a
// duck-typed schema definition that mirrors all fields and adds langgraph_type.
(graph as any)._schemaRuntimeDefinition = {
  getJsonSchema: () => ({
    type: 'object',
    properties: {
      messages: { type: 'array', items: {}, langgraph_type: 'messages', default: [] },
      // ... include your other state fields here so they show up in Studio
    },
  }),
  getInputJsonSchema: () => ({
    type: 'object',
    properties: {
      messages: { type: 'array', items: {}, langgraph_type: 'messages' },
      // ... same fields without defaults
    },
  }),
};

export { graph };

Note: We initially tried subclassing StateSchema to override getInputJsonSchema(), but that crashes at runtime with TypeError: Class constructor StateSchema cannot be invoked without 'new' when webpack transpiles to ES5. The duck-typed patch avoids this entirely.

Tested with @langchain/langgraph@1.1.4 + @langchain/langgraph-cli@1.1.13.

Not sure if this is the "right" fix or if there's a simpler way — just sharing what we found. Hope it helps someone!

@bsarel commented on GitHub (Feb 12, 2026): Hey folks, ran into the same issue while upgrading to 1.x and wanted to share what worked for us in case it helps. Even after upgrading to `@langchain/langgraph@1.1.4` with the 1.1.3 fix, we still couldn't get the Chat tab to show up when using `MessagesValue` with `StateSchema`. After some digging, we found what seems to be two issues (at least in our setup): **1. `MessagesValue` uses `z.custom()` under the hood, which doesn't produce JSON Schema** From what we could tell, `z.custom()` doesn't have a JSON Schema representation, so the `messages` field ended up with no `type: "array"` in the schema — and was completely absent from the `input_schema`. This might be why people are still seeing the issue even after 1.1.3. **2. `StateSchema.getInputJsonSchema()` doesn't seem to include `jsonSchemaExtra`** Even after switching away from `z.custom()`, we noticed that `langgraph_type: "messages"` was showing up in `state_schema` and `output_schema` but not in `input_schema`. It looks like `getInputJsonSchema()` doesn't merge `jsonSchemaExtra` from `ReducedValue` fields. Studio seems to need it in the input schema too to enable the Chat tab. **What worked for us:** We ended up keeping `Annotation.Root()` for the state definition (to preserve TypeScript types) and patching the graph's `_schemaRuntimeDefinition` with a duck-typed schema object that includes `langgraph_type: "messages"`: ```typescript const graph = new MyAgent().buildGraph(); // Patch schema so Studio detects the messages key and enables the Chat tab. // Annotation.Root() doesn't support jsonSchemaExtra, so we attach a // duck-typed schema definition that mirrors all fields and adds langgraph_type. (graph as any)._schemaRuntimeDefinition = { getJsonSchema: () => ({ type: 'object', properties: { messages: { type: 'array', items: {}, langgraph_type: 'messages', default: [] }, // ... include your other state fields here so they show up in Studio }, }), getInputJsonSchema: () => ({ type: 'object', properties: { messages: { type: 'array', items: {}, langgraph_type: 'messages' }, // ... same fields without defaults }, }), }; export { graph }; ``` > **Note:** We initially tried subclassing `StateSchema` to override `getInputJsonSchema()`, but that crashes at runtime with `TypeError: Class constructor StateSchema cannot be invoked without 'new'` when webpack transpiles to ES5. The duck-typed patch avoids this entirely. Tested with `@langchain/langgraph@1.1.4` + `@langchain/langgraph-cli@1.1.13`. Not sure if this is the "right" fix or if there's a simpler way — just sharing what we found. Hope it helps someone!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#369