diff --git a/libs/langgraph-core/src/pregel/index.ts b/libs/langgraph-core/src/pregel/index.ts index 88bf92f03..3bdaad837 100644 --- a/libs/langgraph-core/src/pregel/index.ts +++ b/libs/langgraph-core/src/pregel/index.ts @@ -2012,6 +2012,10 @@ export class Pregel< durability, ] = this._defaults(restConfig); + // Tag root run with LangGraph integration metadata, but don't override + // if already set (e.g. by downstream frameworks like DeepAgents) + config.metadata = { ls_integration: "langgraph", ...config.metadata }; + // At entrypoint, `configurable` is an alias for `context`. if (typeof config.context !== "undefined") { config.context = await this._validateContext(config.context); diff --git a/libs/langgraph-core/src/tests/pregel.test.ts b/libs/langgraph-core/src/tests/pregel.test.ts index fe3e1ebae..fd0527089 100644 --- a/libs/langgraph-core/src/tests/pregel.test.ts +++ b/libs/langgraph-core/src/tests/pregel.test.ts @@ -5351,7 +5351,7 @@ graph TD; payload: { config: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5383,7 +5383,7 @@ graph TD; payload: { config: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5393,7 +5393,7 @@ graph TD; }, parentConfig: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5451,7 +5451,7 @@ graph TD; payload: { config: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5461,7 +5461,7 @@ graph TD; }, parentConfig: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5519,7 +5519,7 @@ graph TD; payload: { config: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5529,7 +5529,7 @@ graph TD; }, parentConfig: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5587,7 +5587,7 @@ graph TD; payload: { config: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -5597,7 +5597,7 @@ graph TD; }, parentConfig: { tags: [], - metadata: { thread_id: "10" }, + metadata: { ls_integration: "langgraph", thread_id: "10" }, recursion_limit: 25, configurable: { thread_id: "10", @@ -9175,6 +9175,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_one:/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_one:/), + ls_integration: "langgraph", name: "p_one", tags: ["graph:step:1"], }, @@ -9191,6 +9192,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_two:.*\|c_one:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", name: "c_one", tags: ["graph:step:1"], }, @@ -9207,6 +9209,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_two:.*\|c_one:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", name: "c_one", tags: ["graph:step:1"], }, @@ -9223,6 +9226,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_two:.*\|c_two:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", ls_model_type: "chat", ls_provider: "FakeChatModel", ls_stop: undefined, @@ -9243,6 +9247,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_two:.*\|c_two:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", ls_model_type: "chat", ls_provider: "FakeChatModel", ls_stop: undefined, @@ -9263,6 +9268,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_three/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_three/), + ls_integration: "langgraph", ls_model_type: "chat", ls_provider: "FakeChatModel", ls_stop: undefined, @@ -9293,8 +9299,21 @@ graph TD; ) ); - expect(streamedCombinedEvents).toMatchObject([ + // The relative ordering of "custom" and "messages" events for the same + // chunk is non-deterministic across Node.js versions, so sort by mode + // before asserting (custom < messages alphabetically). + const sortedCombinedEvents = [...streamedCombinedEvents].sort((a, b) => { + const aMode = a[0] as string; + const bMode = b[0] as string; + if (aMode !== bMode) return aMode < bMode ? -1 : 1; + // within same mode, preserve original order by index + return ( + streamedCombinedEvents.indexOf(a) - streamedCombinedEvents.indexOf(b) + ); + }); + expect(sortedCombinedEvents).toMatchObject([ ["custom", { from: "parent" }], + ["custom", { from: "subgraph", content: "1" }], [ "messages", [ @@ -9307,6 +9326,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_one:/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_one:/), + ls_integration: "langgraph", name: "p_one", tags: ["graph:step:1"], }, @@ -9325,6 +9345,7 @@ graph TD; expect.stringMatching(/^p_two:.*\|c_one:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", name: "c_one", tags: ["graph:step:1"], }, @@ -9343,6 +9364,7 @@ graph TD; expect.stringMatching(/^p_two:.*\|c_one:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", name: "c_one", tags: ["graph:step:1"], }, @@ -9361,6 +9383,7 @@ graph TD; expect.stringMatching(/^p_two:.*\|c_two:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", ls_model_type: "chat", ls_provider: "FakeChatModel", ls_stop: undefined, @@ -9369,7 +9392,6 @@ graph TD; }, ], ], - ["custom", { from: "subgraph", content: "1" }], [ "messages", [ @@ -9383,6 +9405,7 @@ graph TD; expect.stringMatching(/^p_two:.*\|c_two:.*/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_two:/), + ls_integration: "langgraph", ls_model_type: "chat", ls_provider: "FakeChatModel", ls_stop: undefined, @@ -9402,6 +9425,7 @@ graph TD; langgraph_checkpoint_ns: expect.stringMatching(/^p_three/), __pregel_task_id: expect.any(String), checkpoint_ns: expect.stringMatching(/^p_three/), + ls_integration: "langgraph", ls_model_type: "chat", ls_provider: "FakeChatModel", ls_stop: undefined, diff --git a/libs/langgraph-core/src/tests/tracing.test.ts b/libs/langgraph-core/src/tests/tracing.test.ts index 1165d5d16..8d1079d5c 100644 --- a/libs/langgraph-core/src/tests/tracing.test.ts +++ b/libs/langgraph-core/src/tests/tracing.test.ts @@ -48,7 +48,7 @@ it("stream events for a multi-node graph", async () => { name: "LangGraph", tags: [], run_id: expect.any(String), - metadata: {}, + metadata: { ls_integration: "langgraph" }, }, { event: "on_chain_start", @@ -260,7 +260,7 @@ it("stream events for a multi-node graph", async () => { run_id: expect.any(String), name: "LangGraph", tags: [], - metadata: {}, + metadata: { ls_integration: "langgraph" }, data: { chunk: { testnode: { @@ -279,7 +279,7 @@ it("stream events for a multi-node graph", async () => { run_id: expect.any(String), name: "LangGraph", tags: [], - metadata: {}, + metadata: { ls_integration: "langgraph" }, }, ]); }); @@ -391,7 +391,7 @@ it("Should respect .withConfig", async () => { name: "OVERRIDDEN_NAME", tags: [], run_id: expect.any(String), - metadata: {}, + metadata: { ls_integration: "langgraph" }, }, { event: "on_chain_start", @@ -603,7 +603,7 @@ it("Should respect .withConfig", async () => { run_id: expect.any(String), name: "OVERRIDDEN_NAME", tags: [], - metadata: {}, + metadata: { ls_integration: "langgraph" }, data: { chunk: { testnode: { @@ -622,7 +622,7 @@ it("Should respect .withConfig", async () => { run_id: expect.any(String), name: "OVERRIDDEN_NAME", tags: [], - metadata: {}, + metadata: { ls_integration: "langgraph" }, }, ]); });