Repository: langchain
Issue: Additional kwargs key prompt_tokens already exists in left dict and value has unsupported type <class 'int'> in langchain-core/utils/_merge.py merge_dict() function when running with anthropic.claude-3-sonnet
Labels: 🤖:bug

### Checked other resources

- [X] I added a very descriptive title to this issue.
- [X] I searched the LangChain 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 LangChain rather than my code.
- [X] The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).

### Example Code


Below is the method from  _merge.py that raises the error. 
In my code the prebuilt ReAct agent sits inside the LangGraph node 
[Won't be possible to have the entire code in here but the same type of agents executes the first time and fails the second ]
```

def merge_dicts(left: dict[str, Any], *others: dict[str, Any]) -> dict[str, Any]:
    """Merge many dicts, handling specific scenarios where a key exists in both
    dictionaries but has a value of None in 'left'. In such cases, the method uses the
    value from 'right' for that key in the merged dictionary.
    Args:
        left: The first dictionary to merge.
        others: The other dictionaries to merge.

    Returns:
        The merged dictionary.

    Raises:
        TypeError: If the key exists in both dictionaries but has a different type.
        TypeError: If the value has an unsupported type.

    Example:
        If left = {"function_call": {"arguments": None}} and
        right = {"function_call": {"arguments": "{\n"}}
        then, after merging, for the key "function_call",
        the value from 'right' is used,
        resulting in merged = {"function_call": {"arguments": "{\n"}}.
    """
    merged = left.copy()
    for right in others:
        for right_k, right_v in right.items():
            if right_k not in merged or right_v is not None and merged[right_k] is None:
                merged[right_k] = right_v
            elif right_v is None:
                continue
            elif type(merged[right_k]) is not type(right_v):
                msg = (
                    f'additional_kwargs["{right_k}"] already exists in this message,'
                    " but with a different type."
                )
                raise TypeError(msg)
            elif isinstance(merged[right_k], str):
                # TODO: Add below special handling for 'type' key in 0.3 and remove
                # merge_lists 'type' logic.
                #
                # if right_k == "type":
                #     if merged[right_k] == right_v:
                #         continue
                #     else:
                #         raise ValueError(
                #             "Unable to merge. Two different values seen for special "
                #             f"key 'type': {merged[right_k]} and {right_v}. 'type' "
                #             "should either occur once or have the same value across "
                #             "all dicts."
                #         )
                merged[right_k] += right_v
            elif isinstance(merged[right_k], dict):
                merged[right_k] = merge_dicts(merged[right_k], right_v)
            elif isinstance(merged[right_k], list):
                merged[right_k] = merge_lists(merged[right_k], right_v)
            elif merged[right_k] == right_v:
                continue
            else:
                msg = (
                    f"Additional kwargs key {right_k} already exists in left dict and "
                    f"value has unsupported type {type(merged[right_k])}."
                )
                raise TypeError(msg)
    return merged
```

### Error Message and Stack Trace (if applicable)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 7
      2 userInput = '''
      3 Develop Business Challenges and Opportunities (BCOs) for brand based on its Strategic Imperatives (SIs).
      4 '''
      5 message = HumanMessage(content = userInput )
----> 7 graph.invoke(
      8 input =  {"messages" : [message],
      9           "brand" : 'brand',
     10           "primary_competitors" : ["competitor 1", "competitor 2", "competitor 3"],
     11           "brand_research" : [],
     12           "strategic_imperatives" : ["SI-1",
     13                                     "SI-2",
     14                                     "SI-3",
     15                                     "SI-4",
     16                                     "SI-5",
     17                                     "SI-6'),
     18           "stratagic_imperatives_research" : [],
     19           "plan" : [],
     20           "next_actor" : '',
     21           "next_task" : '',
     22           "sender" : '',
     23               },
     24             config = {"configurable": {"thread_id": "42"}, "recursion_limit": 30} ,
     25 
     26 
     27 )
     28 # ToolMessage

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/__init__.py:1940, in Pregel.invoke(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, **kwargs)
   1938 else:
   1939     chunks = []
-> 1940 for chunk in self.stream(
   1941     input,
   1942     config,
   1943     stream_mode=stream_mode,
   1944     output_keys=output_keys,
   1945     interrupt_before=interrupt_before,
   1946     interrupt_after=interrupt_after,
   1947     debug=debug,
   1948     **kwargs,
   1949 ):
   1950     if stream_mode == "values":
   1951         latest = chunk

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/__init__.py:1660, in Pregel.stream(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, subgraphs)
   1654     # Similarly to Bulk Synchronous Parallel / Pregel model
   1655     # computation proceeds in steps, while there are channel updates
   1656     # channel updates from step N are only visible in step N+1
   1657     # channels are guaranteed to be immutable for the duration of the step,
   1658     # with channel updates applied only at the transition between steps
   1659     while loop.tick(input_keys=self.input_channels):
-> 1660         for _ in runner.tick(
   1661             loop.tasks.values(),
   1662             timeout=self.step_timeout,
   1663             retry_policy=self.retry_policy,
   1664             get_waiter=get_waiter,
   1665         ):
   1666             # emit output
   1667             yield from output()
   1668 # emit output

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/runner.py:167, in PregelRunner.tick(self, tasks, reraise, timeout, retry_policy, get_waiter)
    165 t = tasks[0]
    166 try:
--> 167     run_with_retry(
    168         t,
    169         retry_policy,
    170         configurable={
    171             CONFIG_KEY_SEND: partial(writer, t),
    172             CONFIG_KEY_CALL: partial(call, t),
    173         },
    174     )
    175     self.commit(t, None)
    176 except Exception as exc:

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/retry.py:40, in run_with_retry(task, retry_policy, configurable)
     38     task.writes.clear()
     39     # run the task
---> 40     return task.proc.invoke(task.input, config)
     41 except ParentCommand as exc:
     42     ns: str = config[CONF][CONFIG_KEY_CHECKPOINT_NS]

File /opt/conda/lib/python3.11/site-packages/langgraph/utils/runnable.py:408, in RunnableSeq.invoke(self, input, config, **kwargs)
    404 config = patch_config(
    405     config, callbacks=run_manager.get_child(f"seq:step:{i+1}")
    406 )
    407 if i == 0:
--> 408     input = step.invoke(input, config, **kwargs)
    409 else:
    410     input = step.invoke(input, config)

File /opt/conda/lib/python3.11/site-packages/langgraph/utils/runnable.py:184, in RunnableCallable.invoke(self, input, config, **kwargs)
    182 else:
    183     context.run(_set_config_context, config)
--> 184     ret = context.run(self.func, input, **kwargs)
    185 if isinstance(ret, Runnable) and self.recurse:
    186     return ret.invoke(input, config)

File ~/MUltiAgent_SI_to_BCO/graph/workflow.py:74, in workflow.init_graph.<locals>.<lambda>(state)
     68 self.workflow = StateGraph(state)
     70 self.workflow.add_node("brand_research_agent",lambda state: agent_node(state = state,
     71                                                   agent = self.agents["brand_research_agent"],
     72                                                   name = "brand_research_agent",))
---> 74 self.workflow.add_node("si_research_agent",lambda state: agent_node(state = state,
     75                                                   agent = self.agents["si_research_agent"],
     76                                                   name = "si_research_agent",))
     78 self.workflow.add_node("bco_planning_agent",lambda state: agent_node(state = state,
     79                                                   agent = self.agents["bco_planning_agent"],
     80                                                   name = "bco_planning_agent",))
     82 self.workflow.add_node("bco_formulation_agent",lambda state: agent_node(state = state,
     83                                                   agent = self.agents["bco_formulation_agent"],
     84                                                   name = "bco_formulation_agent",))

File ~/MUltiAgent_SI_to_BCO/graph/nodes.py:78, in agent_node(state, agent, name)
     75 except Exception as e:
     76     # Log and raise any exceptions that occur
     77     logger.error(f"Error in executing {name} node: {str(e)}")
---> 78     raise e

File ~/MUltiAgent_SI_to_BCO/graph/nodes.py:39, in agent_node(state, agent, name)
     36 logger.info(f"executing agent {name}")
     38 # Invoke the agent with the current state
---> 39 response = agent.invoke(state)
     41 # Extract the content from the response
     42 content = response['output'] if isinstance(response, dict) and 'output' in response else response

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/__init__.py:1940, in Pregel.invoke(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, **kwargs)
   1938 else:
   1939     chunks = []
-> 1940 for chunk in self.stream(
   1941     input,
   1942     config,
   1943     stream_mode=stream_mode,
   1944     output_keys=output_keys,
   1945     interrupt_before=interrupt_before,
   1946     interrupt_after=interrupt_after,
   1947     debug=debug,
   1948     **kwargs,
   1949 ):
   1950     if stream_mode == "values":
   1951         latest = chunk

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/__init__.py:1660, in Pregel.stream(self, input, config, stream_mode, output_keys, interrupt_before, interrupt_after, debug, subgraphs)
   1654     # Similarly to Bulk Synchronous Parallel / Pregel model
   1655     # computation proceeds in steps, while there are channel updates
   1656     # channel updates from step N are only visible in step N+1
   1657     # channels are guaranteed to be immutable for the duration of the step,
   1658     # with channel updates applied only at the transition between steps
   1659     while loop.tick(input_keys=self.input_channels):
-> 1660         for _ in runner.tick(
   1661             loop.tasks.values(),
   1662             timeout=self.step_timeout,
   1663             retry_policy=self.retry_policy,
   1664             get_waiter=get_waiter,
   1665         ):
   1666             # emit output
   1667             yield from output()
   1668 # emit output

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/runner.py:167, in PregelRunner.tick(self, tasks, reraise, timeout, retry_policy, get_waiter)
    165 t = tasks[0]
    166 try:
--> 167     run_with_retry(
    168         t,
    169         retry_policy,
    170         configurable={
    171             CONFIG_KEY_SEND: partial(writer, t),
    172             CONFIG_KEY_CALL: partial(call, t),
    173         },
    174     )
    175     self.commit(t, None)
    176 except Exception as exc:

File /opt/conda/lib/python3.11/site-packages/langgraph/pregel/retry.py:40, in run_with_retry(task, retry_policy, configurable)
     38     task.writes.clear()
     39     # run the task
---> 40     return task.proc.invoke(task.input, config)
     41 except ParentCommand as exc:
     42     ns: str = config[CONF][CONFIG_KEY_CHECKPOINT_NS]

File /opt/conda/lib/python3.11/site-packages/langgraph/utils/runnable.py:408, in RunnableSeq.invoke(self, input, config, **kwargs)
    404 config = patch_config(
    405     config, callbacks=run_manager.get_child(f"seq:step:{i+1}")
    406 )
    407 if i == 0:
--> 408     input = step.invoke(input, config, **kwargs)
    409 else:
    410     input = step.invoke(input, config)

File /opt/conda/lib/python3.11/site-packages/langgraph/utils/runnable.py:176, in RunnableCallable.invoke(self, input, config, **kwargs)
    174     context = copy_context()
    175     context.run(_set_config_context, child_config)
--> 176     ret = context.run(self.func, input, **kwargs)
    177 except BaseException as e:
    178     run_manager.on_chain_error(e)

File /opt/conda/lib/python3.11/site-packages/langgraph/prebuilt/chat_agent_executor.py:560, in create_react_agent.<locals>.call_model(state, config)
    558 def call_model(state: AgentState, config: RunnableConfig) -> AgentState:
    559     _validate_chat_history(state["messages"])
--> 560     response = model_runnable.invoke(state, config)
    561     has_tool_calls = isinstance(response, AIMessage) and response.tool_calls
    562     all_tools_return_direct = (
    563         all(call["name"] in should_return_direct for call in response.tool_calls)
    564         if isinstance(response, AIMessage)
    565         else False
    566     )

File /opt/conda/lib/python3.11/site-packages/langchain_core/runnables/base.py:3022, in RunnableSequence.invoke(self, input, config, **kwargs)
   3020             input = context.run(step.invoke, input, config, **kwargs)
   3021         else:
-> 3022             input = context.run(step.invoke, input, config)
   3023 # finish the root run
   3024 except BaseException as e:

File /opt/conda/lib/python3.11/site-packages/langchain_core/runnables/base.py:4711, in RunnableLambda.invoke(self, input, config, **kwargs)
   4697 """Invoke this Runnable synchronously.
   4698 
   4699 Args:
   (...)
   4708     TypeError: If the Runnable is a coroutine function.
   4709 """
   4710 if hasattr(self, "func"):
-> 4711     return self._call_with_config(
   4712         self._invoke,
   4713         input,
   4714         self._config(config, self.func),
   4715         **kwargs,
   4716     )
   4717 else:
   4718     msg = (
   4719         "Cannot invoke a coroutine function synchronously."
   4720         "Use `ainvoke` instead."
   4721     )

File /opt/conda/lib/python3.11/site-packages/langchain_core/runnables/base.py:1925, in Runnable._call_with_config(self, func, input, config, run_type, serialized, **kwargs)
   1921     context = copy_context()
   1922     context.run(_set_config_context, child_config)
   1923     output = cast(
   1924         Output,
-> 1925         context.run(
   1926             call_func_with_variable_args,  # type: ignore[arg-type]
   1927             func,  # type: ignore[arg-type]
   1928             input,  # type: ignore[arg-type]
   1929             config,
   1930             run_manager,
   1931             **kwargs,
   1932         ),
   1933     )
   1934 except BaseException as e:
   1935     run_manager.on_chain_error(e)

File /opt/conda/lib/python3.11/site-packages/langchain_core/runnables/config.py:396, in call_func_with_variable_args(func, input, config, run_manager, **kwargs)
    394 if run_manager is not None and accepts_run_manager(func):
    395     kwargs["run_manager"] = run_manager
--> 396 return func(input, **kwargs)

File /opt/conda/lib/python3.11/site-packages/langchain_core/runnables/base.py:4565, in RunnableLambda._invoke(self, input, run_manager, config, **kwargs)
   4563                 output = chunk
   4564 else:
-> 4565     output = call_func_with_variable_args(
   4566         self.func, input, config, run_manager, **kwargs
   4567     )
   4568 # If the output is a Runnable, invoke it
   4569 if isinstance(output, Runnable):

File /opt/conda/lib/python3.11/site-packages/langchain_core/runnables/config.py:396, in call_func_with_variable_args(func, input, config, run_manager, **kwargs)
    394 if run_manager is not None and accepts_run_manager(func):
    395     kwargs["run_manager"] = run_manager
--> 396 return func(input, **kwargs)

File /opt/conda/lib/python3.11/site-packages/langchain_core/messages/utils.py:571, in merge_message_runs(messages, chunk_separator)
    564         if (
    565             isinstance(last_chunk.content, str)
    566             and isinstance(curr_chunk.content, str)
    567             and last_chunk.content
    568             and curr_chunk.content
    569         ):
    570             last_chunk.content += chunk_separator
--> 571         merged.append(_chunk_to_msg(last_chunk + curr_chunk))
    572 return merged

File /opt/conda/lib/python3.11/site-packages/langchain_core/messages/ai.py:395, in AIMessageChunk.__add__(self, other)
    393 def __add__(self, other: Any) -> BaseMessageChunk:  # type: ignore
    394     if isinstance(other, AIMessageChunk):
--> 395         return add_ai_message_chunks(self, other)
    396     elif isinstance(other, (list, tuple)) and all(
    397         isinstance(o, AIMessageChunk) for o in other
    398     ):
    399         return add_ai_message_chunks(self, *other)

File /opt/conda/lib/python3.11/site-packages/langchain_core/messages/ai.py:412, in add_ai_message_chunks(left, *others)
    409     raise ValueError(msg)
    411 content = merge_content(left.content, *(o.content for o in others))
--> 412 additional_kwargs = merge_dicts(
    413     left.additional_kwargs, *(o.additional_kwargs for o in others)
    414 )
    415 response_metadata = merge_dicts(
    416     left.response_metadata, *(o.response_metadata for o in others)
    417 )
    419 # Merge tool call chunks

File /opt/conda/lib/python3.11/site-packages/langchain_core/utils/_merge.py:58, in merge_dicts(left, *others)
     56     merged[right_k] += right_v
     57 elif isinstance(merged[right_k], dict):
---> 58     merged[right_k] = merge_dicts(merged[right_k], right_v)
     59 elif isinstance(merged[right_k], list):
     60     merged[right_k] = merge_lists(merged[right_k], right_v)

File /opt/conda/lib/python3.11/site-packages/langchain_core/utils/_merge.py:68, in merge_dicts(left, *others)
     63         else:
     64             msg = (
     65                 f"Additional kwargs key {right_k} already exists in left dict and "
     66                 f"value has unsupported type {type(merged[right_k])}."
     67             )
---> 68             raise TypeError(msg)
     69 return merged

TypeError: Additional kwargs key prompt_tokens already exists in left dict and value has unsupported type <class 'int'>.

### Description

I am trying to use the Pre built ReAct agent as nodes inside a LangGraph Graph. The graph as 2 ReAct based agent nodes.Both are exactly identical just with different prompts.

Agent 1 runs fine but Agent 2 gives the below error. 

The issue seems to be in _merge.py utility within langchain_core library. 
Similar issue with Gemini is discussed in #23827

Thanks in advance for all the help

### System Info

System Information
------------------
> OS:  Linux
> OS Version:  #1 SMP Tue Dec 3 14:36:00 UTC 2024
> Python Version:  3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:36:13) [GCC 12.3.0]

Package Information
-------------------
> langchain_core: 0.3.29
> langchain: 0.3.14
> langchain_community: 0.3.14
> langsmith: 0.2.7
> langchain_aws: 0.2.10
> langchain_chroma: 0.2.0
> langchain_text_splitters: 0.3.4
> langchainhub: 0.1.21
> langgraph_sdk: 0.1.48

Optional packages not installed
-------------------------------
> langserve

Other Dependencies
------------------
> aiohttp: 3.11.11
> async-timeout: Installed. No version info available.
> boto3: 1.35.91
> chromadb: 0.5.23
> dataclasses-json: 0.6.7
> fastapi: 0.115.6
> httpx: 0.27.0
> httpx-sse: 0.4.0
> jsonpatch: 1.33
> langsmith-pyo3: Installed. No version info available.
> numpy: 1.26.4
> orjson: 3.10.13
> packaging: 23.2
> pydantic: 2.9.2
> pydantic-settings: 2.7.1
> PyYAML: 6.0.1
> requests: 2.32.3
> requests-toolbelt: 1.0.0
> SQLAlchemy: 2.0.31
> tenacity: 8.4.1
> types-requests: 2.32.0.20241016
> typing-extensions: 4.1