本节摘要:当外部智能体(LLM 应用、自动化脚本、你自己写的助手)需要访问 QuantDinger 时,正确的入口不是主 API,而是 Agent Gateway——官方 README 口径的 /api/agent/v1 专用入口。本节先回答"为什么不直接开主 API":权限粒度、审计隔离、限流模式、密钥管理四条理由;然后展开作用域 token 的分级设计——只读行情、只能 paper、可交易三级,默认 paper-only;最后给出 token 的签发、保管、吊销全流程与最小调用示例。本节的思想与《Harness 工程:从零打造智能体运行环境》第 05 章《权限与审批门》一脉相承:凭证的权限集合必须恰好覆盖任务需要,一项不多。
主 API 面向人:浏览器界面背后的全功能接口,持有它等于持有整个系统的全部能力。把这种接口交给一个会自主发起请求的智能体,问题立刻出现:
| 维度 | 主 API 的问题 | Agent Gateway 的对策 |
|---|---|---|
| 权限粒度 | 全有或全无 | token 绑定作用域,按能力分级 |
| 审计 | 混在人工操作里 | 智能体调用独立记流,事后可归因 |
| 限流 | 按人的节奏设计 | 按智能体的节奏设计(可突发、可循环) |
| 密钥管理 | 一把主钥匙 | 一任务一 token,可吊销不伤主体 |
第一行是最本质的:智能体的调用模式是"自主决策后的动作",出错时没有人类即时纠偏,所以权限边界必须在一开始就收窄——这正是《Harness 工程》第 05 章《权限与审批门》的核心论点:给智能体的凭证,权限集合要恰好覆盖任务,出错时的爆炸半径才是设计出来的,而不是运气决定的。
网关的工程位置(第 02 章六进程模型的延伸):/api/agent/v1 由 backend 进程承载,动作仍由各 worker 执行——HTTP API 不拥有长循环的原则不变,网关只是多了一扇为智能体设计的门,不是另一套系统。
官方 README 口径的作用域 token 分级(具体作用域名称以官方文档为准):
| 级别 | 能做什么 | 不能做什么 | 适合谁 |
|---|---|---|---|
| 只读行情 | 查行情、查公开数据 | 下任何单、改任何配置 | 行情分析类智能体 |
| 只 paper | 上述 + paper 单、跑回测 | 触达真实资金的一切操作 | 研究与实验类智能体 |
| 可交易 | 上述 + 真实订单(仍过第 09 章决策门) | 改系统配置、动应急开关 | 少数受信任的执行场景 |
两条铁律。其一,默认 paper-only:新签发的 token 从最低可用级别起步,用出可信的调用记录后再升级——升级是一次显式决策,不是默认漂移。其二,可交易级 token 必须叠加约束:绑出口 IP、设调用频率上限、配额每日复核(能力以官方文档为准);即便如此,它触发的订单仍然要走第 09 章决策门与第 8.3 节对账——智能体不是特权用户,是持低权限凭证的用户。
选级不靠感觉,靠任务清单反推(示意对照,作用域名称以官方文档为准):
| 智能体任务特征 | 建议级别 | 依据 |
|---|---|---|
| 只读行情、写自己的分析笔记 | 只读行情 | 全程不需要触达任何账户动作 |
| 跑回测、做参数实验、paper 验证 | 只 paper | 需要提交任务与虚拟订单,但不碰真实资金 |
| 按既定规则执行真实订单 | 可交易 | 但必须叠加约束,且过决策门 |
这张表的用法是从上往下找第一个能覆盖任务的级别,而不是从下往上图省事。任务清单里出现任何一个"也许以后会需要"的项,都不构成升级理由——将来需要时再走显式升级,台账上多一行记录,比权限长期闲置在高位安全得多。
token 生命周期 签发 ──▶ 保管 ──▶ 使用 ──▶ 轮换/吊销 │ │ │ │ 一任务 环境变量 审计记流 用完即吊 一token 不进代码 频率复核 泄露即吊
| 环节 | 做法 | 常见错误 |
|---|---|---|
| 签发 | 明确任务与有效期,选最低够用级别 | 为省事直接签最高级 |
| 保管 | 环境变量或密管文件,权限收紧 | 写进智能体的提示词或代码库 |
| 使用 | 每次调用带 token,审计侧按 token 归因 | 多个智能体共用一个 token |
| 轮换 | 按固定周期换新(示意建议:季度) | token 一用数年 |
| 吊销 | 任务结束立即吊销;疑似泄露立即吊销 | 任务死了 token 还活着 |
"疑似泄露立即吊销"值得强调:智能体的运行环境(脚本、配置、日志)比人类环境更容易把凭证带出去,吊销成本极低而纵容成本极高——宁可误吊十次,不可放行一次。
"定期复核"也可以脚本化——从网关审计日志统计每个 token 的最后使用时间,闲置即列入吊销候选(纯标准库,输入为审计日志导出的 CSV):
# token_review.py —— 作用域 token 定期复核(输入为网关审计日志导出的 CSV) import csv from datetime import datetime IDLE_DAYS = 30 # 超过该天数未使用即列吊销候选(示意值) def review(path, today=None): today = today or datetime.now() last_seen, scope = {}, {} with open(path, newline="", encoding="utf-8") as f: for row in csv.DictReader(f): tid = row["token_id"] ts = datetime.fromisoformat(row["ts"]) if tid not in last_seen or ts > last_seen[tid]: last_seen[tid] = ts scope[tid] = row["scope"] for tid in sorted(last_seen): idle = (today - last_seen[tid]).days flag = "吊销候选" if idle > IDLE_DAYS else "在用" print(f"{tid} 作用域={scope[tid]} {idle} 天未用 {flag}")
复核的输出不只是清理清单:在用 token 的作用域分布、调用节奏的变化,都是第 11 章可观测层在智能体通道上的输入。一次典型的智能体接入也遵循同一节奏(示意走查):为行情分析智能体签发只读 token——当天做反向验证(只读 token 打 paper 下单接口,应得到权限不足的明确错误码)——运行两周积累调用记录——按记录决定是否升级到只 paper 级。升级决策的依据是"实际调用都做了什么",而不是"我预期它会做什么"。
(命令形态示意,路径、参数与鉴权头以官方文档为准。)
# agent_api_probe.sh —— 用只读作用域 token 做一次最小调用(示意) export PATH="/usr/bin:$PATH" curl -s "https://你的域名/api/agent/v1/market/ticker?symbol=BTC-USDT" \ -H "Authorization: Bearer QD_AGENT_TOKEN_READONLY" \ -H "Content-Type: application/json"
把 token 放进环境变量后,示例里直接引用变量名即可(上例为可读性写成了占位名)。预期行为检查:用只读 token 调 paper 下单接口,应得到权限不足的明确错误码——拿到错误码是好事,说明边界真实存在;如果成功了,立刻停下排查作用域配置。这个"反向验证"与第 8.1 节"故意触发错误"是同一个思想:边界要靠越界尝试来确认。
| 问题 | 排查方向 | 要点 |
|---|---|---|
| 智能体调用总是被拒 | 凭证无效还是权限不足 | 先反向验证定位是凭证问题还是作用域问题 |
| 想给智能体加能力 | 走升级流程还是换签新 token | 任务变了就换签新 token,旧的原地吊销 |
| 审计日志查不到归因 | 多智能体共用一个 token | 立即拆分:一任务一 token |
| 怀疑 token 泄露 | 宁可误吊 | 先吊销再求证,恢复成本低 |
| 网关延迟高于主 API | 限流模式差异 | 对照网关限流配置确认是否预期内 |
第一行值得多说一句:凭证无效与权限不足是两类问题——前者是凭证本身的问题(过期、吊销、抄错),后者是凭证有效但作用域不够。排查时先做一次反向验证把两类分开,能避免"反复换 key 却发现 key 没坏"的无效循环;而如果权限不足出现在预期外的接口上,那就是一次作用域配置的现场纠偏机会,值得记进 token 台账。
网关解决了"谁能进来、能做什么"。下一个问题是"进来之后用什么姿势做事"——MCP server 把查行情、跑回测、下 paper 单封装成智能体原生理解的工具,下一节讲工具清单、挂接配置与工具层的安全边界。