agenticSeek 贡献指南:Tools 与 Agent 的开发实战、架构原理与代码贡献规范
【免费下载链接】agenticSeekFully Local Manus AI. No APIs, No $200 monthly bills. Enjoy an autonomous agent that thinks, browses the web, and code for the sole cost of electricity.项目地址: https://gitcode.com/GitHub_Trending/ag/agenticSeek
导读
本文以 agenticSeek 官方贡献指南 docs/CONTRIBUTING.md 为主线,系统讲解如何为这个"完全本地化"的 AI Agent 项目贡献代码:从环境准备、分支提交流程,到 Tools(工具)与 Agent(智能体)两大核心扩展机制的完整实现原理。读完本文,你将掌握 block 解析协议、三个抽象方法的实现要点、把新工具挂载到 Agent 的三步法,以及 Agent 路由系统(含 planner 分治调度)的底层工作方式,并能在本地独立编写、测试和提交新的工具与 Agent。
环境准备:贡献前需要具备的条件
按照官方指南,参与贡献前需确认本地环境满足以下前提(详见 docs/CONTRIBUTING.md):
| 依赖 | 说明 |
|---|---|
| Python 3.10+ | 项目后端全部基于 Python,要求 3.10 或更高版本,见 pyproject.toml 与 setup.py |
| Docker / Orbstack / Podman | 用于拉起 LLM 推理服务(llm_server/Dockerfile)与 searxng 搜索实例(searxng/docker-compose.yml) |
| Ollama + deepseek-r1 变体 | 需要本地推理模型,Ollama至少安装一个 deepseek-r1 系列或同类本地推理模型(reasoning model) |
| Python 与 AI 模型基础 | 需要基本熟悉 Python 与 LLM 推理概念 |
| Discord(可选) | 官方指南提供社区 Discord 入口,非必选项 |
从仓库结构看,路由、TTS/STT、记忆、Web 浏览器控制等模块分布在 sources 目录下,每个类文件底部都带有if __name__ == "__main__"独立测试入口,这既是项目约定,也是贡献者本地验证的最小抓手(参见 sources/tools/tools.py 的示例)。
贡献方向与标准流程
欢迎的贡献类型
官方指南明确欢迎以下四类贡献:
- Code Improvements:优化既有代码、修复 bug 或添加新功能;
- Documentation:完善 README、撰写教程、补充行内注释;
- Testing:编写单元测试、集成测试,或协助调试;仓库 tests 目录已沉淀了大量测试用例(如 tests/test_tools_parsing.py、tests/test_planner_agent_parsing.py),新功能提交时应参照这些测试的写法补齐覆盖;
- New Features:实现新的工具(Tools)、新的 Agent 或新的集成。
标准提交流程
按指南的"Steps to Contribute",标准流程为:Fork → 建分支 → 修改 → 测试 → 提交 PR:
# 1. Fork 项目到你自己的 GitHub 账户 # 2. 创建功能分支 git checkout -b feature/your-feature-name # 3. 编写代码、文档或修复 bug # 4. 测试你的改动,确保不破坏既有功能 # 5. 推送分支并提交 Pull Request 到主分支 # 在 PR 描述中清晰说明改动内容,并关联相关 issue仓库根目录提供了覆盖三大平台的安装入口(install.sh、install.bat、scripts/linux_install.sh、scripts/macos_install.sh、scripts/windows_install.bat),本地复现与回归测试时可参考。
核心贡献原则:Good Practice
官方指南提出了六条必须遵守的工程原则,这构成了 agenticSeek 的架构底线:
1. 隐私优先,永远本地(Privacy First, Always Local)
- 所有核心功能必须能够 100% 本地运行;
- 云服务只能作为可选的替代方案,且必须带有清晰的警告提示;
- 远程 API 仅允许用于特定工具(如天气 API、MCP、航班搜索等);
- 用户数据隐私不可妥协。
从源码看这一原则是落实在工具实现上的:例如 sources/tools/flightSearch.py 通过os.getenv("SERPAPI_API_KEY")读取密钥,未配置时execute直接返回"Error: No SerpApi key provided.",即"远程 API 是可选且显式声明"的体现。
2. 基于 Agent 的架构(Agent-Based Architecture)
- 每个 Agent 应有清晰、单一的责任;
- Agent 应当模块化且可独立测试;
- 新 Agent 应解决特定的用例。
仓库中 sources/agents 下的每个 Agent 都对应一个明确职责:casual_agent负责闲聊、code_agent负责写代码、file_agent负责文件操作、browser_agent负责上网、planner_agent负责任务规划(详见下文"架构总览")。
3. 基于工具的扩展性(Tool-Based Extensibility)
- 工具应当是自包含的,并继承
Tools基类; - 每个工具只做好一件事;
- 工具应对成功/失败给出清晰反馈。
4. 用户体验(User Experience)
- 对所有操作提供有意义的反馈;
- 支持多语言;
- 对简短响应启用文本转语音(Text to Speech);
- 保持响应简洁。
5. 代码质量(Code Quality)
- 编写清晰、自解释的代码;
- 包含类型注解(type hints)与 docstring;
- 遵循代码库中既有的模式;
- 每个类文件的底部添加
if __name__ == "__main__"用于单独测试; - 理想情况下要有自动化测试。
6. 错误处理(Error Handling)
- 优雅失败并给出有意义的错误信息;
- 尽可能包含恢复机制;
- 恰当记录错误日志,且不暴露敏感数据。
需要帮助的领域(Areas Needing Help)
官方指南列出的待贡献方向包括:
| 领域 | 说明 |
|---|---|
| Web Browsing | 提升助手自主上网浏览能力 |
| 图形界面 | Web 图形界面(需先询问) |
| 多 Agent 系统 | 增强 planner agent 的任务分治能力(需先询问) |
| New Tools | 增加更多编程语言或 API 支持 |
| MCP | 增加 MCP 协议兼容(可作为特殊类型的工具) |
| 多语言支持 | Text to speech 与 speech to text 的多语言 |
| Prompt engineering | 改进提示词,对同一 query 用不同 prompt 对比效果并迭代 |
| Bug hunt | 排查并修复 bug |
| Cross-platform | 增强跨平台支持 |
| Testing | 为现有功能编写全面测试 |
工具开发实战:从 block 协议到三个抽象方法
理解 block 解析协议
Agent 调用工具时使用一种标准化格式,称为block(代码块):即"工具名 + 反引号代码块"的组合。给 Agent 编写 prompt 时,必须明确告诉它使用这一格式。基本形式为:
```<tool name> <code or query to execute> ```实际示例:
```web_search What to do in Taipei? ```Tools基类通过load_exec_block方法从 Agent 的回复中提取并解析这些 block——识别工具名与内容,交给系统执行对应动作。其底层实现见 sources/tools/tools.py:该方法以```{self.tag}为起始标记、```为结束标记扫描整段文本,支持多个 block 的连续提取、块前导空白剥离,并在检测到:path语法时返回保存路径;若文本中不存在起始标记则直接返回(None, None)。注意load_exec_block前会断言self.tag != "undefined",即每个工具必须在__init__中设置自己的 tag(对应 tests/test_tools_parsing.py 中"tag 未定义抛 AssertionError"的用例)。
多参数如何处理?
每个工具都可以在 block 内按自己的方式处理参数,但基类提供了一套通用解析逻辑get_parameter_value(实现见 sources/tools/tools.py,按行扫描参数名=值格式并返回=右侧内容):
```trip_search from=Paris to=Toulouse ```每个工具可以自行决定参数处理逻辑,但Tools类保证了解析的一致性。如果某个工具需要特定格式,你也可以为它实现专门的解析方法——使用get_parameter_value是可选的。对应的单元测试覆盖了参数存在、缺失、多个参数等场景(tests/test_tools_parsing.py)。
block 内容保存到文件
block 的内容可以通过:path语法保存到文件。例如:
```python:toto.py print("Hello world") ```这段代码会被保存到config.ini中定义的work_folder工作目录下的toto.py文件。底层由save_block(sources/tools/tools.py)完成:它通过resolve_path将路径限定在隔离的 Agent 工作区内,防止路径逃逸,必要时自动创建目录,随后写入 block 内容。注意load_exec_block对首行含:的 block 会将其拆分为save_path(见 sources/tools/tools.py)。
工具实现的三个抽象方法
开发一个新工具时,必须实现Tools类中定义的三个抽象方法,以保证跨工具行为一致、并与 LLM 形成稳健交互(抽象方法定义见 sources/tools/tools.py):
1.execute方法
@abstractmethod def execute(self, blocks: [str], safety: bool) -> str:定义工具如何处理传入的 block(s) 并产出结果。例如航班工具FlightSearch.execute会解析航班号、调用 SerpApi 的 Google Flights 引擎并返回格式化的航班信息(sources/tools/flightSearch.py)。
2.execution_failure_check方法
@abstractmethod def execution_failure_check(self, output: str) -> bool:分析工具输出,判断执行是成功还是失败。例如FlightSearch.execution_failure_check检查输出是否以"Error"开头或包含"No flight information found"(sources/tools/flightSearch.py);而BashInterpreter则维护了一个包含failed、syntax、not found、segmentation fault等数十个关键词的错误模式正则表(sources/tools/BashInterpreter.py)。
3.interpreter_feedback方法
@abstractmethod def interpreter_feedback(self, output: str) -> str:为 LLM 生成反馈消息,帮助它理解工具执行结果并调整后续行为。BashInterpreter的反馈形如[success] Execution success, code output: ...或[failure] Error in execution: ...(sources/tools/BashInterpreter.py),这些反馈会被推入 Agent 的记忆,形成"执行-反馈-修正"闭环。
三个核心能力速查
| 方法/能力 | 作用 |
|---|---|
load_exec_block | 从 Agent 回复中提取并解析工具 block |
get_parameter_value | 从 block 内容中获取参数值 |
| 文件处理 | 指定:path时将 block 内容保存到文件 |
在 Prompt 中引导 Agent 使用工具
以给 casual agent 添加航班搜索工具为例:需要修改 CasualAgent 的 prompt 文件(如 prompts/base/casual_agent.txt),在其中明确告知 LLM 如何使用flight_search工具,例如向 prompt 追加:
You can search for flights using the flight_search tool. Example: ```flight_search RY7481 ``` You simply need to enter the flight number, you will then various informations about the flight if it exist, such as : Airline, Status, Departure time, Arrival Time把工具挂载到 Agent:三步法
官方指南给出把工具加入 Agent 的三个步骤:
- 导入工具类(Import a tool);
- 将工具实例加入tools字典;
- 更新 Agent 的 prompt。
代码示例(来自指南):
from sources.tools.flightSearch import FlightSearch class CasualAgent(Agent): def __init__(self, name, prompt_path, provider, verbose=False): super().__init__(name, prompt_path, provider, verbose, None) self.tools = { "flight_search": FlightSearch(), } self.role = "en" self.type = "casual_agent"仓库中的真实实现与此完全一致:CasualAgent的tools字典为空(sources/agents/casual_agent.py),而CoderAgent的tools字典则挂载了bash、python、c、go、java、file_finder六个工具(sources/agents/code_agent.py)。工具名(字典 key)必须与工具实例的tag对应,因为load_exec_block正是按```{tag}来匹配的。
Agent 开发实战:继承基类与实现 process
Agent 基类概览
Agent 是定义 LLM 如何与用户交互、如何处理输入的类。它们可以使用工具(执行代码、查询 API 等),并通过对话记忆(memory)提供上下文感知的响应。所有 Agent 都继承自基类Agent(sources/agents/agent.py),该基类提供记忆管理与 LLM 通信等核心能力。
最简单的 Agent 示例是 casual agent:
class CasualAgent(Agent): def __init__(self, name, prompt_path, provider, verbose=False): """ The casual agent is a special for casual talk to the user without specific tasks. """ super().__init__(name, prompt_path, provider, verbose, None) self.tools = { } # No tools for the casual agent self.role = "en" self.type = "casual_agent" def process(self, prompt, speech_module) -> str: self.memory.push('user', prompt) animate_thinking("Thinking...", color="status") answer, reasoning = self.llm_request() self.last_answer = answer return answer, reasoning注:仓库中的实际实现把
role设为了"talk"、type设为"casual_agent",并把process声明为async(sources/agents/casual_agent.py),指南中的示例为早期写法,以仓库源码为准。
Agent 的关键属性
每个 Agent 需要设置如下参数:
tools:Agent 可使用的工具字典。每个工具必须继承自Tools类。例如CasualAgent没有工具({}),而代码 Agent 可能包含 Python 执行工具;role:定义 Agent 角色的字典,路由系统用它来选择合适的 Agent。仓库中各 Agent 的 role 分别为:talk(casual)、code(coder)、files(file)、web(browser)、mcp(mcp)、planification(planner),见 sources/agents 各文件;type:Agent 类型,用于唯一标识 Agent 类型的固定名称(casual_agent、code_agent、file_agent、browser_agent、mcp_agent、planner_agent)。
process 方法的工作流
每个 Agent 必须实现process方法,它定义了 Agent 如何处理用户输入并生成响应。标准工作流:
- 用
self.memory.push('user', prompt)将用户 prompt 推入 Agent 记忆; - 调用
self.llm_request()基于记忆上下文生成响应与推理(reasoning); - 存储并返回响应与推理。
注意记忆逻辑的约定:你只需 push'user'消息,llm_request会自动负责 push assistant 消息。从源码看,sync_llm_request在拿到 LLM 响应后会将答案中<think>...</think>推理段剥离(extract_reasoning_text/remove_reasoning_text),并把剥离后的回答 push 进记忆(sources/agents/agent.py)。指南也指出,这种"用户/助手消息记忆处理分离"的做法目前可能不一致,未来可能重构以提升清晰度。
工具 block 的执行:execute_modules
Agent 的回复中可能包含一连串待执行的工具 block。例如 coding agent 的回复可能是:
I will create a work folder: ```bash mkdir myAGI ``` I will enter the folder. ```bash cd myAGI ``` I will create a python code. ```python:myAGI/super_smart.py <python code> ```execute_modules方法能自动查找、解析并执行 LLM prompt 中的所有工具:
def execute_modules(self, answer: str) -> Tuple[bool, str]:它会在 Agent 回复中寻找所有工具 "block",执行对应工具,并返回(success, feedback)元组。底层实现(sources/agents/agent.py)逐个遍历self.tools字典:对每个工具调用load_exec_block解析,再对每个 block 依次执行tool.execute→tool.interpreter_feedback→tool.execution_failure_check;若某个 block 执行失败,立即将反馈推入记忆并返回(False, feedback);若 block 指定了save_path,则在执行后调用tool.save_block保存内容。
架构总览:路由系统与三类 Agent
Agent 选择逻辑(4 步路由)
官方指南给出了路由系统流程图(对应仓库 docs/technical/routing_system.png):
Agent 的选择分 4 步完成:
- 检测查询语言并翻译成英文,供 zero-shot 模型和 llm_router 使用;
- 评估任务复杂度并确定最佳 Agent:
- 若为HIGH 复杂度:直接返回 planner agent;
- 若为LOW 复杂度:使用 2 个分类模型的投票系统确定最佳 Agent;
- 处理高复杂度查询:若任务为高复杂度,planner agent 会生成 JSON 计划,用多个 Agent 分治(divide and conquer)任务;
- 执行任务。
从 sources/router.py 的实现看,这一逻辑有更细的落地细节:
- 语言检测与翻译由
LanguageUtility完成(支持en/fr/zh,见 sources/router.py); - 复杂度估计由
AdaptiveClassifier(llm_router)完成,带有一大批 LOW/HIGH few-shot 示例(sources/router.py),置信度低于 0.5 时保守判定为 HIGH; - 低复杂度任务的投票系统
router_vote在 BART zero-shot 模型(facebook/bart-large-mnli)与 llm_router 之间按置信度加权投票(sources/router.py); - 最后按
agent.role与投票结果匹配具体 Agent(sources/router.py)。
文件/代码 Agent(File/Code agents)
File 与 Code Agent 的运行方式相似:提交 prompt 后,它们会在 LLM 与代码解释器之间启动一个循环,持续执行命令或代码,直到执行成功或达到最大尝试次数。从 sources/agents/code_agent.py 可见,CoderAgent.process以max_attempts = 5为上限循环:调用execute_modules执行 block,失败时把反馈推回记忆并提示"Correcting code..."继续下一轮,成功且最后一个工具不是 bash 时提前跳出循环。
Web Agent
Web Agent 控制一个由 Selenium 驱动的浏览器。收到查询后,它首先生成优化过的搜索 prompt 并执行web_search工具,随后进入导航循环,在循环中:
- 分析当前页面的内容与可交互元素;
- 决定跟随哪个链接(来自当前页面或 web_search 结果);
- 判断是否应该返回,若返回则重新评估最初的 web_search 结果;
- 识别并与网页表单交互,按需提取或填写;
- 任务完成时请求退出,标记完成。
Planner Agent 与多 Agent 分治
高复杂度任务会交给 planner agent:它生成 JSON 计划,把任务拆解给coder、file、web、casual等子 Agent 顺序执行,并根据各子 Agent 的执行结果动态更新计划(见 sources/agents/planner_agent.py)。其 JSON 计划通过```jsonblock 输出,由parse_agent_tasks解析(要求每个任务包含agent、id、task字段,可选need字段传递前序 Agent 产出),并对非法 JSON、未知 Agent 名、缺失字段做容错处理(sources/agents/planner_agent.py)。对应的健壮性测试见 tests/test_planner_agent_parsing.py。
代码规范与行为准则
官方指南要求参考 docs/CODE_OF_CONDUCT.md 遵守社区行为准则。作为贡献者,还应牢记前文六条 Good Practice——尤其"隐私优先、永远本地"是该项目区别于云端 Agent 方案的根本设计约束(远程 API 仅限特定工具并需显式告警),任何新功能都不应破坏这一底线。
结语
agenticSeek 的扩展路径非常清晰:写一个继承Tools的工具、用三步法挂进 Agent、在 prompt 里教会 LLM 使用它,或者继承Agent实现process并设置role/type注册进路由。配合if __name__ == "__main__"的本地自测入口与 tests 目录中的既有测试范式,你可以低门槛地开始贡献。所有核心改动都应保持 100% 本地可运行,这是项目的第一原则。
【免费下载链接】agenticSeekFully Local Manus AI. No APIs, No $200 monthly bills. Enjoy an autonomous agent that thinks, browses the web, and code for the sole cost of electricity.项目地址: https://gitcode.com/GitHub_Trending/ag/agenticSeek
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考