新闻详情

新闻详情

首页 / 资讯中心 / 详情

大模型开发 - 手写Manus之Tavily搜索工具:04 让AI Agent接入互联网(TaoToken 统一 Key 配置版)

发布时间:2026/11/13 8:53:44来源:尧图网络
大模型开发 - 手写Manus之Tavily搜索工具:04 让AI Agent接入互联网(TaoToken 统一 Key 配置版)
1. 为什么你的 Java Agent 还差一双“眼睛”大模型开发走到手写 Manus 这一步文件读写和 Docker 沙箱代码执行都已经跑通了但你会发现 Agent 依然是个“闭卷考生”。你问它“今天有什么值得关注的 AI 开源项目”它只能从训练数据里翻旧账给出的答案可能停留在几个月前。这不是模型不够聪明而是它缺少一个能实时访问互联网的搜索工具。Tavily 就是为 AI Agent 量身定做的搜索 API。它不像传统搜索引擎那样返回一堆需要解析的 HTML而是直接给你结构化的 JSON标题、链接、摘要拿来就能塞进大模型的上下文。对于 Java 手写 Manus 的场景来说这意味着你不需要写爬虫、不需要处理反爬、不需要清洗页面一个 HTTP 请求就能让 Agent 拿到互联网上的最新信息。但这里有个现实问题Tavily 的 Key 要管大模型的 Key 也要管如果后面还要接别的模型或工具环境变量会越堆越多。我试过在三个不同的配置文件里来回切换 Key最后自己都搞混了。所以这篇内容的核心思路是用 TaoToken 统一管理 Key 和 API 通道让 Tavily 搜索工具通过一个稳定的入口接入 Agent配置一次后面加工具、换模型都不用再动环境变量。适合谁看如果你正在用 Java 手写类 Manus 的 AI Agent已经完成了基础架构和沙箱执行现在想让 Agent 能搜索互联网这篇就是为你准备的。我会给出完整的config.toml和settings.json骨架、TaoToken 接入 AI Agent 的配置片段以及一次搜索请求的验证动作目标只有一个让 Agent 稳定接入互联网。2. TaoToken 前置统一 Key 与 API 通道在动手改代码之前先把 TaoToken 的接入准备好。你可以把它理解成一个“Key 管家 通道调度器”Tavily 搜索、模型对话、代码补全这些能力都通过同一个 API 入口和同一套 Key 体系来调用。这样做的好处是Agent 的配置文件里不需要散落各种厂商的 Key只需要维护一份 TaoToken 的凭证。2.1 获取 TaoToken API Key打开 TaoToken 官网注册或登录后进入控制台在 API Keys 页面创建一个新的 Key。建议按用途命名比如manus-agent-dev方便后面排查问题时区分环境。创建完成后把 Key 复制出来它只会完整显示一次。注意这个 Key 不要直接写死在 Java 代码里也不要提交到 Git 仓库。后面我们会用配置文件加环境变量的方式管理。2.2 确认 API 入口地址TaoToken 的 API 入口是https://taotoken.net/api所有通过 TaoToken 转发的请求都走这个地址。Tavily 搜索工具在底层发起 HTTP 请求时会把目标指向这个入口由 TaoToken 完成后续的通道调度。你不需要在代码里硬编码 Tavily 官方的地址统一走 TaoToken 即可。2.3 规划配置文件结构在手写 Manus 的项目里我建议把配置分成两层一层是config.toml放 Agent 运行时的全局参数另一层是settings.json放工具级别的开关和参数。TaoToken 的 Key 和 API 地址放在config.toml的[llm]和[tools]段里Tavily 搜索的具体行为参数放在settings.json里。这样后面加新工具时只需要在settings.json里加一段不用动主配置。3. 可复制配置config.toml 与 settings.json 骨架下面这份配置可以直接复制到你的项目里按实际情况改 Key 和路径即可。我尽量把注释写清楚方便你对照自己的项目结构调整。3.1 config.toml 骨架# config.toml - Agent 全局配置 [llm] # TaoToken 统一 API 入口 base_url https://taotoken.net/api # 从环境变量读取避免硬编码 api_key ${TAOTOKEN_API_KEY} # 模型名称按需替换 model claude-3-5-sonnet timeout_seconds 60 [tools] # 工具总开关 enabled [file, sandbox, tavily_search] [tools.tavily_search] # 搜索工具也走 TaoToken 统一通道 base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} # 单次搜索返回结果数上限 max_results 5 # 请求超时单位秒 timeout_seconds 30 [agent] workspace ./workspace max_iterations 10这里的关键点是[tools.tavily_search]段base_url和api_key都指向 TaoToken而不是 Tavily 官方地址。这样 Tavily 搜索工具在发起请求时实际是向 TaoToken 的 API 入口发送请求由 TaoToken 完成后续处理。3.2 settings.json 骨架{ tavily_search: { enabled: true, search_depth: basic, include_answer: false, include_raw_content: false, max_results: 5, search_params: { query: , topic: general } }, agent_runtime: { log_level: INFO, tool_call_timeout_ms: 30000, retry_on_failure: true, max_retries: 2 } }settings.json里放的是工具的行为参数比如搜索深度、是否包含原始内容、重试策略。这些参数和 Key 无关所以单独抽出来方便不同环境用不同的 JSON 文件覆盖。3.3 环境变量注入在启动 Agent 之前把 TaoToken 的 Key 注入环境变量export TAOTOKEN_API_KEY你的_TaoToken_API_Key如果你在 IDE 里跑可以在 Run Configuration 里加环境变量如果打包成 jar 跑用-D参数或者启动脚本里 export。这样config.toml里的${TAOTOKEN_API_KEY}就能被正确替换。4. Java 侧接入TavilySearchTool 改造配置准备好之后回到 Java 代码。原来的TavilySearchTool是直接从环境变量读 Tavily 的 Key现在要改成从config.toml读取 TaoToken 的配置。4.1 新增依赖除了原有的 langchain4j Tavily 封装还需要一个 TOML 解析库来读config.toml!-- Tavily 搜索引擎封装 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-web-search-engine-tavily/artifactId version0.36.2/version /dependency !-- TOML 配置解析 -- dependency groupIdcom.moandjiezana.toml/groupId artifactIdtoml4j/artifactId version0.7.2/version /dependency4.2 读取 TaoToken 配置写一个简单的配置加载类把config.toml里的[tools.tavily_search]段读出来import com.moandjiezana.toml.Toml; import java.io.File; public class AgentConfigLoader { private final Toml toml; public AgentConfigLoader(String configPath) { this.toml new Toml().read(new File(configPath)); } public String getTavilyBaseUrl() { return toml.getString(tools.tavily_search.base_url); } public String getTavilyApiKey() { String key toml.getString(tools.tavily_search.api_key); // 支持 ${ENV_VAR} 形式的环境变量替换 if (key ! null key.startsWith(${) key.endsWith(})) { String envName key.substring(2, key.length() - 1); return System.getenv(envName); } return key; } public int getTavilyMaxResults() { Long value toml.getLong(tools.tavily_search.max_results); return value ! null ? value.intValue() : 5; } }4.3 改造 TavilySearchTool原来的工具类从System.getenv(TAVILY_API_KEY)读 Key现在改成从配置加载器读public class TavilySearchTool extends BaseTool { private final WebSearchEngine searchEngine; private final int defaultMaxResults; public TavilySearchTool(AgentConfigLoader config) { super(tavily_search, Search the web for real-time information); String apiKey config.getTavilyApiKey(); if (apiKey null || apiKey.trim().isEmpty()) { throw new IllegalStateException(TaoToken API Key is required for tavily_search); } this.defaultMaxResults config.getTavilyMaxResults(); // 关键baseUrl 指向 TaoToken 统一入口 this.searchEngine TavilyWebSearchEngine.builder() .apiKey(apiKey) .baseUrl(config.getTavilyBaseUrl()) .build(); } Override public MapString, Object getParametersSchema() { MapString, MapString, Object properties new HashMap(); properties.put(query, stringParam(The search query to execute)); properties.put(max_results, intParam(Max results, default defaultMaxResults)); return buildSchema(properties, List.of(query)); } Override public ToolResult execute(MapString, Object parameters) { try { String query getString(parameters, query); if (query null || query.trim().isEmpty()) { return ToolResult.error(Query parameter is required); } int maxResults getInt(parameters, max_results, defaultMaxResults); WebSearchResults results searchEngine.search(query); MapString, Object response new HashMap(); response.put(query, query); response.put(total_results, results.results().size()); ListMapString, Object items results.results().stream() .limit(maxResults) .map(r - { MapString, Object item new HashMap(); item.put(title, r.title()); item.put(url, r.url()); item.put(snippet, r.snippet()); return item; }) .toList(); response.put(results, items); return ToolResult.success(response); } catch (Exception e) { return ToolResult.error(Search failed: e.getMessage()); } } }注意baseUrl这一行它把搜索请求的目标指向了 TaoToken 的 API 入口。Tavily 的官方 SDK 支持自定义 baseUrl所以这里不需要改底层 HTTP 逻辑只需要在构建时传入 TaoToken 的地址即可。4.4 注册到 Agent在ManusAgent的初始化流程里把配置加载器和工具注册串起来public class ManusAgent { private final ToolCollection toolCollection; public ManusAgent(String configPath) { AgentConfigLoader config new AgentConfigLoader(configPath); this.toolCollection new ToolCollection(); // 注册文件工具 toolCollection.addTool(new FileReadTool(config)); toolCollection.addTool(new FileWriteTool(config)); // 注册沙箱工具 toolCollection.addTool(new SandboxTool(config)); // 注册 Tavily 搜索工具走 TaoToken 统一通道 toolCollection.addTool(new TavilySearchTool(config)); } }到这里Java 侧的改造就完成了。Tavily 搜索工具不再依赖单独的 Tavily Key而是复用 TaoToken 的 Key 和 API 入口。5. 验证请求一次搜索的成功结果配置和代码都改完之后先别急着跑完整的 Agent 流程单独验证一次搜索请求确认 TaoToken 通道是通的。5.1 写一个最小验证类public class TavilySearchVerify { public static void main(String[] args) { AgentConfigLoader config new AgentConfigLoader(config.toml); TavilySearchTool tool new TavilySearchTool(config); MapString, Object params new HashMap(); params.put(query, Java AI Agent 开源项目 2025); params.put(max_results, 3); ToolResult result tool.execute(params); if (result.isSuccess()) { System.out.println(搜索成功结果数: result.getData().get(total_results)); ListMapString, Object items (ListMapString, Object) result.getData().get(results); for (MapString, Object item : items) { System.out.println(标题: item.get(title)); System.out.println(链接: item.get(url)); System.out.println(摘要: item.get(snippet)); System.out.println(---); } } else { System.err.println(搜索失败: result.getErrorMessage()); } } }5.2 预期输出运行这个类如果配置正确你会看到类似下面的输出搜索成功结果数: 3 标题: 2025年值得关注的Java AI Agent框架 链接: https://example.com/java-ai-agent-2025 摘要: 本文整理了当前主流的Java AI Agent开源项目... --- 标题: 手写Manus系列教程 链接: https://example.com/manus-java-tutorial 摘要: 从零用Java实现类Manus智能体涵盖架构、沙箱、搜索... --- 标题: LangChain4j 最新进展 链接: https://example.com/langchain4j-update 摘要: LangChain4j 近期新增了多个工具集成... ---5.3 接入 Agent 后的完整流程单独验证通过后把搜索工具放进 Agent 的决策链里跑一次。用户输入“搜索一下最近有哪些新的 Java AI Agent 项目把结果写到文件里”Agent 的执行流程会是这样第一步大模型推理后调用tavily_searchquery 是“Java AI Agent 新项目 2025”TaoToken 通道返回结构化搜索结果。第二步大模型从搜索结果里提取关键信息调用write_file把整理后的内容写入workspace/java_agent_projects.txt。第三步大模型判断任务完成返回finish_reasonstop。搜索结果被封装成toolMessage存入 Memory 后下一轮推理时大模型能看到完整的搜索内容并据此决定是继续搜索、提取信息还是写入文件。这就是搜索工具流入 Agent 决策链的完整路径。6. 本篇常见错排查配置和代码都给了但实际跑的时候大概率会遇到几个坑。下面这几个是我在调试时踩过的按顺序排查基本能覆盖大部分问题。6.1 搜索请求返回 401 或 403先检查config.toml里的api_key是否被正确替换成了环境变量的值。可以在AgentConfigLoader里加一行日志把读到的 Key 前几位打印出来确认。如果 Key 本身没问题检查base_url是否写成了https://taotoken.net/api注意末尾不要多加斜杠也不要写成其他路径。6.2 搜索结果为空或 total_results 为 0这种情况通常是 query 参数没传进去或者max_results被设成了 0。检查execute方法里getString(parameters, query)的返回值确认大模型调用工具时确实填了 query 字段。另外settings.json里的max_results和config.toml里的max_results如果冲突以代码里实际读取的为准建议只保留一处配置。6.3 工具注册后 Agent 不调用如果 Agent 在应该搜索的时候没有调用tavily_search先检查工具是否真的注册进了ToolCollection。可以在ManusAgent构造完成后打印一下toolCollection里的工具名称列表。另外工具的description要写清楚用途大模型是根据描述来决定调不调用的。Search the web for real-time information这种描述比search tool更容易被正确触发。6.4 超时或连接失败TaoToken 的 API 入口是 HTTPS确认你的运行环境能正常访问外网。如果公司网络有代理需要在 JVM 启动参数里配置代理设置。另外config.toml里的timeout_seconds如果设得太短搜索请求可能还没返回就被中断了建议先设 30 秒测试。6.5 环境变量没生效${TAOTOKEN_API_KEY}这种写法依赖AgentConfigLoader里的替换逻辑。如果你用的是其他 TOML 库可能不支持这种语法需要手动读取环境变量再 set 进去。最简单的验证方式是在main方法里直接System.out.println(System.getenv(TAOTOKEN_API_KEY))确认环境变量在当前进程里可见。排查完这几个点Tavily 搜索工具基本就能稳定工作了。后面如果要加新的搜索源或者换模型只需要在 TaoToken 控制台调整通道配置Java 侧不用改代码。7. 接入文档与后续工具扩展Tavily 搜索工具跑通之后你的 Agent 工具箱里就有了文件读写、沙箱执行、网页搜索三类能力。这三者组合起来能做的事情比单个工具叠加要多得多搜索获取实时信息沙箱里跑代码处理数据最后把结果写入文件。如果你在接入过程中遇到 Key 配置或通道相关的问题可以直接看 TaoToken 的接入文档里面有各语言的最小接入示例和常见错误码说明。需要管理多个 Key 或者查看调用量的话控制台里有按工具维度的统计。后续如果要给 Agent 加新的工具比如代码补全或者长文本摘要建议继续走 TaoToken 的统一通道这样配置文件里只需要加一段[tools.xxx]不用再引入新的 Key 管理体系。搜索工具只是 Agent 接入互联网的第一步。真正让 Agent 变得好用的是工具之间的组合调用而组合调用的前提是每个工具都能稳定、可配置地工作。把 TaoToken 作为统一入口后面加工具、换模型、调参数都会轻松很多。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/13 0:43:49

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/12 23:59:09

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/12 9:50:02

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/12 9:25:38

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/12 15:57:44

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/13 0:02:27

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉