Skip to content

Commit 5c40008

Browse files
committed
fix: remove duplicate tools in langgraph integrations
1 parent eae2316 commit 5c40008

File tree

3 files changed

+38
-19
lines changed

3 files changed

+38
-19
lines changed

typescript-sdk/integrations/langgraph/python/ag_ui_langgraph/agent.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,12 +446,26 @@ def langgraph_default_merge_state(self, state: State, messages: List[BaseMessage
446446
else:
447447
tools_as_dicts.append(tool)
448448

449+
all_tools = [*state.get("tools", []), *tools_as_dicts]
450+
451+
# Remove duplicates based on tool name
452+
seen_names = set()
453+
unique_tools = []
454+
for tool in all_tools:
455+
tool_name = tool.get("name") if isinstance(tool, dict) else getattr(tool, "name", None)
456+
if tool_name and tool_name not in seen_names:
457+
seen_names.add(tool_name)
458+
unique_tools.append(tool)
459+
elif not tool_name:
460+
# Keep tools without names (shouldn't happen, but just in case)
461+
unique_tools.append(tool)
462+
449463
return {
450464
**state,
451465
"messages": new_messages,
452-
"tools": [*state.get("tools", []), *tools_as_dicts],
466+
"tools": unique_tools,
453467
"ag-ui": {
454-
"tools": [*state.get("tools", []), *tools_as_dicts],
468+
"tools": unique_tools,
455469
"context": input.context or []
456470
}
457471
}

typescript-sdk/integrations/langgraph/src/agent.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
PredictStateTool,
2626
LangGraphReasoning,
2727
StateEnrichment,
28-
LangGraphTool,
28+
LangGraphToolWithName,
2929
} from "./types";
3030
import {
3131
AbstractAgent,
@@ -1003,21 +1003,25 @@ export class LangGraphAgent extends AbstractAgent {
10031003

10041004
const newMessages = messages.filter((message) => !existingMessageIds.has(message.id));
10051005

1006-
const langGraphTools: LangGraphTool[] = [...(state.tools ?? []), ...(input.tools ?? [])].map((tool) => {
1007-
if (tool.type) {
1008-
return tool;
1006+
const langGraphTools: LangGraphToolWithName[] = [...(state.tools ?? []), ...(input.tools ?? [])].reduce((acc, tool) => {
1007+
let mappedTool = tool;
1008+
if (!tool.type) {
1009+
mappedTool = {
1010+
type: "function",
1011+
name: tool.name,
1012+
function: {
1013+
name: tool.name,
1014+
description: tool.description,
1015+
parameters: tool.parameters,
1016+
},
1017+
}
10091018
}
10101019

1011-
return {
1012-
type: "function",
1013-
name: tool.name,
1014-
function: {
1015-
name: tool.name,
1016-
description: tool.description,
1017-
parameters: tool.parameters,
1018-
},
1019-
};
1020-
});
1020+
// Verify no duplicated
1021+
if (acc.find((t: LangGraphToolWithName) => (t.name === mappedTool.name) || t.function.name === mappedTool.function.name)) return acc;
1022+
1023+
return [...acc, mappedTool];
1024+
}, []);
10211025

10221026
return {
10231027
...state,

typescript-sdk/integrations/langgraph/src/types.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ export enum LangGraphEventTypes {
1515
OnInterrupt = "on_interrupt",
1616
}
1717

18-
export type LangGraphTool = {
18+
export type LangGraphToolWithName = {
1919
type: "function";
20+
name?: string;
2021
function: {
2122
name: string;
2223
description: string;
@@ -29,9 +30,9 @@ export type State<TDefinedState = Record<string, any>> = {
2930
} & Record<string, any>;
3031
export interface StateEnrichment {
3132
messages: LangGraphMessage[];
32-
tools: LangGraphTool[];
33+
tools: LangGraphToolWithName[];
3334
'ag-ui': {
34-
tools: LangGraphTool[];
35+
tools: LangGraphToolWithName[];
3536
context: RunAgentInput['context']
3637
}
3738
}

0 commit comments

Comments
 (0)