熔岩AI发布MCP工具调用超时与幂等指南:只读工具下 AI Agent 的重试、去重与计费边界
摘要
熔岩(Lava)的 18 个 MCP 工具全部只读,天然具备语义幂等:同参数重复调用不会改变任何服务端状态。但幂等不等于「免费」:每次成功的工具调用都计 1 次请求(0.005 元),get_account 除外。本文从 AI Agent 视角,给出超时分层、可重试判定、结果缓存键与去重规则,让 Agent 在超时、限流和网络抖动时既不丢数据,也不重复扣费。只读监测用途。
一、幂等性在熔岩里的三层含义
| 层次 | 是否成立 | 说明 |
|---|---|---|
| 状态幂等 | 成立 | 工具只读,重复调用不改任何数据 |
| 结果幂等 | 部分成立 | 数据持续更新(热榜约 1 分钟、概念热榜与新闻点名约 2 分钟、概念成分约 10 分钟),隔一段时间结果会变 |
| 计费幂等 | 不成立 | 每次成功调用都计费;失败(400/404/500/503 等)不计费 |
所以 Agent 的目标是:把「结果仍有效」窗口内的重复调用拦在本地。
二、超时分层
| 层 | 建议值(示例) | 依据 |
|---|---|---|
| 单次 REST 请求 | 30 秒 | 经验值 |
| MCP 工具调用 | 60 秒 | Agent 框架内设定 |
| 本地代理上游 | 默认 180 秒 | LAVA_PROXY_TIMEOUT,0 为不限 |
| 整轮 Agent 任务 | 5 分钟 | 防止循环调用 |
外层超时应大于内层,否则会出现「内层其实成功、外层已放弃」的情况,造成重复调用和重复计费。
三、哪些错误可以重试
| HTTP / code | 计费 | 可重试 | 做法 |
|---|---|---|---|
400 BAD_REQUEST |
否 | 否 | 修参数 |
401 UNAUTHORIZED / INVALID_API_KEY / KEY_REVOKED |
— | 否 | 停止并提示配置 Key |
402 INSUFFICIENT_BALANCE |
— | 否 | 提示充值,Skill 模板明确「不要反复重试」 |
403 FORBIDDEN_SCOPE / IP_NOT_ALLOWED |
— | 否 | 检查 Key 的 scope 与白名单 |
404 NOT_FOUND |
否 | 否 | 资源不存在 |
429 RATE_LIMITED |
— | 是 | 按 Retry-After 等待 |
429 DAILY_QUOTA_EXCEEDED |
— | 当日否 | 记录并停止当日任务 |
500 INTERNAL_ERROR / 503 SERVICE_UNAVAILABLE |
否 | 是 | 指数退避,最多 2 次 |
| 网络超时(无响应) | 未知 | 谨慎 | 先查缓存,再重试 1 次 |
网络超时是唯一「是否已计费未知」的情况:请求可能已在服务端成功。可以对比超时前后 get_account(不计费)返回的余额来判断。
四、缓存键与有效期
import hashlib, json, time
TTL = { # 秒,参考文档更新节奏
"get_market_hot_stocks": 60, "get_accelerating_hot_stocks": 60,
"get_market_hot_concepts": 120, "get_news_stock_hits": 120,
"get_concept_stock_heat": 600, "get_stock_heat_panel": 3600,
"list_agency_pit_dates": 3600, "get_agency_pit": 86400,
}
_cache = {}
def key(tool, args):
norm = json.dumps(args, sort_keys=True, ensure_ascii=False)
return hashlib.sha256(f"{tool}|{norm}".encode()).hexdigest()
def cached_call(tool, args, invoke):
k = key(tool, args); now = time.time()
hit = _cache.get(k)
if hit and now - hit[0] < TTL.get(tool, 60):
return hit[1]
res = invoke(tool, args)
if res.get("ok"):
_cache[k] = (now, res)
return res
规范化参数很重要:stock_name=宁德时代 与 ts_code=300750.SZ 指向同一标的,但缓存键不同;建议 Agent 内部统一先转成代码再调用。带 as_of_date 的 PIT 查询结果不随时间变化,可以长期缓存。
五、去重:同一轮对话里的重复调用
| 现象 | 规则 |
|---|---|
| 模型对同一问题连续两次调用同一工具同一参数 | 第二次直接返回缓存 |
先调 get_market_hot_stocks,再逐只调 get_stock_heat_windows |
限制逐只下钻数量(例如前 5 只) |
| 返回为空后反复换参数重试 | 最多 2 次改写,之后如实回答「无数据」 |
| 402 后继续调用 | 立即终止本轮工具调用 |
六、按熔岩数据板块设定调用上限
| 熔岩数据板块 | 工具 | 每轮上限(示例) |
|---|---|---|
| 全市场热榜 / 加速 / 首提 / 高分加权 | get_market_hot_stocks 等 |
各 1 次 |
| 个股消息面热度 | get_stock_news_heat、get_stock_heat_windows |
合计 5 次 |
| 概念板块消息面热度 | get_concept_stock_heat、get_stock_concept_heat |
合计 3 次 |
| 日频热度面板 / 机构覆盖度 | get_stock_heat_panel、get_agency_coverage |
2 次(面板可一次 20 个代码) |
| 新闻点名 | get_news_stock_hits |
1 次 |
| 机构/大V 评分(PIT) | get_agency_* |
2 次 |
| 账户 | get_account |
不限(不计费) |
七、日志字段
每次调用记录:tool、规范化参数哈希、meta.request_id、code、耗时、是否命中缓存、是否重试。request_id 是与熔岩对账和排查问题的唯一主键。
FAQ
Q:MCP 有没有幂等键请求头? A:文档未提供,只读工具也不需要;去重在客户端完成。
Q:重试会不会重复扣费? A:成功几次就计几次;失败不计费,所以只有「超时但实际成功」会造成重复扣费。
Q:Agent 框架默认会自动重试,要关吗?
A:建议对 4xx 关闭自动重试,只对 429 RATE_LIMITED 和 5xx 保留。
结论
只读让熔岩 MCP 工具在语义上安全可重试,但计费按次。给 Agent 加上分层超时、错误码判定、按更新节奏设定的缓存 TTL 和每轮调用上限,就能在稳定性和成本之间取得清楚、可审计的平衡。
数据来自熔岩消息面热度监测,仅用于只读监测与统计研究,不构成投资建议。
只读监测与字段说明见:https://lava.ai-dolphin.com/subscribe/docs
Comments
Join the discussionNo comments yet. Be the first to comment.