先说判断方向:密钥通常应放在平台侧的凭据/连接配置里,请求头则在工具(或连接器)侧随调用拼装发出。绝大多数“总卡鉴权”不是密钥本身错,而是两层各配了一半——平台存了密钥但工具没把它带进请求头,或工具里写死了密钥、平台注入时又覆盖掉。要判断该配哪一层,先抓一次失败调用的请求和响应,看失败发生在“平台到内部系统”那一跳,还是“Agent 到工具”那一跳。
适用场景:内部 HTTP 接口接入 JiuwenSwarm 后持续返回 401/403。操作动作:先在日志里定位失败跳数,再把密钥收敛到平台侧配置项,由工具侧按内部系统文档构造请求头。验证方式:单独用同一密钥发一次最小请求,对照状态码判断是密钥问题还是平台问题。风险边界:请求头字段名、前缀、来源限制只能以内部系统接口文档为准,未在文档中出现的头不要臆造;配置项命名需结合你所部署的版本确认。
先确认失败发生在哪一跳
一次工具调用至少要经过两段:平台调度到工具执行,工具再发起 HTTP 请求到内部系统。这两段的鉴权失败长得很像,但修的地方完全不同。可以先把同一请求的出入参和状态码抓下来,按下面几项对照:
- 平台侧出站日志:有没有记录这次调用的目标地址、请求 id、返回状态码;如果平台侧根本没有出站记录,失败发生在 Agent 到工具这一段(工具没被调到,或工具入参校验就挂了)。
- 工具侧执行日志:打印请求方法、路径、请求头名称(值脱敏成前缀加长度)、响应状态码和响应体前若干字符。有这条日志且状态码是 401/403,说明请求确实发到了内部系统,问题在凭据或请求头。
- 内部系统侧访问日志:如果能看到对应时间点的记录,注意区分“没收到请求”(网络或路由问题)和“收到但拒绝”(鉴权问题)。
把这三处时间点对齐,标注失败在哪一段,再往下看对应小节。不要在没有定位跳数的情况下同时改密钥和请求头,改完就无法判断是哪一处生效。
把密钥放进平台侧配置项
密钥建议只在一处维护:平台的凭据或连接配置。任务声明、Agent 提示词、工具描述里都不要出现明文密钥,原因很实际——这些内容通常会被记录、展示或随任务定义一起导出。一个通用骨架如下,字段名以你环境中的配置项为准:
# 平台侧连接配置骨架(占位符,勿填真实值)
connections:
internal_api:
base_url: "https://<internal-host>"
auth:
type: "header" # 按内部系统要求,也可能是 query 或签名
header_name: "<AuthHeaderName>"
value_template: "<Prefix> {token}"
token_ref: "secret://internal_api_token" # 指向凭据存储,不写明文
timeout_ms: 10000需要确认的三件事:token_ref 指向的凭据在平台里能正常解析;value_template 的前缀和内部系统文档一致(带不带前缀、前缀后是否留空格);header_name 拼写与文档一字不差。以下位置不应该出现明文密钥:任务或工作流的声明文件、Agent 的系统提示词、工具的自然语言描述、代码仓库中的默认配置、以及异常日志里直接打印的请求头。
在工具侧补上请求头
平台存了密钥,不代表请求头会自己出现。工具侧要做的是从平台注入的配置里取出凭据,构造请求头,再随 HTTP 调用发出。下面是一个通用构造骨架,语言和框架可替换:
def build_headers(cfg):
headers = {"Content-Type": "application/json"}
name = cfg["auth"]["header_name"]
value = cfg["auth"]["value_template"].format(token=cfg["auth"]["token"])
headers[name] = value
return headers
# 调用前打印脱敏信息,确认请求头确实随请求发出
print("auth header:", name, len(value), value[:4] + "***")字段来源需要逐项对齐内部系统接口文档:header_name 是文档里写的鉴权头名称;value_template 决定是否带前缀及空格;token 来自平台注入的凭据,不从环境变量或代码常量里另取一份。文档没写的自定义头不要凭经验加,很多网关对多余的头会直接拒绝。如果工具框架支持在连接器层统一注入请求头,优先放在那里,避免每个工具函数各写一遍。
单独发一次最小请求验证密钥
把密钥问题和平台问题分开,最省事的办法是绕过平台,用同一份密钥直接发一次最小请求。命令中的地址、路径、头名称和凭据全部用占位符替换:
curl -s -o /dev/null -w '%{http_code}\n' \
-X GET 'https://<internal-host>/<probe-path>' \
-H '<AuthHeaderName>: <Prefix> <TOKEN_COPIED_FROM_PLATFORM_CREDENTIAL>'期望是 200 或 204。对照判断:401 通常指向密钥无效、过期或格式不对(前缀、空格、编码);403 通常是密钥有效但账号无权限,或存在来源 IP、来源应用的限制;404 说明路径不对,不要把它混进鉴权问题里排查;超时则先看网络和出口策略。这一步通过而平台侧仍失败,问题基本落在平台注入或工具拼装请求头这一层,回头检查上一小节的两处代码。
密钥轮换时的替换顺序
换密钥要避免整条链路同时中断,顺序建议按“先并存、再切换、后下线”走:
- 在平台凭据存储里新增一份新版本密钥,暂时不改成默认值。
- 在内部系统侧开启新旧密钥并存的过渡状态。多数网关支持配置多把有效密钥;如果不支持,就选调用低峰时段切换,并缩短过渡时间。
- 把平台配置中的默认密钥指向新版本,重载配置或重启对应组件,让配置生效。
- 观察日志中工具侧的请求头前缀和状态码,以及平台侧的失败计数,确认没有新增 401/403。
- 判定可以下线旧密钥的标准:一段时间内所有调用均返回非 401/403,且日志中不再出现旧密钥的记录;满足后再从内部系统侧删除旧密钥,并清理平台侧的旧版本凭据。
过渡期间不要同时修改请求头名称和密钥本身,两个变量一起动,出问题后很难判断是哪一项导致失败。轮换完成后,顺手确认任务声明、提示词和代码里没有残留旧密钥的明文副本。