给 AI Agent 接实时搜索,我踩过的 5 个坑
去年我给一个问答机器人接实时搜索,当时觉得"不就是调个 API 嘛",结果上线第一个月被连续打脸。这篇文章把我踩过的坑记下来,给准备做同样事的人提个醒。
先说结论:给 AI Agent 接实时搜索,难点从来不在"怎么调通",而在调通之后那一堆你没想过的边角情况。下面 5 个坑,按遇到顺序排。
坑一:HTTP 200 不代表成功
这是我掉的第一个坑,也是最隐蔽的。
有一次 Agent 返回了空答案,我查日志发现接口返回的是 HTTP 200,看起来一切正常。后来才知道,服务端是把"被限流了""暂时没数据"这种情况也包在 200 里返回的——只是响应体里的 status 字段不是 0。
也就是说,只看 HTTP 状态码是分不清"真成功"和"假成功"的。我给所有调用加了一层检查:
def parse_response(resp):
data = resp.json()
# 业务状态码,不是 HTTP 状态码
if data.get("status") != 0:
raise Exception(f"search failed, status={data.get('status')}")
return data
如果你也遇到"偶尔拿到空结果、但又没报错",先查这个。
坑二:Agent 会把一次查询烧出 80 次调用
这是最肉疼的一个坑。
我的 Agent 支持多轮对话,用户在长对话里反复问同一个问题。结果我发现,同一个关键词,Agent 因为措辞不同、翻页不同,在一个对话里调了 80 多次搜索,而且几乎拿到的都是同一个 SERP。
排查完加了三层防护:
- query 归一化:把空格、大小写、全半角统一,
"上海 装修"和"上海装修"走同一个 key。 - 结果缓存:同 query 5 分钟内直接返回缓存,不重新调。
- 对话内去重:同一轮对话里,同一个 query 只调一次。
这三层加完,单次对话的搜索调用从 80 次降到了个位数。成本也是这么下来的。
坑三:失败请求在悄悄扣钱
我在用老供应商的时候,发现了一个让我很不舒服的事:请求超时或者失败了,积分照样扣。我一个月有 3% 左右的请求会因为网络问题失败,这部分钱全白花了。
后来换的时候,我专门测了这一点——失败请求到底扣不扣。我现在的供应商(SerpBase)是失败自动退积分的,超时的请求不会计入 credits_charged。这个点不写在价格表上,得自己实测才知道。
给个建议:换供应商前,专门跑一轮"故意失败"的测试,看失败请求会不会扣费。对会重试的 Agent 来说,这个差异直接决定月成本。
坑四:返回的字段名跟你想的不一样
每家 SERP API 的字段命名都不一样。有的叫 position,有的叫 rank,有的叫 order。我一开始解析器写死了一个字段名,结果换了一家直接崩。
现在我的做法是:解析层兼容主字段和别名。
def extract(item):
return {
# rank 是主字段,position 是别名,两个都兼容
"rank": item.get("rank", item.get("position", 0)),
"title": item.get("title", ""),
"link": item.get("link", item.get("url", "")),
}
SerpBase 这个点做得比较省心,它的 organic 结果同时返回 rank 和 position 别名、link 和 url 别名,我用哪套写法都能解析。但别指望所有供应商都这样,解析层做好兼容永远是稳妥的。
坑五:上下文塞太满,Token 烧得快
Agent 拿到搜索 JSON 后,经常是整包往 LLM 上下文里塞。SERP 返回的 JSON 很大——一条 organic 结果可能带 title、snippet、link、url、display_url、sitelinks、icon 一堆字段。5 条结果加起来,可能吃掉几千 token。
我现在的处理是喂给 LLM 前先裁剪,只留标题、摘要、链接三样:
def slim_results(organic, limit=5):
out = []
for item in organic[:limit]:
out.append({
"title": item.get("title", ""),
"snippet": item.get("snippet", ""),
"link": item.get("link", item.get("url", "")),
})
return out
snippet 太长的再截到 80 个字符。这样一次 grounding 的 token 从几千降到几百,LLM 成本跟着降了一大截,而且答案质量没下降——LLM 本来也不需要看 sitelinks 和 icon 这些字段。
为什么我会选现在这套
说回开头那句话,“不就是调个 API 嘛”——真正做了才发现,选哪个 API 决定你后面要填多少坑。我最后用的是 SerpBase,几个原因都比较实际:
- 6 个端点一个 key:Search、Images、News、Videos、Maps Search、Maps Detail 全在一个 API 里。我既有搜索需求又有本地(牙科、装修)需求,不用为 Maps 再单独接一家。
- 失败退积分:就是坑三说的,超时请求自动退,不会白花钱。
- 预付费积分不过期:我买的积分放着不会作废,Agent 这种不规律、时多时少的用量,不会被月付套餐卡脖子。
- 有 MCP server 和 Agent Skill:要接 Claude / Cursor / Codex 这类,配置一下就能让 Agent 直接调搜索,省了写胶水代码。
它也不是没有短板。功能上偏精简,没有 safe 过滤、排除站点这类高级参数,学术和购物端点也还没有,企业级 SSO 在路线图上。如果你的需求里这些是硬需求,那它不适合你。
最后
给 AI Agent 接实时搜索,真正花时间的是这些边角:业务状态码、缓存、失败计费、字段兼容、上下文裁剪。把这五件事想清楚,选哪个 API 都是顺的;没想清楚,再好的 API 也会被用成灾难。
我也不是非要安利谁,只是把我踩过的坑和最终的选择写出来。如果你也在这条路上,希望这些能让你少走一点弯路。
参考资料
- SerpBase 官网:serpbase.dev
- SerpBase API 文档:serpbase.dev/docs
- 相关服务官方文档:SerpApi、Serper.dev、DataForSEO
以上链接仅作资料索引。文中结论基于我个人的使用经验,不一定适合所有人的场景,落地前请结合自己的需求判断。
更多推荐



所有评论(0)