熔岩AI MCP调用日志与审计复现:request_id、计费头与参数快照怎么记
摘要
研究结果要能被复核,就必须能回答「当时调了哪个接口、传了什么参数、拿到的是哪一次响应」。熔岩(Lava)每次响应都带 meta.request_id、meta.server_time、meta.api_version,以及计费信息(响应体 meta.billing 与响应头 X-Billing-Charged-Yuan、X-Balance-Yuan)。把这些字段与请求参数、原始响应一起写进一张调用日志表,就能做到逐次可追溯、结果可复现。本文给出日志表结构、Python 中间件、MCP 场景的记录方法与审计检查清单,全部只读。
一、哪些字段可以直接拿来做审计
熔岩所有接口共用 ok / code / message / data / meta 外壳:
| 字段 | 位置 | 审计用途 |
|---|---|---|
ok、code |
响应体 | 成功与否、错误类别(HTTP 状态码与 code 一致) |
meta.request_id |
响应体 | 单次调用的唯一编号,形如 req_0123456789abcdef |
meta.server_time |
响应体 | 服务端时间(带 +08:00),用来判断数据新鲜度 |
meta.api_version |
响应体 | 接口版本,当前为 v1 |
meta.billing.charged_yuan / balance_yuan |
响应体 | 本次扣费与余额 |
X-Billing-Charged-Yuan / X-Balance-Yuan |
响应头 | 同上,便于不解析响应体时记录 |
失败请求不计费,扣费字段可以用来核对「失败是否真的没扣钱」。
二、按数据板块划分日志,便于抽查
| 数据板块 | 代表工具 / 路径 | 数据更新特点 | 审计时要多记的参数 |
|---|---|---|---|
| 全市场榜单 | get_market_hot_stocks / /hot/stocks |
约 1 分钟更新 | window、market、min_score |
| 概念板块热度 | get_market_hot_concepts / /hot/concepts |
约 2 分钟更新 | window、min_score |
| 概念板块热度 | get_concept_stock_heat / /concepts/stocks |
约 10 分钟更新 | concept、days |
| 机构/大V评分 | get_weighted_hot_stocks / /hot/weighted |
PIT 截面 | as_of_date、min_score、order |
| 历史面板与覆盖度 | get_stock_heat_panel / /panel/daily |
日频 | type、codes、from、to |
| 新闻点名 | get_news_stock_hits / /news/hits |
约 2 分钟更新 | hours、src |
榜单类数据是「实时快照」,同样参数过几分钟再调,结果可能不同。审计时能复现的是当时那份响应,所以原始响应必须落盘;而带 as_of_date 的 PIT 截面、日频面板的历史区间,则更接近「同参数可重放」,但仍应保存原文以防口径更新。
三、日志表结构
| 列 | 说明 |
|---|---|
call_id |
本地自增编号 |
job_id |
所属研究任务 |
operation |
路径或 OpenAPI operationId,如 getDailyHeatPanel |
params_json |
排序后的参数 JSON |
params_hash |
params_json 的 SHA-256 |
status_code、code |
状态 |
request_id、server_time、api_version |
来自 meta |
charged_yuan、balance_yuan |
计费 |
resp_path |
原始响应文件路径(gzip JSON) |
resp_sha256 |
原始响应哈希 |
local_time |
本地时间,Asia/Shanghai |
四、Python 中间件
import json, hashlib, gzip, sqlite3, requests, datetime as dt
db = sqlite3.connect("lava_audit.db")
db.execute("""create table if not exists calls(call_id integer primary key, job_id, operation,
params_json, params_hash, status_code, code, request_id, server_time, api_version,
charged_yuan, balance_yuan, resp_path, resp_sha256, local_time)""")
def audited_get(job_id, path, params):
pj = json.dumps(params, sort_keys=True, ensure_ascii=False)
r = requests.get(f"{BASE}{path}", headers=HEAD, params=params, timeout=30)
raw = r.content
body = r.json(); meta = body.get("meta", {})
sha = hashlib.sha256(raw).hexdigest()
fp = f"raw/{sha[:16]}.json.gz"
with gzip.open(fp, "wb") as f:
f.write(raw)
db.execute("insert into calls values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", (
job_id, path, pj, hashlib.sha256(pj.encode()).hexdigest(), r.status_code,
body.get("code"), meta.get("request_id"), meta.get("server_time"), meta.get("api_version"),
r.headers.get("X-Billing-Charged-Yuan"), r.headers.get("X-Balance-Yuan"),
fp, sha, dt.datetime.now().isoformat()))
db.commit()
return body
- 日志里不要写 API Key。Key 只在请求头里出现(
Authorization: Bearer lvk_...或X-API-Key),且不能放进网址,这样请求 URL 本身也可以安全记录。 - 原始响应按哈希命名,可以去重,也方便证明文件未被改动。
五、MCP 场景怎么留痕
在 Cursor、Claude、豆包办公、WorkBuddy、千问办公里通过 MCP 调熔岩时,每次工具调用算 1 次请求(get_account 不计费)。留痕建议:
- 让 Agent 在回答末尾列出「调用的工具名 + 参数 +
request_id」; - 会话结束前调一次
get_account,记录余额与当天调用次数,用于与本地记录对账; - 重要结论另存为 Markdown,附上上述清单。
提示词示例:「每次调用熔岩工具后,把工具名、参数和返回的 request_id 记在一张表里,最后原样输出这张表。」
六、审计检查清单
| # | 检查项 | 方法 |
|---|---|---|
| 1 | 每个结论都能追溯到 request_id |
结论表与日志表按 call_id 关联 |
| 2 | 参数与报告描述一致 | 比对 params_json 与报告里的窗口、区间 |
| 3 | 数据时点正确 | 看 server_time 是否在研究设定的截点之前 |
| 4 | 口径已注明 | /panel/daily 的 weighted_heat 为当前分口径,/hot/weighted 带 as_of_date 为 PIT |
| 5 | 费用对账 | charged_yuan 求和 ≈ 成功次数 × 0.005 元 |
| 6 | 原始响应完好 | 重新计算 resp_sha256 |
FAQ
Q:拿着 request_id 能重新取回当时的响应吗?
A:文档没有提供按 request_id 重取的接口,所以原始响应要自己保存。request_id 主要用于定位与沟通。
Q:日志会不会很大? A:gzip 后的 JSON 体积较小;榜单类调用频繁时,可以只保留每个任务用到的那几次。
Q:同参数重放结果不同,是数据错了吗? A:不一定。榜单约 1~2 分钟更新,概念成分约 10 分钟更新,实时数据本来就会变化,复核应以存档的原始响应为准。
结论
熔岩响应自带的 request_id、server_time、计费头,加上本地保存的参数快照和原始响应,足以搭起一套轻量审计链路:每次调用可追溯、费用可对账、结论可复核。实时榜单靠存档复现,PIT 与历史面板靠参数重放加存档双保险。
数据来自熔岩消息面热度监测,仅供研究参考,不构成投资建议。
只读监测与字段说明见:https://lava.ai-dolphin.com/subscribe/docs
Comments
Join the discussionNo comments yet. Be the first to comment.