Skip to content

feat: support dynamic tool calling via tool override in wrap_model_call#6711

Merged
sydney-runkle merged 5 commits intomainfrom
sr/dynamic-part-2
Jan 22, 2026
Merged

feat: support dynamic tool calling via tool override in wrap_model_call#6711
sydney-runkle merged 5 commits intomainfrom
sr/dynamic-part-2

Conversation

@sydney-runkle
Copy link
Collaborator

@sydney-runkle sydney-runkle commented Jan 22, 2026

Allow overriding tool impl in wrap_tool_call in order to support dynamically registered tools via middleware

@sydney-runkle sydney-runkle enabled auto-merge (squash) January 22, 2026 15:49
@sydney-runkle sydney-runkle merged commit c1b3598 into main Jan 22, 2026
60 checks passed
@sydney-runkle sydney-runkle deleted the sr/dynamic-part-2 branch January 22, 2026 15:53
sydney-runkle added a commit to langchain-ai/langchain that referenced this pull request Jan 23, 2026
dependent upon langchain-ai/langgraph#6711

1. relax constraint in `factory.py` to allow for tools not
pre-registered in the `ModelRequest.tools` list
2. always add tool node if `wrap_tool_call` or `awrap_tool_call` is
implemented
3. add tests confirming you can register new tools at runtime in
`wrap_model_call` and execute them via `wrap_tool_call`

allows for the following pattern

```py
from langchain_core.messages import HumanMessage, ToolMessage
from langchain_core.tools import tool

from libs.langchain_v1.langchain.agents.factory import create_agent
from libs.langchain_v1.langchain.agents.middleware.types import (
    AgentMiddleware,
    ModelRequest,
    ToolCallRequest,
)


@tool
def get_weather(location: str) -> str:
    """Get the current weather for a location."""
    return f"The weather in {location} is sunny and 72°F."


@tool
def calculate_tip(bill_amount: float, tip_percentage: float = 20.0) -> str:
    """Calculate the tip amount for a bill."""
    tip = bill_amount * (tip_percentage / 100)
    return f"Tip: ${tip:.2f}, Total: ${bill_amount + tip:.2f}"

class DynamicToolMiddleware(AgentMiddleware):
    """Middleware that adds and handles a dynamic tool."""

    def wrap_model_call(self, request: ModelRequest, handler):
        updated = request.override(tools=[*request.tools, calculate_tip])
        return handler(updated)

    def wrap_tool_call(self, request: ToolCallRequest, handler):
        if request.tool_call["name"] == "calculate_tip":
            return handler(request.override(tool=calculate_tip))
        return handler(request)


agent = create_agent(model="openai:gpt-4o-mini", tools=[get_weather], middleware=[DynamicToolMiddleware()])
result = agent.invoke({
    "messages": [HumanMessage("What's the weather in NYC? Also calculate a 20% tip on a $85 bill")]
})
for msg in result["messages"]:
    msg.pretty_print()
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants