mirror of
https://github.com/Sea-Haven-Industries/open-swe.git
synced 2026-09-30 22:03:14 +00:00
66 lines
2.1 KiB
Python
66 lines
2.1 KiB
Python
|
|
"""Hide named tools from the model without rebuilding the agent.
|
||
|
|
|
||
|
|
`create_deep_agent` always wires the `task` tool when the auto-added
|
||
|
|
general-purpose subagent is present. The reviewer agent has no use for
|
||
|
|
subagent dispatch, so this middleware drops the named tools from the
|
||
|
|
request before the model sees them. Mirrors the behavior of deepagents'
|
||
|
|
own private `_ToolExclusionMiddleware` but lives here so we don't depend
|
||
|
|
on a private import path.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from collections.abc import Awaitable, Callable
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from langchain.agents.middleware.types import (
|
||
|
|
AgentMiddleware,
|
||
|
|
AgentState,
|
||
|
|
ModelRequest,
|
||
|
|
ModelResponse,
|
||
|
|
)
|
||
|
|
from langchain_core.tools import BaseTool
|
||
|
|
|
||
|
|
|
||
|
|
def _tool_name(tool: BaseTool | dict[str, Any] | Any) -> str | None:
|
||
|
|
if isinstance(tool, dict):
|
||
|
|
name = tool.get("name")
|
||
|
|
return name if isinstance(name, str) else None
|
||
|
|
name = getattr(tool, "name", None)
|
||
|
|
return name if isinstance(name, str) else None
|
||
|
|
|
||
|
|
|
||
|
|
class ExcludeToolsMiddleware(AgentMiddleware):
|
||
|
|
"""Strip named tools from each model request.
|
||
|
|
|
||
|
|
Place this AFTER tool-injecting middleware (FilesystemMiddleware,
|
||
|
|
SubAgentMiddleware) so it can remove middleware-injected tools too.
|
||
|
|
"""
|
||
|
|
|
||
|
|
state_schema = AgentState
|
||
|
|
|
||
|
|
def __init__(self, *, excluded: frozenset[str]) -> None:
|
||
|
|
self._excluded = excluded
|
||
|
|
|
||
|
|
def _filter(self, request: ModelRequest) -> ModelRequest:
|
||
|
|
if not self._excluded:
|
||
|
|
return request
|
||
|
|
filtered = [t for t in request.tools if _tool_name(t) not in self._excluded]
|
||
|
|
if len(filtered) == len(request.tools):
|
||
|
|
return request
|
||
|
|
return request.override(tools=filtered)
|
||
|
|
|
||
|
|
def wrap_model_call(
|
||
|
|
self,
|
||
|
|
request: ModelRequest,
|
||
|
|
handler: Callable[[ModelRequest], ModelResponse],
|
||
|
|
) -> ModelResponse:
|
||
|
|
return handler(self._filter(request))
|
||
|
|
|
||
|
|
async def awrap_model_call(
|
||
|
|
self,
|
||
|
|
request: ModelRequest,
|
||
|
|
handler: Callable[[ModelRequest], Awaitable[ModelResponse]],
|
||
|
|
) -> ModelResponse:
|
||
|
|
return await handler(self._filter(request))
|