Langgraph / InternalAnnotation typing issue #357

Open
opened 2026-02-15 18:16:09 -05:00 by yindo · 3 comments
Owner

Originally created by @hitmands on GitHub (Sep 11, 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

const PrivateAnnotation = Annotation.Root({
  ...MessagesAnnotation.spec,
  count: Annotation<number>,
});

type State = typeof PrivateAnnotation.State;

const graph = new StateGraph(MessagesAnnotation);

graph
  .addNode('a', (state: State) => ({ count: 5 }), { input: PrivateAnnotation })
  .addNode('b', (state: State) => state, { input: PrivateAnnotation })
  .addNode('c', (state: State) => state, { input: PrivateAnnotation })
;

graph
  .addEdge('__start__', 'a')

  // Cannot be typed, although the private state is passed.
  .addConditionalEdge('a', (state: State) => random() > state.count ? 'b' : 'c');

graph.compile();

Error Message and Stack Trace (if applicable)

Type 'StateType<{ messages: BinaryOperatorAggregate<BaseMessage[], Messages>; }>' is missing the following properties from ...

Description

In scenarios like the Supervisor pattern, subgraphs are required to share the same parent-graph annotation... Although, it's useful for some subgraphs to also have an internal state. This is possible and it works fine, but it's not typesafe.

System Info

{
  "@langchain/core": "^0.3.75",
  "@langchain/langgraph": "^0.4.9",
  "@langchain/langgraph-checkpoint": "^0.1.1",
  "@langchain/langgraph-supervisor": "^0.0.19",
  "@langchain/mcp-adapters": "^0.6.0",
  "@langchain/openai": "0.6.11",
}
Originally created by @hitmands on GitHub (Sep 11, 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 ```ts const PrivateAnnotation = Annotation.Root({ ...MessagesAnnotation.spec, count: Annotation<number>, }); type State = typeof PrivateAnnotation.State; const graph = new StateGraph(MessagesAnnotation); graph .addNode('a', (state: State) => ({ count: 5 }), { input: PrivateAnnotation }) .addNode('b', (state: State) => state, { input: PrivateAnnotation }) .addNode('c', (state: State) => state, { input: PrivateAnnotation }) ; graph .addEdge('__start__', 'a') // Cannot be typed, although the private state is passed. .addConditionalEdge('a', (state: State) => random() > state.count ? 'b' : 'c'); graph.compile(); ``` ### Error Message and Stack Trace (if applicable) ```shell Type 'StateType<{ messages: BinaryOperatorAggregate<BaseMessage[], Messages>; }>' is missing the following properties from ... ``` ### Description In scenarios like the Supervisor pattern, subgraphs are required to share the same parent-graph annotation... Although, it's useful for some subgraphs to also have an internal state. This is possible and it works fine, but **it's not typesafe**. ### System Info ```json { "@langchain/core": "^0.3.75", "@langchain/langgraph": "^0.4.9", "@langchain/langgraph-checkpoint": "^0.1.1", "@langchain/langgraph-supervisor": "^0.0.19", "@langchain/mcp-adapters": "^0.6.0", "@langchain/openai": "0.6.11", } ```
yindo added the bug label 2026-02-15 18:16:09 -05:00
Author
Owner

@SunHuawei commented on GitHub (Sep 26, 2025):

Hi — I’m trying to get involved in the LangChain community. This is the first bug I’m looking at.

I wasn’t able to reproduce your issue, but I found a couple of other problems:

  1. Argument of type '"a"' is not assignable to parameter of type '"__start__" | "__end__"'.ts(2345)
  2. Property 'addConditionalEdge' does not exist on type 'StateGraph<{ count: { (): LastValue<number>; (annotation: SingleReducer<number, number>): BinaryOperatorAggregate<number, number>; Root: <S extends StateDefinition>(sd: S) => AnnotationRoot<...>; }; messages: BinaryOperatorAggregate<...>; }, ... 6 more ..., unknown>'. Did you mean 'addConditionalEdges'?ts(2551) graph.d.ts(56, 5): 'addConditionalEdges' is declared here.

So I modified your code accordingly and tested — it now passes npx tsc and npm tsx app.ts.

import { Annotation, MessagesAnnotation, StateGraph } from "@langchain/langgraph";

function random() {
  return Math.random();
}

const PrivateAnnotation = Annotation.Root({
  ...MessagesAnnotation.spec,
  count: Annotation<number>,
});

type State = typeof PrivateAnnotation.State;

const graph = new StateGraph({
  stateSchema: PrivateAnnotation,
  input: MessagesAnnotation,
  output: MessagesAnnotation,
});

graph
  .addNode('a', (state: State) => ({ count: 5 }), { input: PrivateAnnotation })
  .addNode('b', (state: State) => state, { input: PrivateAnnotation })
  .addNode('c', (state: State) => state, { input: PrivateAnnotation })
  .addEdge('__start__', 'a') // add to the call chain
  .addConditionalEdges('a', (state: State) => random() > state.count ? 'b' : 'c'); // addConditionalEdge -> addConditionalEdges

graph.compile();

Please let me know if I have any misunderstandings.

@SunHuawei commented on GitHub (Sep 26, 2025): Hi — I’m trying to get involved in the LangChain community. This is the first bug I’m looking at. I wasn’t able to reproduce your issue, but I found a couple of other problems: 1. `Argument of type '"a"' is not assignable to parameter of type '"__start__" | "__end__"'.ts(2345)` 2. `Property 'addConditionalEdge' does not exist on type 'StateGraph<{ count: { (): LastValue<number>; (annotation: SingleReducer<number, number>): BinaryOperatorAggregate<number, number>; Root: <S extends StateDefinition>(sd: S) => AnnotationRoot<...>; }; messages: BinaryOperatorAggregate<...>; }, ... 6 more ..., unknown>'. Did you mean 'addConditionalEdges'?ts(2551) graph.d.ts(56, 5): 'addConditionalEdges' is declared here.` So I modified your code accordingly and tested — it now passes npx tsc and npm tsx app.ts. ``` import { Annotation, MessagesAnnotation, StateGraph } from "@langchain/langgraph"; function random() { return Math.random(); } const PrivateAnnotation = Annotation.Root({ ...MessagesAnnotation.spec, count: Annotation<number>, }); type State = typeof PrivateAnnotation.State; const graph = new StateGraph({ stateSchema: PrivateAnnotation, input: MessagesAnnotation, output: MessagesAnnotation, }); graph .addNode('a', (state: State) => ({ count: 5 }), { input: PrivateAnnotation }) .addNode('b', (state: State) => state, { input: PrivateAnnotation }) .addNode('c', (state: State) => state, { input: PrivateAnnotation }) .addEdge('__start__', 'a') // add to the call chain .addConditionalEdges('a', (state: State) => random() > state.count ? 'b' : 'c'); // addConditionalEdge -> addConditionalEdges graph.compile(); ``` Please let me know if I have any misunderstandings.
Author
Owner

@hitmands commented on GitHub (Oct 17, 2025):

this fixes:

-  const graph = new StateGraph(MessagesAnnotation);

+ const graph = new StateGraph({
+   stateSchema: PrivateAnnotation,
+   input: MessagesAnnotation,
+   output: MessagesAnnotation,
+ });
@hitmands commented on GitHub (Oct 17, 2025): this fixes: ```diff - const graph = new StateGraph(MessagesAnnotation); + const graph = new StateGraph({ + stateSchema: PrivateAnnotation, + input: MessagesAnnotation, + output: MessagesAnnotation, + }); ```
Author
Owner

@hitmands commented on GitHub (Oct 17, 2025):

Update: supervisor doesn't compile.


this only compiles if the graph is not used as child graph to another one (ie, supervisor pattern)

@hitmands commented on GitHub (Oct 17, 2025): Update: supervisor doesn't compile. --- this only compiles if the graph is not used as child graph to another one (ie, supervisor pattern)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraphjs#357