Dify - 详细介绍 Dify 工具(Tool)系统核心架构设计
本文详细解析了Dify AI开发平台的工具系统架构设计。该系统采用分层架构,包含工具管理器、提供者控制器和工具三层结构,支持内置工具和API工具两种类型。文章介绍了快速接入和高级接入两种开发方式,重点阐述了变量池机制、动态参数生成和工具可用性控制等关键技术。通过模块化设计和配置驱动开发,该系统实现了灵活扩展能力,使多个工具能协同完成复杂任务。开发者可参考该架构进行工具开发和集成。
在 AI 应用开发平台中,工具(Tool)系统是连接大语言模型与外部世界的桥梁,它使 AI 能够执行各种实际任务,如搜索信息、生成图片、处理数据等。本文将深入解析 Dify 工具系统的核心架构设计,帮助理解其工作原理并进行扩展开发。
文件组织结构
core/tools/
├── provider/builtin/ # 内置工具供应商
│ └── {provider_name}/ # 如 google
│ ├── _assets/ # 图标等资源
│ ├── {provider_name}.yaml # 供应商配置
│ ├── {provider_name}.py # 供应商代码
│ └── tools/ # 工具集合
│ ├── {tool_name}.yaml # 工具配置
│ └── {tool_name}.py # 工具实现
└── docs/ # 文档
1、工具系统概述
Dify 工具系统是一个模块化、可扩展的框架,用于在 Agent 助手和工作流中实现各种功能。该系统的设计理念是实现前后端解耦,使开发者能够在不修改前端逻辑的情况下定义和展示自己的工具,从而实现 Dify 能力的水平扩展。(推荐阅读,了解 Dify 如何快速集成新模型👉从零开始学 Dify-详细介绍 Dify 模型运行时的核心架构)

目前,Dify 工具系统支持两种类型的工具:
-
内置工具(Built-in Tools):在产品内部实现,硬编码用于 Agent 和工作流。
-
API 工具(Api-Based Tools):利用第三方 API 实现,无需编码即可集成,只需在前端提供 OpenAPI、Swagger 或 OpenAI-plugin 格式的接口定义。
2、核心架构设计
2.1 整体架构
Dify 工具系统采用了分层架构设计,主要包括管理层、提供者层和工具层三个层次。

2.2 核心组件
2.2.1 工具管理器(ToolManager)
ToolManager 是工具系统的核心管理类,负责管理所有工具提供者和工具实例。它提供了获取工具提供者、工具实例和工具运行时的方法,是工具系统的入口点。
主要功能:
-
加载和管理内置工具提供者
-
获取特定工具提供者和工具实例
-
为 Agent 和工作流创建工具运行时
2.2.2 工具提供者控制器(ToolProviderController)
ToolProviderController 是工具提供者的抽象基类,定义了工具提供者的接口。每个工具提供者都需要实现这个接口,以提供工具列表、获取特定工具、验证凭据等功能。
主要子类:
-
BuiltinToolProviderController:内置工具提供者控制器 -
ApiToolProviderController:API 工具提供者控制器
2.2.3 工具(Tool)
Tool 是工具的抽象基类,定义了工具的接口。每个工具都需要实现这个接口,以提供工具的调用、参数验证等功能。
主要子类:
-
BuiltinTool:内置工具 -
ApiTool:API 工具
2.3 数据结构

3、工具接入方式
3.1 快速接入
快速接入适用于简单工具的开发,通过配置驱动的方式快速实现工具功能。以 Google 搜索工具为例,快速接入需要完成以下步骤:
3.1.1 准备工具供应商 YAML
identity:
author:Dify
name:google
label:
en_US:Google
zh_Hans:Google
description:
en_US:Google
zh_Hans:Google
icon:icon.svg
tags:
-search
3.1.2 准备供应商凭据
credentials_for_provider:
serpapi_api_key:
type:secret-input
required:true
label:
en_US:SerpApiAPIkey
zh_Hans:SerpApiAPIkey
placeholder:
en_US:PleaseinputyourSerpApiAPIkey
zh_Hans:请输入你的SerpApiAPIkey
help:
en_US:GetyourSerpApiAPIkeyfromSerpApi
zh_Hans:从SerpApi获取您的SerpApiAPIkey
url:https://serpapi.com/manage-api-key
3.1.3 准备工具 YAML
identity:
name:google_search
author:Dify
label:
en_US:GoogleSearch
zh_Hans:谷歌搜索
description:
human:
en_US:AtoolforperformingaGoogleSERPsearchandextractingsnippetsandwebpages.
zh_Hans:一个用于执行GoogleSERP搜索并提取片段和网页的工具。
llm:AtoolforperformingaGoogleSERPsearchandextractingsnippetsandwebpages.
parameters:
-name:query
type:string
required:true
label:
en_US:Querystring
zh_Hans:查询语句
human_description:
en_US:usedforsearching
zh_Hans:用于搜索网页内容
llm_description:keywordsforsearching
form:llm
-name:result_type
type:select
required:true
options:
-value:text
label:
en_US:text
zh_Hans:文本
-value:link
label:
en_US:link
zh_Hans:链接
default:link
label:
en_US:Resulttype
zh_Hans:结果类型
human_description:
en_US:usedforselectingtheresulttype,textorlink
zh_Hans:用于选择结果类型,使用文本还是链接进行展示
form:form
3.1.4 准备工具代码
from core.tools.tool.builtin_tool import BuiltinTool
from core.tools.entities.tool_entities import ToolInvokeMessage
from typing import Any, Dict, List, Union
class GoogleSearchTool(BuiltinTool):
def _invoke(self,
user_id: str,
tool_parameters: Dict[str, Any],
) -> Union[ToolInvokeMessage, List[ToolInvokeMessage]]:
"""
invoke tools
"""
query = tool_parameters['query']
result_type = tool_parameters['result_type']
api_key = self.runtime.credentials['serpapi_api_key']
result = SerpAPI(api_key).run(query, result_type=result_type)
if result_type == 'text':
return self.create_text_message(text=result)
return self.create_link_message(link=result)
3.1.5 准备供应商代码
from core.tools.provider.builtin_tool_provider import BuiltinToolProviderController
from core.tools.errors import ToolProviderCredentialValidationError
from core.tools.provider.builtin.google.tools.google_search import GoogleSearchTool
from typing import Any, Dict
class GoogleProvider(BuiltinToolProviderController):
def _validate_credentials(self, credentials: Dict[str, Any]) -> None:
try:
GoogleSearchTool().fork_tool_runtime(
meta={
"credentials": credentials,
}
).invoke(
user_id='',
tool_parameters={
"query": "test",
"result_type": "link"
},
)
except Exception as e:
raise ToolProviderCredentialValidationError(str(e))
3.2 高级接入
高级接入适用于复杂工具的开发,支持多种消息类型、变量池和工具链的构建。
3.2.1 多种消息类型
Dify 工具系统支持多种消息类型,包括文本、图片、链接、文件 BLOB 和 JSON。

示例代码:
# 返回文本消息
self.create_text_message(text="Hello, world!")
# 返回图片消息
self.create_image_message(image="https://example.com/image.png")
# 返回链接消息
self.create_link_message(link="https://example.com")
# 返回文件 BLOB 消息
self.create_blob_message(blob=binary_data, meta={"mime_type": "image/png"})
# 返回 JSON 消息
self.create_json_message(object={"key": "value"})
3.2.2 变量池机制
变量池是工具系统中的一个重要组件,用于在工具之间共享数据。它允许一个工具生成的数据被另一个工具使用,从而构建复杂的工具链。

示例代码(DallE3 生成图片并保存到变量池):
# 将图片保存到变量池
self.create_blob_message(
blob=b64decode(image.b64_json),
meta={"mime_type": "image/png"},
save_as=self.VARIABLE_KEY.IMAGE.value
)
示例代码(Vectorizer.AI 从变量池获取图片):
# 从变量池获取图片
image_binary = self.get_variable_file(self.VARIABLE_KEY.IMAGE)
if not image_binary:
return self.create_text_message("Image not found")
# 处理图片
response = post(
"https://vectorizer.ai/api/v1/vectorize",
files={"image": image_binary},
data={"mode": "test"},
auth=(api_key_name, api_key_value),
timeout=30
)
3.2.3 动态参数生成
工具可以根据当前变量池中的数据动态生成参数列表,使 LLM 能够根据实际情况选择合适的参数。
def get_runtime_parameters(self) -> List[ToolParameter]:
"""
override the runtime parameters
"""
return [
ToolParameter.get_simple_instance(
name="image_id",
llm_description="the image id that you want to vectorize",
type=ToolParameter.ToolParameterType.SELECT,
required=True,
options=[i.name for i in self.list_default_image_variables()]
)
]
3.2.4 工具可用性控制
工具可以根据当前变量池中的数据决定自己是否可用,避免在不适合的情况下被调用。
def is_tool_available(self) -> bool:
# 只有当变量池中有图片时,工具才可用
return len(self.list_default_image_variables()) > 0
4、工具系统工作流程

4.1 工具调用过程
-
用户发送请求到 Agent 或工作流
-
Agent 或工作流通过 ToolManager 获取工具运行时
-
ToolManager 获取工具提供者和工具实例
-
ToolManager 创建工具运行时,包括加载凭据和变量池
-
Agent 或工作流调用工具
-
工具执行逻辑,可能会保存结果到变量池
-
工具返回结果给 Agent 或工作流
-
Agent 或工作流返回响应给用户
4.2 变量池使用过程
-
工具 A 执行逻辑,生成结果
-
工具 A 将结果保存到变量池
-
工具 B 从变量池获取工具 A 的结果
-
工具 B 使用工具 A 的结果执行自己的逻辑
5、总结
Dify 的工具架构设计充分考虑了灵活性和可扩展性,通过配置驱动开发、变量池机制、动态参数生成和工具可用性控制等技术,使开发者能够快速构建从简单到复杂的各类工具。特别是变量池机制,为构建复杂工具链提供了强大支持,使得多个工具可以协同工作,完成更复杂的任务。
参考资料
https://github.com/langgenius/dify (v0.6.3)
更多推荐


所有评论(0)