【免费下载链接】nexent
Nexent is a zero-code platform for auto-generating production-grade AI agents using Harness Engineering principles — unified tools, skills, memory, and orchestration with built-in constraints, feedback loops, and control planes.
导读
Nexent 是一个基于 Harness Engineering 原则、用于自动生成生产级 AI Agent 的零代码平台。本文档聚焦其 Python SDK(sdk/nexent)中工具(Tool)开发的全套规范与最佳实践:包括内置工具的全景分类、工具类的共性架构与核心属性、基于 MessageObserver 的消息流式处理机制、命名与 tool_sign 标识符约定、可复用的代码结构模板,以及开发流程、安全与性能最佳实践。读完本文,你将掌握在 Nexent SDK 中从零编写一个与内置工具保持一致规范、支持中英双语、具备流式输出能力并可通过 core_agent.py 桥接集成到 Agent 运行时的完整工具开发方法论。
本文以 doc/docs/en/sdk/core/tools.md 为骨架,结合
sdk/nexent/core/tools/目录下的真实实现、core_agent.py 的桥接逻辑以及test/sdk/core/tools/下的单元测试进行纵深印证,保证每个结论都有源码级依据。
一、工具全景:Nexent SDK 内置工具分类
Nexent SDK 的内置工具按功能划分为九大类。除少数系统内部管理的工具外,大部分工具统一在 sdk/nexent/core/tools/init.py 中导出,供 Agent 运行时装配。以下是原文档与源码双重印证下的完整分类:
搜索工具(Search Tools)
面向公网与私域数据的检索类工具,统一使用 SearchResultTextMessage 结构化输出,并携带 tool_sign 以便前端引用标签(如 [b0]、[a1])区分检索来源:
- ExaSearchTool:基于 EXA API 的 Web 搜索工具,实现见 exa_search_tool.py
- TavilySearchTool:基于 Tavily API 的 Web 搜索工具,实现见 tavily_search_tool.py
- LinkupSearchTool:基于 Linkup API 的搜索工具
- KnowledgeBaseSearchTool:本地知识库(向量库)检索工具,实现见 knowledge_base_search_tool.py
- RAGFlowSearchTool:RAGFlow 知识检索
- HaotianSearchTool / IndependentAidpSearchTool / AidpSearchTool / DifySearchTool / DataMateSearchTool / IdataSearchTool:企业级检索源接入,分别对接浩天、独立 AIDP、AIDP、Dify、DataMate、iData 等平台
其中 AidpSearchTool 位于 sdk/nexent/core/ext_components/aidp/aidp_search_tool.py,与其余搜索工具解耦存放。
文件管理工具(File Management Tools)
围绕工作空间文件系统的全套操作,统一以 tool_sign = ToolSign.FILE_OPERATION.value 标记:
- CreateFileTool:创建带内容的文件
- ReadFileTool:从文件系统读取文件内容
- DeleteFileTool:删除文件
- MoveItemTool:移动或重命名文件/目录
- CreateDirectoryTool:创建目录
- DeleteDirectoryTool:删除目录及其内容
- ListDirectoryTool:列出目录内容及详细信息
系统工具(System Tools)
- TerminalTool:通过 SSH 执行 shell 命令并管理系统操作,支持会话管理以跨命令保持 shell 状态(见 terminal_tool.py)
通信工具(Communication Tools)
- GetEmailTool:基于 IMAP 的邮件获取
- SendEmailTool:基于 SMTP 的邮件发送
多模态工具(Multimodal Tools)
- AnalyzeTextFileTool:基于数据处理与大语言模型的文档问答工具
- AnalyzeImageTool:基于视觉语言模型(VLM)的图片问答工具
- AnalyzeAudioTool:基于语音模型的音频理解工具
- AnalyzeVideoTool:基于视觉语言模型的视频理解工具
这些工具的提示词模板位于 sdk/nexent/core/prompts/(如 analyze_image_zh.yaml、analyze_video_en.yaml 等,均提供中英双语版本)。
记忆工具(Memory Tools)
- StoreMemoryTool:将重要信息写入当前 Agent 的短期记忆(
MemoryLayer.AGENT+MemoryType.SHORT_TERM),单次运行最多写入 3 条。源码中通过self.max_stores_per_run = 3强制限制(见 store_memory_tool.py) - SearchMemoryTool:以自然语言查询检索当前 Agent 的记忆,
top_k默认为 5(见 search_memory_tool.py)
值得关注的是,search_memory_tool.py 在运行时优先通过 MemoryContextService.build_context 走 Phase 4 检索流水线(分数融合、时间衰减、MMR 去重、token 预算选择),未配置时降级为 SDK 直连 MemoryService 模式——这是"优雅降级"原则的典型实现。
编排工具(Orchestration Tools)
- ParallelExecutorTool:并发执行多个子 Agent 或工具调用,实现见 parallel_executor.py。它要求任务以二元组
(tool_or_agent, kwargs_dict)或三元组(tool_or_agent, kwargs_dict, result_key)传入,且同一次调用不能混用两种格式;timeout默认 120 秒、max_workers默认 4 - CreatePlanTool / UpdatePlanStepTool:计划待办事项(plan todo)的创建与更新,实现见 plan_tools.py
数据工具(Data Tools)
- MySqlTool / PostgreSqlTool / MsSqlTool:受控执行 SQL 查询,基类见 sdk/nexent/core/tools/sql_tools/sql_database_base_tool.py
- UploadToS3Tool / DownloadFromS3Tool:S3 对象的上传与下载
技能与任务工具(系统内部管理,Skill and Task Tools)
- ReadSkillConfigTool / ReadSkillMdTool:读取技能目录下的
config.yaml与SKILL.md - RunSkillScriptTool:执行技能脚本
- WriteSkillFileTool:写入租户隔离的技能目录文件
- CreateScheduledTaskProposalTool:创建待用户确认的定时任务提案(仅保存提案,不执行业务任务)
注意:上述系统内部工具不在 sdk/nexent/core/tools/init.py 中统一导出,由系统在运行时按需装配。
二、工具共性特征:四层基础架构
无论哪种工具,Nexent SDK 都遵循同一套基础架构约定:
1. 基类继承
所有工具必须继承 smolagents.tools.Tool。例如 exa_search_tool.py 第 18 行 class ExaSearchTool(Tool)。这使工具天然兼容 smolagents 的 CodeAgent 工具注册表,可被直接注入 Agent 运行环境。
2. 参数管理
使用 pydantic.Field 定义构造参数并进行验证。例如 ExaSearchTool 的 max_results 声明了 ge=1, le=100 的范围约束,pydantic_utils.py 中的 unwrap_field_info 负责把 smolagents 传入的 FieldInfo 解包为声明默认值。工具的真实参数如 exa_api_key、tavily_api_key、ssh_host、password 等都通过构造器注入——SDK 层不直接读取环境变量,环境变量由服务层读取后再传入(原文档"注意事项"第 4 条对此有明确规定)。
3. 流式输出
集成 MessageObserver 实现实时消息传递。MessageObserver 的实现见 sdk/nexent/core/utils/observer.py:它维护一个线程安全的 message_query 队列,工具通过 observer.add_message(...) 将各类消息推入队列,由 Agent 运行时流式桥接层消费并推送给前端。MessageObserver 还内置了 ANSI 转义序列清洗(_ANSI_ESCAPE_PATTERN),避免终端 traceback 的 [31m 等控制字符污染 JSON/SSE 协议输出。
4. 多语言支持
内置中英文双语提示:类属性 description(英文)与 description_zh(中文)、init_param_descriptions 中每个构造参数的 description / description_zh,以及 observer.lang 驱动的运行时提示语选择。
三、核心属性清单
每个工具类必须声明以下类属性(原文档完整示例):
class ToolExample(Tool):
name = "tool_name" # Tool unique identifier
description = "Tool function description" # Detailed feature description (English)
description_zh = "工具功能描述" # Detailed feature description (Chinese)
inputs = { # Input parameter definition
"param": {
"type": "string",
"description": "Parameter description",
"description_zh": "参数描述"
}
}
init_param_descriptions = { # Constructor parameter descriptions (corresponding to __init__ parameters)
"config_param": {"description": "Config parameter description", "description_zh": "配置参数说明"}
}
output_type = "string" # Output type
category = "search" # Tool category (ToolCategory enum value)
tool_sign = "b" # Tool identifier (ToolSign enum value)
各字段职责:
name:工具在 Agent 环境中的唯一调用标识(如exa_search、terminal),模型据此发起调用;inputs:声明 forward 的输入参数结构(type/description/description_zh/default/nullable),会注入系统提示词供 LLM 理解参数语义;output_type:forward 的返回类型,搜索类工具统一返回 JSON 字符串;category:取自ToolCategory枚举(见下文);tool_sign:取自ToolSign枚举,用于前端引用标签区分检索来源。
ToolCategory 与 ToolSign 两个枚举统一定义在 sdk/nexent/core/utils/tools_common_message.py:
class ToolCategory(Enum):
SEARCH = "search"
FILE = "file"
EMAIL = "email"
TERMINAL = "terminal"
MULTIMODAL = "multimodal"
DATABASE = "database"
MEMORY = "memory"
SKILL = "skill"
PLANNING = "planning"
四、消息处理机制:Observer 模式与 TOOL 桥接
ProcessType 枚举
消息类型由 ProcessType 枚举统一管理,除文档列出的 TOOL、CARD、SEARCH_CONTENT、PICTURE_WEB 外,observer.py 中还包含 FINAL_ANSWER、EXECUTION_LOGS、SUBAGENT_START/END、PLAN、PLAN_STEP_UPDATE、AUTOMATION_PROPOSAL、MEMORY_SEARCH、VERIFICATION 等 30 余种类型,覆盖模型流式输出、子 Agent 边界、计划状态、定时任务提案等全部运行时事件。每种类型在 MessageObserver._init_message_transformers() 中映射一个消息转换器(如 StepCountTransformer、ExecutionLogsTransformer),转换后再以统一 JSON 格式推入队列,Message 类负责将类型、内容、工具元数据(tool_name、tool_arguments、tool_call_id)、子 Agent 归属(agent_id、agent_name、depth、invocation_id)序列化为 JSON。
TOOL 消息的统一发送:core_agent 桥接
这是新版 SDK 最重要的架构约定:工具自身不再发送 ProcessType.TOOL 运行状态消息,而是由 core_agent.py 中的 _wrap_tool_for_observer 桥接(第 477-509 行)在每次工具被调用时统一发送,并附带 tool_call_id 用于上下文关联:
def _wrap_tool_for_observer(tool, observer, agent_name) -> None:
...
def observed_forward(*args, **kwargs):
tool_call_id = str(uuid.uuid4())
observer.add_message(
agent_name or "",
ProcessType.TOOL,
"",
tool_name=tool_name,
tool_arguments=_observer_call_arguments(tool, args, kwargs),
tool_call_id=tool_call_id,
)
with observer.tool_call_context(tool_call_id):
return original_forward(*args, **kwargs)
tool.forward = observed_forward
桥接在 _wrap_visible_tool_events()(第 662-673 行)中对所有可见工具逐一打包装饰,MessageObserver.tool_call_context 通过 ContextVar 把 tool_call_id 与当前工具调用关联,工具内部通过 observer.add_message 发出的补充消息(CARD、SEARCH_CONTENT、PICTURE_WEB 等)也会自动带上该调用上下文,从而保证前端对工具调用的全过程追踪一致。
遗留约定:部分早期工具(如 SQL 工具基类 sql_database_base_tool.py)仍保留 running_prompt_zh/en 属性并在工具内部发送 TOOL 消息;新开发的工具不应再使用该模式,仅发送补充消息即可。
消息格式
所有消息内容使用 JSON 格式。搜索工具通过 SearchResultTextMessage(定义于 tools_common_message.py)统一封装搜索结果,其 to_dict() 保存全量数据(供前端渲染),to_model_dict() 生成喂给大模型摘要的紧凑格式——其中 index = f"{self.tool_sign}{self.cite_index}",即前端引用标签 [b0]、[a1] 的生成源头,reference_mark 为 [[b0]] 形式的引用标记。
五、命名规范
文件命名
- 格式:
{功能名}_tool.py - 风格:小写字母、下划线连接
- 示例:
exa_search_tool.py、knowledge_base_search_tool.py
类命名
- 格式:
{功能名}Tool - 风格:PascalCase(大驼峰)
- 示例:
ExaSearchTool、KnowledgeBaseSearchTool
属性和方法命名
- 格式:小写字母、下划线连接
- 私有方法:以单下划线开头(如
_filter_images、_decode_subject、_format_result) - 示例:
max_results、description_zh、record_ops
tool_sign 标识符约定
tool_sign 是单字母标识符,用于在总结与前端引用标签中区分工具来源。取值必须来自 tools_common_message.py 的 ToolSign 枚举,完整分配规则(以源码第 7-26 行为准):
| 字母 | 枚举成员 | 用途 |
|---|---|---|
a | KNOWLEDGE_BASE | 知识库搜索(KnowledgeBaseSearchTool) |
b | EXA_SEARCH | EXA 搜索(ExaSearchTool) |
c | LINKUP_SEARCH | Linkup 搜索(LinkupSearchTool) |
d | TAVILY_SEARCH | Tavily 搜索(TavilySearchTool) |
e | DATAMATE_SEARCH | DataMate 搜索 |
f | FILE_OPERATION | 文件操作 |
g | DIFY_SEARCH | Dify 搜索 |
h | IDATA_SEARCH | iData 搜索 |
i | HAOTIAN_SEARCH | Haotian 搜索 |
j | AIDP_SEARCH | AIDP 搜索 |
k | RAGFLOW_SEARCH | RAGFlow 搜索 |
l | INDEPENDENT_AIDP_SEARCH | 独立 AIDP 搜索 |
m | MULTIMODAL_OPERATION | 多模态操作 |
n | MEMORY_OPERATION | 记忆操作 |
p | PLAN_OPERATION | 计划/步骤状态工具 |
s | SKILL_OPERATION | 技能脚本/文件工具 |
t | TERMINAL_OPERATION | 终端操作 |
z | DATABASE_OPERATION | 数据库操作 |
源码同时维护了 TOOL_SIGN_MAPPING(工具名→字母)与 REVERSE_TOOL_SIGN_MAPPING(字母→工具名)用于向后兼容与反向查询。
六、代码结构模板
基础工具模板
以下模板完整继承自原文档,并结合源码补充了 category/tool_sign 赋值与注释说明,可直接复制落地:
import json
import logging
from typing import Optional
from smolagents.tools import Tool
from pydantic import Field
from ..utils.observer import MessageObserver, ProcessType
from ..utils.tools_common_message import ToolCategory, ToolSign
logger = logging.getLogger("your_tool_name")
class YourTool(Tool):
name = "your_tool"
description = "Detailed description of the tool function, including applicable scenarios and usage"
description_zh = "工具功能的中文描述,说明适用场景和使用方法"
inputs = {
"param1": {
"type": "string",
"description": "Detailed description of parameter 1",
"description_zh": "参数1的中文描述"
},
"param2": {
"type": "integer",
"description": "Detailed description of parameter 2",
"description_zh": "参数2的中文描述",
"default": 10,
"nullable": True
}
}
init_param_descriptions = { # Constructor parameter descriptions (corresponding to __init__ parameters)
"config_param": {"description": "Config parameter description", "description_zh": "配置参数说明"},
"optional_param": {"description": "Optional parameter description", "description_zh": "可选参数说明"}
}
output_type = "string"
category = ToolCategory.FILE.value # Choose the ToolCategory enum member by tool type
tool_sign = ToolSign.FILE_OPERATION.value # Choose the ToolSign enum member by tool type
def __init__(
self,
config_param: str = Field(description="Config parameter"),
observer: MessageObserver = Field(description="Message observer", default=None, exclude=True),
optional_param: int = Field(description="Optional parameter", default=5)
):
super().__init__()
self.config_param = config_param
self.observer = observer
self.optional_param = optional_param
# Record operation sequence (if needed)
self.record_ops = 0
def forward(self, param1: str, param2: int = 10) -> str:
"""Main execution method of the tool
Args:
param1: Parameter 1 description
param2: Parameter 2 description
Returns:
JSON format string result
Raises:
Exception: Detailed error information
"""
try:
# Send card information (optional)
if self.observer:
card_content = [{"icon": "your_icon", "text": param1}]
self.observer.add_message("", ProcessType.CARD,
json.dumps(card_content, ensure_ascii=False))
# Main business logic
result = self._execute_main_logic(param1, param2)
# Process result and return
return self._format_result(result)
except Exception as e:
logger.error(f"Error in {self.name}: {str(e)}")
raise Exception(f"Error executing {self.name}: {str(e)}")
def _execute_main_logic(self, param1: str, param2: int):
"""Private method for executing main business logic"""
# Implement specific business logic
pass
def _format_result(self, result) -> str:
"""Format return result"""
formatted_result = {
"status": "success",
"data": result,
"tool": self.name
}
return json.dumps(formatted_result, ensure_ascii=False)
模板要点(与真实实现的对照):
observer参数必须声明exclude=True,确保它不作为工具参数暴露给 LLM(所有内置工具如 exa_search_tool.py、terminal_tool.py 均如此);record_ops用于记录操作序号,在搜索类工具中作为引用序号(cite_index)的累加起点;- 异常统一抛
Exception并记录日志,错误信息包含{self.name}便于定位。
搜索工具模板
搜索类工具在基础模板之上叠加 SearchResultTextMessage 统一结果封装与 SEARCH_CONTENT 消息推送:
import json
import logging
from typing import List
from smolagents.tools import Tool
from pydantic import Field
from ..utils.observer import MessageObserver, ProcessType
from ..utils.tools_common_message import SearchResultTextMessage, ToolCategory, ToolSign
logger = logging.getLogger("search_tool_name")
class SearchTool(Tool):
name = "search_tool"
description = "Detailed description of the search tool, including search scope and applicable scenarios"
description_zh = "搜索工具的中文描述,包括搜索范围和适用场景"
inputs = {
"query": {"type": "string", "description": "The search query to perform", "description_zh": "搜索查询词"},
"max_results": {"type": "integer", "description": "Maximum number of results", "description_zh": "最大结果数", "default": 5, "nullable": True}
}
init_param_descriptions = { # Constructor parameter descriptions (corresponding to __init__ parameters)
"api_key": {"description": "API key", "description_zh": "API密钥"}
}
output_type = "string"
category = ToolCategory.SEARCH.value
tool_sign = ToolSign.EXA_SEARCH.value # Choose the ToolSign enum member by actual search source
def __init__(
self,
api_key: str = Field(description="API key"),
observer: MessageObserver = Field(description="Message observer", default=None, exclude=True),
max_results: int = Field(description="Maximum number of search results", default=5)
):
super().__init__()
self.api_key = api_key
self.observer = observer
self.max_results = max_results
# Citation index starts from 1 (used by SearchResultTextMessage's cite_index)
self.record_ops = 1
def forward(self, query: str, max_results: int = None) -> str:
if max_results is None:
max_results = self.max_results
# Send card information (optional; TOOL running status messages are sent uniformly by the core_agent bridge)
if self.observer:
card_content = [{"icon": "search", "text": query}]
self.observer.add_message("", ProcessType.CARD,
json.dumps(card_content, ensure_ascii=False))
try:
# Execute search
search_results = self._perform_search(query, max_results)
if not search_results:
raise Exception("No search results found! Please try shorter or broader queries.")
# Format search results
formatted_results = self._format_search_results(search_results)
# Record search content
if self.observer:
search_results_data = json.dumps(formatted_results["json"], ensure_ascii=False)
self.observer.add_message("", ProcessType.SEARCH_CONTENT, search_results_data)
return json.dumps(formatted_results["return"], ensure_ascii=False)
except Exception as e:
logger.error(f"Search error: {str(e)}")
raise Exception(f"Search failed: {str(e)}")
def _perform_search(self, query: str, max_results: int):
"""Execute actual search operation"""
# Implement specific search logic
pass
def _format_search_results(self, results):
"""Format search results into unified format"""
search_results_json = []
search_results_return = []
for index, result in enumerate(results):
search_result_message = SearchResultTextMessage(
title=result.get("title", ""),
url=result.get("url", ""),
text=result.get("content", ""),
published_date=result.get("date", ""),
source_type="url",
filename="",
score=result.get("score", ""),
score_details=result.get("score_details", {}),
cite_index=self.record_ops + index,
search_type=self.name,
tool_sign=self.tool_sign
)
search_results_json.append(search_result_message.to_dict())
search_results_return.append(search_result_message.to_model_dict())
self.record_ops += len(search_results_return)
return {
"json": search_results_json,
"return": search_results_return
}
以真实的 exa_search_tool.py 为参照,其 forward 的具体实现展示了搜索模板的完整落地形态:调用 Exa.search_and_contents 后,逐条构造 SearchResultTextMessage,同时把 PICTURE_WEB 图片列表通过 _filter_images 交给数据处理服务(/tasks/filter_important_image)过滤(负向提示词为 "logo or banner or background or advertisement or icon or avatar"),过滤失败时优雅降级为直接发送未过滤的图片 URL 列表。单元测试见 test/sdk/core/tools/test_exa_search_tool.py,通过模块级 mock(patch.dict('sys.modules', ...))隔离 exa_py 与 aiohttp 依赖,验证了工具在无真实网络环境下的行为。
七、开发流程规范
1. 开发前准备
- 确定工具功能与适用场景;
- 选择合适的工具分类(
ToolCategory)与标识符(ToolSign); - 检查是否与现有工具功能重复(对照 tools/init.py 的既有导出清单)。
2. 实现步骤
- 创建工具文件:按命名规范创建
{name}_tool.py; - 定义类结构:继承
Tool基类,定义必要类属性(name、description、inputs、output_type、category、tool_sign等); - 实现构造函数:用
pydantic.Field定义参数,observer参数exclude=True; - 实现
forward方法:核心功能逻辑,返回 JSON 字符串; - 添加私有方法:将复杂逻辑拆分为
_开头的私有方法(如_perform_search、_format_result); - 集成 MessageObserver:按需发送
CARD、SEARCH_CONTENT、PICTURE_WEB等补充消息,支持流式输出与多语言; - 异常处理:完善错误处理与日志记录(
logger = logging.getLogger("your_tool_name"))。
3. 测试与集成
- 单元测试:测试各种输入场景与边界条件。仓库内每个工具都有对应测试,如 test_terminal_tool.py、test_store_memory_tool.py、test_knowledge_base_search_tool.py、SQL 工具测试位于 test/sdk/core/tools/sql_tools/;
- 集成测试:与
CoreAgent(core_agent.py)集成,验证 TOOL 桥接与流式消息链路; - 更新导出:在 tools/init.py 的导入与
__all__中登记新工具(系统内部管理的技能/任务类工具除外); - 文档更新:更新相关文档与示例(如 tools/README.md 及其英文版 README_EN.md)。
八、最佳实践
1. 性能优化
- 异步处理:耗时操作使用异步。如 exa_search_tool.py 的
_filter_images用asyncio.gather并发处理图片;记忆工具通过_run_coroutine将协程调度到受管线程管理器(get_current_thread_manager)执行; - 连接池:复用网络连接。Exa/Tavily 工具复用
aiohttp.TCPConnector(limit=0),SQL 工具复用数据库连接; - 缓存机制:适当使用缓存提升响应速度;
- 并发控制:用
Semaphore控制并发请求数(图片过滤设置asyncio.Semaphore(10),ParallelExecutorTool通过max_workers控制线程数)。
2. 安全性
- 输入验证:严格验证输入参数。SQL 工具在 sql_database_base_tool.py 中内置
HIGH_RISK_SQL_PATTERNS黑名单(DROP DATABASE、GRANT、REVOKE、CREATE USER、INTO OUTFILE、LOAD DATA INFILE、EXEC xp_等),并强制UPDATE/DELETE语句必须包含WHERE子句(否则抛出MISSING_WHERE安全拦截异常); - 敏感信息:API 密钥等敏感信息不得出现在日志中——注意 exa_search_tool.py 与 terminal_tool.py 的日志只记录事件类型与状态,不打印密钥;
store_memory日志记录的是content_length而非内容本身; - 错误信息:避免在错误消息中泄露敏感信息;
- 超时控制:设置合理超时。SQL 查询默认
timeout=10秒、max_rows=100;TerminalTool命令默认超时 30 秒;SSH 连接超时 10 秒。
3. 可维护性
- 模块化设计:复杂功能拆分为多个方法;
- 清晰注释:为复杂逻辑添加详细注释(真实实现中注释密度很高);
- 类型注解:使用完整类型注解(如
Optional[List[Any]]、Dict[str, Any]); - 文档字符串:为所有公共方法添加 docstring(含 Args/Returns/Raises)。
4. 用户体验
- 多语言支持:中英文双语提示(
description_zh、init_param_descriptions双语描述、双语 prompts 位于 sdk/nexent/core/prompts/); - 进度反馈:通过
MessageObserver提供实时反馈(卡片消息、搜索内容流、图片流); - 错误提示:提供清晰错误信息与解决建议(如 "No results found! Try a less restrictive/shorter query."、知识库搜索的 "NOTICE" 提示,见 knowledge_base_search_tool.py 中
build_knowledge_search_response对权限过滤/范围回退的模型侧说明); - 参数验证:执行前验证参数有效性(
ge/le范围约束、unwrap_field_info解包默认值)。
九、重要注意事项
- 版本兼容:确保工具兼容不同版本的依赖库(如 smolagents、pydantic、aiohttp);
- 资源清理:及时释放网络连接、文件句柄等资源。
TerminalTool._cleanup_session负责关闭 SSH channel 与 client,并实现了会话保活检测(_is_session_alive),发现连接失效自动重建; - 日志级别:合理设置日志级别,避免过多调试信息(如
_filter_images中对图片过滤异常使用logger.info而非logger.error以避免噪音); - 配置管理:所有配置通过构造参数传入,SDK 不直接读环境变量(
DATA_PROCESS_SERVICE等环境变量由服务层读取后传入); - 错误恢复:尽可能提供错误恢复机制。记忆工具在存储超限时返回 "Information will be saved automatically at the end." 的降级提示;图片过滤失败时回退为发送未过滤图片列表;
SearchMemoryTool在流水线异常时返回 "Continuing without memory results." 而非中断 Agent。
遵循以上规范,新工具将与现有工具保持高度一致,具备良好的可维护性与可扩展性,并能无缝接入 Nexent Agent 运行时的消息流、引用标注与前端渲染链路。
关键源码索引
- 工具实现目录:sdk/nexent/core/tools/(含
sql_tools/子目录) - 工具统一导出:sdk/nexent/core/tools/init.py
- 枚举与统一消息模型:sdk/nexent/core/utils/tools_common_message.py
- 消息观察者与 ProcessType:sdk/nexent/core/utils/observer.py
- TOOL 桥接与 Agent 装配:sdk/nexent/core/agents/core_agent.py
- AIDP 搜索工具(独立目录):sdk/nexent/core/ext_components/aidp/aidp_search_tool.py
- 多模态提示词:sdk/nexent/core/prompts/
- 工具单元测试:test/sdk/core/tools/
- 中文版工具规范:sdk/nexent/core/tools/README.md 与 README_EN.md
【免费下载链接】nexent
Nexent is a zero-code platform for auto-generating production-grade AI agents using Harness Engineering principles — unified tools, skills, memory, and orchestration with built-in constraints, feedback loops, and control planes.
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



