# Token Lens Agent API 接入规范与扩展规划

更新：2026-10-21 · API v1 · token-risk Agent 0.2.0

服务基址：https://agent.vestpivot.com

在线文档：https://agent.vestpivot.com/api-docs.html

OpenAPI 3.1：https://agent.vestpivot.com/api/v1/openapi.json

## 1. 命名与版本约定

Agent使用全局唯一、稳定的小写kebab-case名称：token-risk、wallet-flow等。中文名称只用于展示。接口统一以/api/v1/agents/{agent_id}/{operation}开头，operation是明确的业务能力。operationId使用Agent前缀加驼峰功能名，用于生成SDK。

API大版本、Agent版本、数据结构版本和规则版本分开：URL的v1表示调用契约；agent.version表示实现版本；meta.schema_version表示报告结构；meta.rules_version表示判断规则。v1内不改变已有字段含义、类型、单位或必填条件，不随意删字段；不兼容变更另开v2。若需要新增枚举值，应在发布前评估客户端兼容性。调用方忽略未知返回字段，但请求端拒绝未知参数。

Agent边界以输入对象和生命周期为准：token-risk分析一个代币；wallet-flow分析一个钱包；liquidity-watch运行持续监控任务。不要把同一代币报告的五个切片冒充五个独立Agent。

## 2. 当前可调用接口

| 方法 | 路径 | 功能 | 参数 | 返回内容 |
|---|---|---|---|---|
| GET | /api/v1/health | 检查API进程，不检查供应商可用性 | 无 | data.status、service、api_version |
| GET | /api/v1/agents | 列出Agent目录 | 无 | data.items[]：id、name、version、status、callable；已上线项有operations、chains、limitations，规划项有proposed_input/output |
| GET | /api/v1/agents/{agent_id} | 获取Agent详情 | 路径agent_id，例如token-risk | data为对应目录项，未知ID返回404 |
| GET | /api/v1/openapi.json | 下载机器可读规范 | 无 | 原始OpenAPI对象，此端点不使用统一Envelope |
| POST | /api/v1/agents/token-risk/analyze | 代币综合风险分析 | 共用TokenInput，见下文 | 完整报告data |
| POST | /api/v1/agents/token-risk/holders | 前20持有人 | 共用TokenInput，见下文 | data.token + data.module + data.result + data.sources |
| POST | /api/v1/agents/token-risk/liquidity | 流动性与历史变化 | 共用TokenInput，见下文 | data.token + data.module + data.result + data.sources |
| POST | /api/v1/agents/token-risk/large-transactions | 大额成交与转账 | 共用TokenInput，见下文 | data.token + data.module + data.result + data.sources |
| POST | /api/v1/agents/token-risk/contract-permissions | 合约权限检查 | 共用TokenInput，见下文 | data.token + data.module + data.result + data.sources |
| POST | /api/v1/agents/token-risk/fund-flows | 资金流观察 | 共用TokenInput，见下文 | data.token + data.module + data.result + data.sources |

六个POST子接口共享同一次完整数据采集和60秒缓存，只缩小返回范围，不保证减少上游调用量或延迟。相同请求缓存有效时meta.cache.hit=true。

## 3. 参数：TokenInput

所有已上线分析接口均使用Content-Type: application/json，请求体上限4096字节，不支持URL查询参数代替JSON。两个参数都必填；未列出的参数返回400，避免拼写错误静默生效。

| 参数 | 类型 | 是否必填 | 含义与限制 | 示例 |
|---|---|---|---|---|
| chain | string | 是 | ethereum=Ethereum主网；bsc=BNB Smart Chain主网，区分大小写；不支持测试网 | ethereum |
| token_address | string | 是 | 0x开头40位十六进制代币合约地址，允许混合大小写，输出统一小写 | 0xdac17f958d2ee523a2206206994597c13d831ec7 |

当前不支持币名搜索、原生ETH/BNB、自定义大额门槛、自定义前N名、自定义24h窗口、强制刷新、地址标签自动推断等参数。10万美元门槛、前20、最多2个成交池、近期100条转账是当前固定采集配置。

```json
{
  "chain": "ethereum",
  "token_address": "0xdac17f958d2ee523a2206206994597c13d831ec7"
}
```

## 4. 统一返回结构

| 字段 | 类型 | 含义 |
|---|---|---|
| request_id | UUID string | 本次请求追踪编号；同时出现在X-Request-ID响应头，反馈问题时附带 |
| api_version | string | 固定为1，和URL的v1对应 |
| agent | object或null | 分析结果含{id,version}；平台目录与错误返回可能为null |
| status | string | completed=声明范围完成；partial=请求完成但数据部分覆盖；error=请求错误或所请求范围全部数据不足。与资产风险等级不同 |
| data | object或null | 完整报告或子模块结果；503时仍可能含可诊断数据，不应直接丢弃 |
| meta | object | 分析结果含generated_at、cache{hit,ttl_seconds}、data_path=server、schema_version、rules_version、coverage{模块名:状态} |
| warnings | array | 覆盖警告：code、message，可选module。机器码DATA_UNAVAILABLE、PARTIAL_COVERAGE、NOT_FULL_24H |
| error | object或null | 失败时含code、message、details[{field,message}]、retryable；中文message不作为程序分支依据 |

报告模块状态：observed表示该模块声明范围的数据已获取；partial表示部分覆盖；insufficient表示不足。null=未知，0=已知零，[]仅表示本次声明范围内没有记录。合约flags的值是字符串1/0或null；不要按JavaScript truthiness解释字符串0。百分比50表示50%，不是0.5。所有时间戳是Unix秒，UTC绝对时间；ISO字符串日期仅存在于供应商原始数据，标准结果已归一为秒。

金额、代币数量、百分比优先保留为十进制字符串。raw_balance是代币最小单位的精确整数，禁止转为JavaScript Number；精确换算需要已知decimals。当前美元估值和资金流汇总使用浮点近似，不用于结算。Decimal字符串可为负数，例如净流出。

### 各功能返回字段

#### 代币综合风险分析 · analyze

返回五个风险维度、权限线索、来源和完整度。采集范围受免费供应商限制。

data是综合报告：token、assessment、五个modules、findings、sources、notice、precision_note；不返回内部_inputs。

assessment.observed_risk_level枚举undetermined/medium/high/critical，仅表示已发现风险的最高等级。完整性assessment.status目前始终incomplete。findings每项包含severity、message、evidence；不能把没有命中规则解释为安全。

#### 前20持有人 · holders

按供应商余额排名返回最多20个持有人、持仓占比与精确原始余额。

data.result包含status、reason、returned、required、returned_holders_pct、items[]。每项是address、raw_balance或回退balance、supply_pct、tag；部分来源还有source、is_locked。

#### 流动性与历史变化 · liquidity

返回去重后的池子、当前美元流动性和已积累快照的1h/6h/24h变化。

data.result包含current_usd、pool_count、pools[]、changes、provider_pool_counts、status、reason。每个池子返回pair、dex、liquidity_usd、volume_24h_usd；changes按1h/6h/24h返回基准、同池比较与集合变化。

#### 大额成交与转账 · large-transactions

返回10万美元以上的大额DEX成交、近期转账样本和覆盖窗口；不能视为全链完整24小时。

data.result包含threshold_usd、dex_trades[]、transfers[]、recent_transfers[]、scanned_transfers、transfer_sample_from/to、trade_pools_requested/succeeded、large_dex_trades_found、large_transfers_found、complete_24h=false、status、reason。

#### 合约权限检查 · contract-permissions

返回蜜罐、增发、暂停、黑名单、代理等第三方检测标记，未知保留null。

data.result包含flags、tax_pct、owner_address、status、reason。flags有is_honeypot、cannot_sell_all、is_blacklisted、is_mintable、transfer_pausable、owner_change_balance、slippage_modifiable、hidden_owner、is_proxy。

#### 资金流观察 · fund-flows

返回转账样本中的地址净变化、增发/销毁和管理员大额转出线索，以及已覆盖的大额DEX买卖差。

data.result包含address_net_flows[]、items[]线索、sample_transfers、large_dex_buy_usd、large_dex_sell_usd、large_dex_net_buy_usd、status、reason。净变化按地址返回数量、当前美元估值、流入/流出次数和标签。

### 记录级字段与边界

- 持有人：raw_balance精确保留最小单位整数；supply_pct为百分数字符串。GoPlus回退仅有balance时不推断它与raw_balance同单位。标签为空表示未标注。
- 成交：hash、timestamp、pool、wallet、direction（相对目标代币的buy/sell）、quantity、usd、valuation=provider_trade_value、event_id、source。一个交易可能有多个成交事件，去重依据event_id，不是仅交易哈希。
- 转账：hash、timestamp、from、to、quantity、usd_estimate、valuation（current_price_estimate或unavailable）、event_index、source。当前估值不等于历史成交值。自转账不计地址净流入/流出。
- 大额结果：items最多150条，dex_trades和transfers各最多100条；found统计可能大于实际返回数组长度；recent_transfers最多100条。当前不支持下游分页。不要将成交和转账金额直接相加，它们可能属于同一交易。
- 流动性历史：changes.1h/6h/24h含status；有基准时附baseline_at、change_pct、compared_pools、pool_set_changed、note，无基准返回reason。仅比较相同池子，美元下降不直接等于撤池。
- sources每项含kind、url、fetched_at、status，失败有error。客户端来源原始数据不作为认证或授权依据。

完整字段类型、必填范围、枚举和nullable定义以OpenAPI components.schemas为准。

## 5. 状态码、鉴权与调用策略

| HTTP | error.code | 调用方处理 |
|---|---|---|
| 200 | error=null | 检查status、warnings和meta.coverage；partial也会返回200 |
| 400 | INVALID_JSON / INVALID_ARGUMENT | 修正JSON或参数，检查details，不自动重试 |
| 404 | NOT_FOUND / AGENT_NOT_FOUND | 检查路径和Agent目录 |
| 405 | METHOD_NOT_ALLOWED | 按Allow响应头修正HTTP方法 |
| 413 | PAYLOAD_TOO_LARGE | 将请求体限制为4096字节以内 |
| 415 | UNSUPPORTED_MEDIA_TYPE | 设置Content-Type: application/json |
| 429 | RATE_LIMITED | 按Retry-After等待，目前60秒，禁止立即循环重试 |
| 500 | INTERNAL_ERROR | 保留request_id，向服务方反馈 |
| 501 | AGENT_NOT_AVAILABLE | Agent仅处于规划阶段；不要重试 |
| 502 | UPSTREAM_ERROR | 分析服务返回错误或结构不合法，有限退避重试 |
| 503 | UPSTREAM_UNAVAILABLE | 所请求模块全部insufficient；data可能仍含来源与解释，不判定为低风险 |

当前为无API Key公共预览，CORS允许公共网页跨域、不使用Cookie凭据；约15次/分钟/IP，为边缘近似限制且和旧接口共用。建议超时60秒，限制并发，429按Retry-After，其他retryable错误最多少量退避重试。不得把服务器返回的成功HTTP状态当作数据实时性保证。没有SLA。

服务器接口不会运行页面内的浏览器回退，API数据覆盖可能低于网页。meta.data_path固定server；网页浏览器本机历史不属于服务器历史，外部应用不能通过API读取另一设备的localStorage。当前API不提供完整历史回补、报告持久化查询或全链24h分页。

正式对外接入阶段增加按应用分配的API Key（Authorization: Bearer）、租户隔离、应用配额与审计，再迁移到稳定自定义域名；目前尚未实现，不要发送交易所API Key、私钥或钱包助记词。

## 6. 调用示例

```bash
curl -X POST 'https://agent.vestpivot.com/api/v1/agents/token-risk/analyze' \
  -H 'Content-Type: application/json' \
  --data '{"chain":"ethereum","token_address":"0xdac17f958d2ee523a2206206994597c13d831ec7"}'
```

JavaScript SDK在sdk/client.mjs，包含listAgents、getAgent、analyzeToken、getTokenHolders、getTokenLiquidity、getTokenLargeTransactions、getTokenContractPermissions、getTokenFundFlows。SDK返回完整Envelope，不隐藏partial警告；非2xx抛AgentApiError，保留code/requestId/retryable/data。SDK本身不重试。

```js
import { AgentApiClient, AgentApiError } from './sdk/client.mjs';
const client = new AgentApiClient();
try {
  const result = await client.analyzeToken({"chain":"ethereum","token_address":"0xdac17f958d2ee523a2206206994597c13d831ec7"});
  console.log(result.status, result.meta.coverage, result.data, result.warnings);
} catch (error) {
  if (error instanceof AgentApiError) console.error(error.code, error.requestId, error.data);
  else throw error;
}
```

## 现货ETF资金流 Agent · etf-flows（已上线）

应用页面：https://agent.vestpivot.com/etf-flows.html

接口：POST /api/v1/agents/etf-flows/analyze；operationId=etfFlowsAnalyze；Agent版本1.0.0。

请求体：`{"asset":"btc"}`，asset必填，接受btc/eth/BTC/ETH，输出小写。未知参数拒绝；只支持美国现货ETF，不是港股、期货ETF或全球汇总。

返回仍使用统一Envelope。data内包含：

| 字段 | 含义 |
|---|---|
| asset / market / currency | btc或eth / us_spot / USD |
| latest_trading_day | 纽约时间下最近已经收盘的美股交易日，不保证该日资金流已公布 |
| reference_date | 本次选中来源最新记录日期；三组窗口均以此日为结束日期 |
| latest_available_date | 本次选中来源有非空资金流金额的最近日期 |
| periods.latest / last_5 / last_20 | 最新披露日、包含该日的近5/20个美股交易日汇总 |
| daily | 近20个交易日逐日记录，含缺失日 |
| selected_source / sources | 采用的来源、署名、原始抓取时间、更新日期及失败情况 |
| status / warnings / cache | 完成/部分/不可用、覆盖警告、15分钟缓存信息 |

每个period含requested_trading_days、observed_trading_days、start_date、end_date、net_flow_usd、observed_net_flow_usd、direction、status、inflow_days、outflow_days、flat_days、missing_dates、daily。net_flow_usd是有符号USD十进制字符串，正数流入、负数流出。缺失任一交易日则net_flow_usd=null，只提供已披露部分observed_net_flow_usd。direction=inflow/outflow/flat/unknown；status=complete/partial/provisional。

近5/20日指NYSE常规休市规则下的美股交易日，不是自然日；保留已公布的0，不跳过缺失日。市场日历已维护2025-01-09特别休市，未来临时休市需维护；提前收盘保守按16:00 ET判断。

来源：Farside公开表；CryptoETF官方免注册MCP（明确提供30日历史；极端节假日组合可能不足20个交易日）；BTC还有TFTC公开JSON（CC BY 4.0署名）。优先选择最新记录日期的有效来源，不混拼不同来源，不以AUM变化或成交量替代净申赎。来源数据可能修订；不同来源存在更新差异时warnings说明。

Cloudflare独立Durable Object按btc/eth缓存15分钟，每15分钟预更新；上游失败时最多使用原抓取时间7天内的成功数据并标注缓存回退和滞后。全部无效时HTTP503，不生成演示数字。当前不需要注册或配置数据API Key。

JavaScript SDK新增 `client.getEtfFlows({asset:"btc"})`。完整Schema见EtfInput、EtfDay、EtfPeriod、EtfReport。

```bash
curl -X POST 'https://agent.vestpivot.com/api/v1/agents/etf-flows/analyze' -H 'Content-Type: application/json' --data '{"asset":"eth"}'
```

## 7. 后续Agent规划（草案，均不可调用）

### 阶段2 · wallet-flow · 钱包资金流 Agent

针对单个钱包分析代币流入流出、主要交易对手和地址集中度。

草案入口：`POST /api/v1/agents/wallet-flow/analyze`；status=planned，callable=false。

| 参数 | 草案类型、范围与默认值 |
|---|---|
| chain | ethereum \| bsc |
| wallet_address | 0x开头40位EVM地址 |
| lookback_hours | 整数1–168，默认24 |
| token_address | 可选，限制分析的代币 |

建议返回：wallet、window、net_flows[]、counterparties[]、large_transfers[]、coverage、sources[]。具体字段类型与完整度规则须在实现前另发OpenAPI，当前不是可用契约。

依赖：可分页转账索引、历史估值或明确的当前价估值、地址标签。


### 阶段2 · liquidity-watch · 流动性监控 Agent

持续采集指定代币的池子，区分估值变化与增减流动性事件，生成告警。

草案入口：`POST /api/v1/agents/liquidity-watch/monitors`；status=planned，callable=false。

| 参数 | 草案类型、范围与默认值 |
|---|---|
| chain | ethereum \| bsc |
| token_address | 代币合约地址 |
| interval_minutes | 枚举5/15/60，默认15 |
| drop_threshold_pct | 大于0且小于100，默认30 |
| duration_hours | 整数1–168，默认24 |

建议返回：monitor_id、status、next_run_at、expires_at、snapshot_count、alerts[]。具体字段类型与完整度规则须在实现前另发OpenAPI，当前不是可用契约。

依赖：调度器、持久化历史、池子事件索引、租户鉴权与监控额度。

后续草案操作：`GET /api/v1/agents/liquidity-watch/monitors/{monitor_id}`。
后续草案操作：`DELETE /api/v1/agents/liquidity-watch/monitors/{monitor_id}`。

### 阶段3 · market-pulse · 市场状态 Agent

分析指定交易市场的价格、成交量、波动率和交易深度。

草案入口：`POST /api/v1/agents/market-pulse/analyze`；status=planned，callable=false。

| 参数 | 草案类型、范围与默认值 |
|---|---|
| exchange | binance \| okx |
| market_type | spot，首版仅现货 |
| symbol | 统一格式BASE/QUOTE，例如BTC/USDT |
| lookback_hours | 枚举1/4/24/168，默认24 |

建议返回：instrument、price、volume、volatility、order_book_depth、signals[]、coverage、sources[]。具体字段类型与完整度规则须在实现前另发OpenAPI，当前不是可用契约。

依赖：交易所公共行情、K线与深度缓存、统一交易对映射。


### 阶段3 · portfolio-risk · 组合风险 Agent

汇总代币风险敞口、资产集中度和相关性，分析用户提供的持仓组合。

草案入口：`POST /api/v1/agents/portfolio-risk/analyze`；status=planned，callable=false。

| 参数 | 草案类型、范围与默认值 |
|---|---|
| positions | 数组1–50项，每项{chain,token_address,quantity}；quantity为非负十进制字符串 |
| valuation_currency | USD，首版固定 |

建议返回：valuation、weights[]、concentration、token_risks[]、correlation、unpriced_positions[]、coverage、sources[]。具体字段类型与完整度规则须在实现前另发OpenAPI，当前不是可用契约。

依赖：token-risk、历史价格、缺失估值处理、持仓隐私与授权。


### 阶段4 · event-risk · 项目事件风险 Agent

汇总代币解锁、治理、升级和安全事件，并保留事件原始来源。

草案入口：`POST /api/v1/agents/event-risk/analyze`；status=planned，callable=false。

| 参数 | 草案类型、范围与默认值 |
|---|---|
| chain | ethereum \| bsc |
| token_address | 代币合约地址 |
| lookahead_days | 整数1–90，默认30 |
| event_types | 可选数组：unlock/governance/upgrade/security；默认全部 |

建议返回：events[]、timeline、risk_notes[]、coverage、sources[]。具体字段类型与完整度规则须在实现前另发OpenAPI，当前不是可用契约。

依赖：可信事件与解锁数据、项目官方来源、事实去重与时间验证。


## 8. 演进顺序与新Agent接入清单

第一阶段：统一当前六个接口、目录、错误格式、OpenAPI、SDK和兼容旧网页（本次已实现）。

第二阶段：优先钱包资金流与持续流动性监控，补齐可分页索引、历史与任务运行能力。此阶段先实现API Key、租户和额度，再开启持久监控；不能将public preview的IP限流当作监控任务授权。

第三阶段：市场状态和组合风险，通过独立适配器复用行情与token-risk，保留数据依赖失败的传播方式。第四阶段：事件风险，先保证官方来源、时间与证据质量，再引入模型总结。

未来耗时任务应使用POST /api/v1/runs返回202及run_id，再用GET /api/v1/runs/{run_id}轮询；需要持久化、队列、鉴权、过期/取消和幂等键后再上线。这些运行接口当前未实现，未加入可调用OpenAPI。若增设webhook，必须有签名校验、防重放、重试和回执，不能现在承诺通知送达。

每新增Agent：确定稳定ID和边界 → 定义输入/输出Schema与数据范围 → 设计缓存/时效/费用/权限 → 实现适配器和证据 → 验证异常、限流与缺失数据 → 更新目录与OpenAPI → 加入SDK与示例 → 验收后将planned切换live。新Agent不复制旧报告引擎，不直接耦合网页组件。

## 9. 旧接口兼容

GET /api/analyze?chain=ethereum&address=0x…和GET /health保持现有返回，供已有网页使用。旧接口没有Envelope，且包含浏览器回退所需的内部采集载荷；新应用不要依赖旧接口。当前未设停用日期；未来迁移提前公告，再实施停用。

## 10. 验证

```bash
node tools/build-api-docs.mjs
node --test test_worker.mjs test_providers.mjs test_api.mjs
```

测试验证统一响应、六个功能边界、目录上线状态、CORS、未知参数拒绝、大小限制、稳定错误码、503保留诊断数据以及OpenAPI引用解析。底层真实数据覆盖受既有免费接口限制；本次接口整理没有新增数据供应商或付费服务。


## BTC 恐惧与贪婪指数 Agent · fear-greed

POST /api/v1/agents/fear-greed/analyze

输入：`{"asset":"btc"}`，必填，仅btc/BTC，未知参数拒绝。

返回data.latest（date/timestamp/value/classification/classification_zh）、comparisons.yesterday/last_week/last_month（日期、值、分类、change_points）、history、history_days、stale、source、methodology、generated_at、warnings、cache。0–100指数，变化单位点，UTC自然日回溯，缺失null。最近31日最多31条，缓存900秒；最新数据超过48小时告警，上游失败503，不生成模拟数据。SDK：getFearGreed({asset:"btc"})。完整字段见OpenAPI FearGreedInput/FearGreedReport。

来源Alternative.me：https://alternative.me/crypto/fear-and-greed-index/ ，调用方显示指数时必须在数据旁标明来源。
