让 Agent 调内部系统,卡点通常不在模型或提示词,而在调用主体和权限范围没定下来。可行的顺序是:先把调用身份固定成一个独立账号,只申请只读范围,跑通一条最小查询,逐字段核对返回值,确认无误后再单独走一次写权限审批,并且限制可写字段和调用频率。这样任何一步出问题都停在这一步,不会带着不确定的权限去碰线上数据。
如果目标只是让 VM0 读内部系统数据,就先别把写权限一起申请。做法是单独建一个只读服务账号,申请单写到字段级和条数上限,脱离 Agent 先用一条最小请求验证连通,再逐字段比对返回结果。判断是否继续的标准是:字段名、类型、数据范围都对得上。对不上就先改权限或接口,不要靠 Agent 侧做兼容。
确定调用身份:复用现有服务账号还是单独建一个账号
先把调用主体固定下来,后面所有权限申请、限流配置、日志排查才有附着点。两种方式没有绝对优劣,差别主要在责任归属和审计。
- 复用现有服务账号:接入快,权限现成,不用再走一轮审批。问题是对方系统的访问日志里,Agent 的调用和你原有的定时任务、人工后台混在同一个账号下,出问题时无法按调用方切开。密钥轮换也会互相牵连。
- 单独建一个账号:需要走一次账号申请和密钥分发流程。换来的是独立可控:可以单独停用、单独限流、单独按账号名筛日志,责任边界清楚。
本例建议单独建账号。理由是 VM0 的调用特征和人工系统不一样:调用频次相对规律、读取字段固定、失败容易触发重试。混在共用账号里,重试产生的请求会和正常业务叠在一起,排查成本明显上升。账号命名带用途更容易事后对账,例如 svc-vm0-readonly,写权限阶段再单独建一个 svc-vm0-write,不要复用同一个。
验证方式很直接:用这个账号单独发起一次调用,然后到对方系统的访问日志或审计页里按账号名过滤,看能不能筛出刚才这一条。筛不出来说明账号没有独立标识,后面出问题一样定位不了。
只申请只读范围,列出这次要读的字段清单
权限压到刚好够用,比事后收紧容易得多。申请单里建议把这个表填清楚,字段级而不是接口级:
| 系统 | 接口 / 表 | 字段名 | 类型 | 用途 |
|---|---|---|---|---|
| 订单系统 | GET /order/detail | order_id | string | 定位单据 |
| 订单系统 | GET /order/detail | status | string | 判断状态 |
| 订单系统 | GET /order/detail | updated_at | timestamp | 判断是否需二次确认 |
申请范围描述要包含三个维度:接口范围(只列 GET 类查询)、字段范围(明确写出上面清单)、数据范围(时间窗、组织或租户 ID、单次返回条数上限)。只有接口没有数据范围,等于把整张表交出去。
用途文字控制在两三句,说明谁在用、读什么、不写什么、数据保留多久。例如:“供内部自动化任务查询订单状态,仅读取上述三个字段,不做任何写操作,查询结果不留存超过任务运行周期。”这类描述比“业务需要”更容易通过审批,也方便后续追责时对照。
用一条最小请求验证连通性
先脱离 Agent,用命令行或平台自带的调试面板单独发一次。这样能把“网络不通”“身份不对”“接口写错”三类问题分开,不会都堆到 Agent 日志里。
POST https://<内部系统域名>/<接口路径>
Authorization: Bearer <只读账号 Token>
Content-Type: application/json
X-Request-Id: <每次调用唯一,便于在对方日志里反查>
{
"query": "<查询条件,例如单据号>",
"fields": ["order_id", "status", "updated_at"],
"limit": 1
}
说明几点替换项:鉴权头按对方要求改,有的系统用 AK/SK 签名,有的走内网网关换取短期 token,不要照抄。请求体里 limit 先设成 1,目的是只验证链路,不验证数据量。如果对方只提供固定接口、不支持指定 fields,就把 fields 从请求体里去掉,改成在申请单里约束。
期望看到的返回结构通常是:HTTP 200,业务层 code 为成功值,data 是一个数组或对象,字段名和申请清单一致。如果返回 200 但 data 为空,先别急着改代码,换成一条确定存在的记录再试,区分“链路通但没数据”和“链路根本不通”。
在返回结果里核对字段是否与预期一致,记录错误码与原因
“能通”和“能拿到正确数据”是两件事。用一条已知记录做字段比对,把差异记下来:
| 预期字段 | 实际返回 | 是否一致 | 处理 |
|---|---|---|---|
| order_id (string) | order_id (string) | 是 | — |
| status (string) | status (int 枚举) | 否 | 确认枚举映射后再改 Agent 解析 |
| updated_at (timestamp) | 未返回 | 否 | 回到申请单补字段权限 |
错误码不要只看日志里那一行,建议按三列记下来,形成自己的排查表:错误码 / 返回提示 / 本次排查方向。常见的几类:
- 401 / 鉴权失败:token 过期、签名方式不对、时钟偏差导致签名失效。先确认 token 有效期和服务器时间。
- 403 / 无权限:账号建对了但字段没批,或数据范围不含这条记录。回申请单核对,不要在代码里绕过。
- 404 / 路径或资源不存在:接口路径写错,或查询的那条记录本身不在授权范围内。
- 429 / 触发限流:说明调用节奏超过对方阈值,记录下来,作为后面设频率上限的依据。
- 200 但业务 code 非成功:这类最容易漏,务必把业务 code 一起记,不要只看 HTTP 状态。
同一类错误连续出现两次以上再动手改配置,避免因偶发抖动反复调整权限。
验证通过后单独申请写权限,限制可写字段与调用频率
只读链路跑通、字段核对无误,再走写权限。写权限是独立的一次申请,不要挂在只读账号上,也不要在原申请单上追加。
可写字段白名单要逐个列出,并注明允许的操作类型(新增、更新、作废)。例如只允许更新 remark 和 assignee,不允许改 status 和金额类字段。清单之外的一律不批,Agent 侧也不要做动态字段拼接。
频率上限建议在申请时一次写死:每分钟调用次数上限、并发数限制为 1、单次批量条数上限、失败重试次数上限。这几项不是性能优化,是防止重试风暴把线上写接口压出问题。具体数值需要结合对方系统的承载能力和你的任务周期确认,不要照搬别人的值。
写操作留痕字段也一并提:来源系统标识(写 VM0 或账号名)、request_id、目标记录 ID、改动前后值、操作时间戳。这几项里至少 request_id 和目标记录 ID 必须落在对方日志里,否则线上数据被改了以后没法还原是哪次调用改的。
最后确认一次边界:写接口先在测试数据或非关键单据上跑一次,确认改动范围和留痕都符合预期,再放到正常任务里。任何一步对不上,退回只读状态,不要带着写权限继续调。