本节根据用户角色限制可用工具:内部用户可以访问数据库,外部用户只能使用 Web Search。
工具权限不能只靠 prompt 约束。更可靠的做法是在模型调用前直接修改本次可见的工具列表,让模型根本看不到不该调用的工具。
| 用户角色 | 可用工具 |
|---|---|
| internal | web_search + sql_query |
| external | web_search only |
不要只告诉外部用户“不要查数据库”。应该在 middleware 中移除数据库工具。
Notebook 准备两个工具:web_search 查询互联网,sql_query 查询本地 Chinook 数据库。
tavily_client = TavilyClient()
db = SQLDatabase.from_uri("sqlite:///resources/Chinook.db")
@tool
def web_search(query: str) -> Dict[str, Any]:
"""Search the web for information"""
return tavily_client.search(query)
@tool
def sql_query(query: str) -> str:
"""Obtain information from the database using SQL queries"""
try:
return db.run(query)
except Exception as e:
return f"Error: {e}"SQL 工具通常访问内部数据。生产环境还需要只读限制、表级权限、行数限制和审计日志。
用户角色通过 runtime context 传入。默认角色是 external。
from dataclasses import dataclass
@dataclass
class UserRole:
user_role: str = "external"用户角色通常来自登录系统、组织权限或 API token,不应该让模型自己从用户文本中判断。
dynamic_tool_call 读取 request.runtime.context.user_role。如果不是 internal,就用 request.override(tools=[web_search]) 把 SQL 工具移除。
from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse
from typing import Callable
@wrap_model_call
def dynamic_tool_call(
request: ModelRequest,
handler: Callable[[ModelRequest], ModelResponse],
) -> ModelResponse:
"""Dynamically call tools based on the runtime context"""
user_role = request.runtime.context.user_role
if user_role == "internal":
pass
else:
tools = [web_search]
request = request.override(tools=tools)
return handler(request)外部用户的本次模型调用只会看到 web_search,因此无法选择 sql_query。
Agent 初始注册两个工具,但实际可见工具会被 middleware 按角色改写。外部用户问数据库数量时,模型没有 SQL 工具可用。
agent = create_agent(
model=deepseek_model(),
tools=[web_search, sql_query],
middleware=[dynamic_tool_call],
context_schema=UserRole,
)
response = agent.invoke(
{"messages": [HumanMessage(content="How many artists are in the database?")]},
context={"user_role": "external"},
)
print(response["messages"][-1].content)如果传 context=UserRole(user_role="internal"),middleware 不覆盖工具列表,模型就可以使用 SQL 工具。
request.override(tools=...) 可以改变本次模型调用的工具集。