工具绑定凭证:交互方案
本文定第二批的界面:工具怎么绑定「对接凭据」里的凭证、「对接凭据」页要改什么。凭证是公用的:同一条凭证工作流节点能用,工具也能用。
| # | 决定(2026-10-02 用户确认) | 取代了什么 |
|---|---|---|
| 1 | 工具直接用现有的 HTTP Api Key(httpApiKey)、HTTP Basic Auth(httpBasicAuth)、HTTP Bearer Token(httpBearerToken),一个字段都不改。API Key 只写进请求头,一期没有放查询参数或 Cookie 的需求 | tool-credentials.md 第 4 节、交接 T2-2 的四种新类型 toolApiKey 等 |
| 2 | 新增一个通用的 OAuth2 客户端凭证类型 | — |
| 3 | 不做到期日 | tool-credentials.md 第 8 节「到期提醒」 |
| 4 | 「对接凭据」页不加页签、不分组、不加类型列和引用列 | 工具编辑页方案第 5 节「按用途分两组」、交接 T2-7 的分组与被引用数 |
| 5 | 编辑对话框修复密钥框的占位串问题(第 3.2 节方案 B) | — |
| 6 | 删除保护保留:被工具绑定的凭证不能删 | — |
截图是本机 2026-10-02 的整页(1440×900,含左侧约 220px 导航栏),团队「数据库团队」(1111),三条凭证是真实数据。 示意图只画单个对话框或单个区块,各图下面写明。本机还没有工具用的凭证,示意图里的凭证名与工具名是示例数据,沿用工具编辑页方案里的「Jax 开放接口」等。
1. 现状
- 列表三列:名称、更新时间、创建时间(图 1)。「新增凭据」先弹出类型选择,110 种类型按品牌平铺成卡片,靠搜索框找(图 2)。
- 三种 HTTP 类型目前只有工作流 HTTP 节点在用(
components/nodes/agentflow/HTTP/HTTP.ts:35)。节点把它们写进请求的方式(:238-247)与工具需要的完全一致,见第 5 节。 - 通用的 OAuth2 客户端凭证类型不存在。现有的七个 OAuth2 类型(Gmail、Google 日历 / 文档 / 云盘 / 表格、Outlook、Teams)都是要用户登录授权的那种,不是 client_credentials。
- 编辑对话框把密钥显示成一串圆点(图 3)。圆点是服务端回填的占位串
_FLOWISE_BLANK_07167752-…(server/src/utils/index.ts:78),前端保存时不提交等于占位串的字段(AddEditCredentialDialog.jsx:174)。 2026-10-02 本机实测:编辑一条 HTTP Bearer Token,在圆点后面接着输入abc再保存,提交的是{"token":"_FLOWISE_BLANK_07167752-1a71-43b1-bf8f-4f32252165dbabc"}。这串字符被存成新令牌,之后调下游必然认证失败。不碰密钥框直接保存时不提交密钥,原值保留。 - 删除不检查有没有人在用。
- 凭证接口的权限检查是空实现(
server/src/copyright/rbac/PermissionCheck.ts:5-9、:25-27),团队边界只靠x-team-id。T2-1(aimp-platform69897260)已让按 ID 读、改、删都按它校验。x-team-id不核对成员身份是已知问题(agent-runtime-identity.md§2.4),不在本次范围。

图 1 现状:「对接凭据」列表(整页截图,团队 1111 的三条 OpenAI API 凭证)。本方案不改这张表。

图 2 现状:「新增凭据」的类型选择(整页截图)。新增的 OAuth2 类型作为第 111 张卡片出现在这里,搜「oauth」可找到。

图 3 现状:编辑对话框,「OpenAI Api Key」里的圆点是占位串(整页截图)。
2. 改动一览
| 位置 | 改动 | 不变的 |
|---|---|---|
| 「对接凭据」页 | 多一种类型「OAuth2 客户端凭证」;它的编辑对话框多一个「测试」按钮(3.1);删除被工具绑定的凭证时拒绝并列出工具(3.3) | 列表、搜索、类型选择的样子,其余 110 种类型 |
| 编辑对话框(所有类型共用) | 密钥框里还是占位串时,一点进去就清空;离开时没输入就恢复(3.2) | 新建流程;不碰密钥框直接保存时保留原值 |
| 工具编辑页「认证」区块 | 放开「关联固定凭证」:下拉列本团队四种可绑定类型的凭证、新建凭证、写入摘要、失效提示;请求头敏感值提示(第 4 节) | 其余三种认证方式 |
| 工作流 | 无 | HTTP 节点仍只认三种 HTTP 类型,看不到 OAuth2 类型(未决问题 3) |
工具能绑定的类型是固定的四种:httpApiKey、httpBasicAuth、httpBearerToken、新增的 OAuth2 类型。平台服务端维护这张清单,resolve 按它校验,工具编辑页按它过滤下拉。
三种 HTTP 类型的定义文件不是为工具写的,不在定义里加标记,所以用清单而不是给类型加字段。
3. 「对接凭据」页
3.1 新类型:OAuth2 客户端凭证
类型名 oAuth2ClientCredentials,标签 OAuth2 客户端凭证(2026-10-02 用户决定改中文,原定英文 OAuth2 Client Credentials)。类型选择的搜索按类型名匹配,搜「oauth」能和 Gmail OAuth2 等排在一起。字段说明用中文,显示在字段名旁的悬浮提示里(现有对话框已支持,CredentialInputHandler.jsx:51)。
| 字段 | 名称 | 类型 | 必填 | 说明(悬浮提示) |
|---|---|---|---|---|
| Token URL | tokenUrl | string | 是 | 令牌地址,必须是 http:// 或 https:// 开头 |
| Client ID | clientId | string | 是 | — |
| Client Secret | clientSecret | password | 是 | 保存后不回显 |
| Scope | scope | string | 否 | 多个用空格分隔 |
| Client Authentication | clientAuthentication | options | 是,缺省「放在请求体」 | client_id / client_secret 放在请求体,或放在 Basic 请求头(RFC 6749 §2.3.1 两种都允许) |
平台按这些字段向 Token URL 换 access_token,按返回的 expires_in 缓存,提前 60 秒重取。工具调用时写成 Authorization: Bearer <access_token>。
图 4 新建 OAuth2 客户端凭证(单个对话框,示例数据)。与图 3 是同一个对话框组件,字段按类型定义渲染;「测试」按钮只在这个类型下出现。
- 「测试」按当前表单值真实换一次令牌。新建时未保存也能测,测试接口不落库。编辑时没改的 Client Secret 由服务端用库里的原值补上,明文不回前端。
- 三种 HTTP 类型是固定值,平台不知道下游怎么验,没有「测试」;用工具编辑页的「测试调用」验证。
3.2 密钥框的占位串(方案 B)
改动在 CredentialInputHandler.jsx 的 password 输入框,所有类型共用:
图 5 编辑对话框里密钥框的三种状态(只画输入框)。新建时没有占位串,行为不变。
修完后,图 3 那种「在圆点后面接着输入」不会再发生:一点进去圆点就没了。
代价:不能再把已保存的密钥清空。现在把圆点删光再保存,提交的是空字符串,会存成空值;改完后留空离开等于「不改」。
必填的密钥清空了也没法用,不受影响;受影响的是可选的密钥字段,例如 AWS 凭证的 Session Token(AWSCredential.credential.ts:37)、OpenSearch 的密码(OpenSearchUrl.credential.ts:29)。见未决问题 4。
3.3 删除保护
这条凭证被 3 个工具绑定。先到这些工具的「认证」区块改选其他凭证或改为「无须认证」,再删除。
| 工具 | 标识 |
|---|---|
| 告警查询 | query_alerts |
| 告警详情 | get_alert_detail |
| 告警统计 | alert_stats |
查不到这条凭证被哪些工具绑定(工具服务不可用)。为避免删掉正在使用的凭证,这次不删除,请稍后重试。
图 6 删除被工具绑定的凭证(左)与查不到绑定情况(右)(单个对话框,示例数据)。点工具名在新标签页打开该工具的编辑页。
- 点删除图标后,先走现有的确认框;确认后服务端查绑定,有绑定就返回 409 与工具列表,前端弹图 6 左。没有绑定照常删除。
- 绑定检查放在服务端删除逻辑里,对所有删除入口生效(包括直接调
DELETE /api/v1/credentials/:id),只对四种可绑定类型做,其余类型的删除不变。 - 只查得到工具的绑定。工作流节点引用凭证今天没有记录,删掉工作流在用的凭证照旧不拦,这是现状,本次不改。
- agent-base 不可用时拒绝删除(图 6 右),见未决问题 1。
4. 工具编辑页的「认证」区块
大体按工具编辑页方案图 1:认证方式选「关联固定凭证」后出现凭证下拉。下面补齐下拉的内容与三种状态。
图 7 工具编辑页「认证」区块(只画区块;工具编辑页在壳外,没有左侧导航;示例数据)。上:下拉展开;左下:没有可绑定的凭证;右下:绑定的凭证已被删除或不属于本团队。
| 元素 | 内容 | 数据来源 |
|---|---|---|
| 下拉项 | 凭证名 + 类型标签。只列本团队四种可绑定类型的凭证 | 现有接口 GET /api/v1/credentials?credentialName=…,一次传四个类型名(接口已支持数组) |
| 写入摘要 | HTTP Api Key:请求头 X-API-Key;HTTP Basic Auth:Authorization: Basic(用户名 aimp-ro);HTTP Bearer Token:Authorization: Bearer;OAuth2:Authorization: Bearer(向 itsm.example.internal 换取) | 现有接口 GET /api/v1/credentials/:id,只用非密字段(Key、用户名、Token URL) |
| 「新建凭证」 | 打开「对接凭据」的类型选择(图 2 那个对话框),只列四种可绑定类型;选完进入图 3 / 图 4 的编辑对话框;保存后关闭并自动选中新凭证 | 复用 CredentialListDialog、AddEditCredentialDialog |
| 「去对接凭据管理」 | 新标签页打开 /chatV2/credentials。下拉每次展开都重新拉列表,另一个标签页建的凭证回来就能选到 | — |
| 失效提示 | 工具上存的凭证 ID 在本团队查不到(被删、或换了团队)时显示图 7 右下,保存被拦 | 同「写入摘要」,接口返回 404 即失效 |
- 与工具编辑页方案图 1 的差异:下拉不显示密钥末 4 位。末 4 位要服务端解密后另开接口返回;按决定 4 的「只打通绑定」不新增这个接口,用凭证名与类型区分。
- 保存校验:选了「关联固定凭证」没选凭证,提示「请选择凭证」。
- 脚本工具:「关联固定凭证」置灰(第一批已实现,文案不变)。
- 分享给别的团队的工具:调用时用工具所属团队的凭证。别的团队在工具详情里只看到认证方式「关联固定凭证」,看不到凭证名。
| Key | Value |
|---|---|
| Content-Type | application/json |
| X-Api-Key | {{$vars.jaxKey}} |
图 8 请求头敏感值提示(只画请求头表格,示例数据)。保存时不阻断。
提示条件(tool-credentials.md 第 9 节):请求头名是 Authorization,或名字含 key / token / secret / password(不分大小写),且值是字面量或 {{$vars.xxx}}。值是 {{$sys.xxx}} 时不提示。
5. 运行时:四种类型怎么写进请求
工具调用时,平台的 resolve 接口把凭证解析成注入集 {version, headers, ttlSeconds}(契约 docs/contracts/tool-credentials/),agent-base 在前置 Hook 之后、发请求前写入(tool-credentials.md 第 5、7 节,交接 T2-3、T2-5)。三种 HTTP 类型的写法与工作流 HTTP 节点逐字一致,同一条凭证在两处的效果相同:
| 类型 | 注入集 | HTTP 节点的写法 | ttlSeconds |
|---|---|---|---|
| HTTP Api Key | headers[key] = value | HTTP.ts:247 | 60 |
| HTTP Basic Auth | Authorization: Basic base64(用户名:密码) | HTTP.ts:240 | 60 |
| HTTP Bearer Token | Authorization: Bearer 令牌 | HTTP.ts:244 | 60 |
| OAuth2 客户端凭证 | Authorization: Bearer access_token | 节点不支持 | 令牌剩余有效期减 60 秒,最长 300 |
agent-base 按 ttlSeconds 在内存里缓存注入集,所以改了凭证,三种 HTTP 类型 60 秒内对工具生效。OAuth2 的令牌缓存按「凭证 ID + 更新时间」作废,改完下一次调用就重取。
HTTP Api Key 的 Key 为空时 HTTP 节点什么都不写(HTTP.ts:245),resolve 改为报「凭证缺少 Key」,不让工具带着空认证调下游。
6. 被否决的方案
| # | 做法 | 否决原因 |
|---|---|---|
| 1 | 新建四种工具专用类型(toolApiKey 等),「对接凭据」页分「工具凭证」「模型与节点凭证」两组(本文 2026-10-02 上午的初稿) | 三种 HTTP 类型的写法与工具需要的一致,新建只多出三种重复类型;凭证本来就公用,按用途分组反而要回答「一条凭证两处都用算哪组」。用户 2026-10-02 决定直接复用 |
| 2 | 给 HTTP Api Key 加「位置」选项(请求头 / 查询参数 / Cookie) | HTTP 节点不读这个字段,一律写请求头;选了查询参数的凭证在节点里会被写错位置。以后有需要时单独建一个新类型 |
| 3 | 给可绑定的类型新写一个对话框 | 凭证公用,两个对话框编辑同一条凭证,行为必然分叉 |
| 4 | 只在新写的地方处理占位串,现有对话框不动(方案 A) | 问题对所有类型都存在,且后果是下游调用失败、原因难查。用户 2026-10-02 选方案 B |
| 5 | 在类型定义里加 usage 字段标出可绑定类型 | 要改三种 HTTP 类型的定义文件;可绑定类型只有四种,服务端一张清单就够 |
7. 关键取舍
- 凭证公用:工作流与工具共用一条凭证,改一处两边一起变。删除保护只覆盖工具,工作流的引用照旧不拦。
- 不显示末 4 位:省掉一个解密接口,代价是同名凭证只能靠名字区分。
- 可绑定类型清单写两处:服务端一份(权威,
resolve与删除保护用),前端一份(只用来过滤下拉)。四种类型很少变;前端多列或少列,resolve会拒绝,不会放过错的类型。 - 静态类型 60 秒生效:
ttlSeconds越短,改凭证生效越快,agent-base 回平台取注入集越频繁。60 秒内同一条凭证最多取一次。 - MUI 对话框进 antd 页面:工具编辑页用 antd,「对接凭据」的两个对话框是 MUI。复用就得在工具编辑页挂 MUI 对话框,主题与层级要实测(工具编辑页在壳外)。
8. 影响面
| 位置 | 改动 | 任务卡 |
|---|---|---|
components credentials/OAuth2ClientCredentials.credential.ts 与 dist/ | 新增一种类型。用 corepack pnpm@10.20.0 build 构建,git status 应只多出这个类型的产物,多出别的先停下来查 | T2-2(范围从四种缩为一种) |
server services/credentials | 删除四种可绑定类型前查工具绑定 | T2-4 |
server 新增 services/tool-credentials/ | 可绑定类型清单、四种类型的注入集解析、OAuth2 令牌缓存、测试 | T2-3 |
| server 新接口 | 服务签名的 POST /api/v1/internal/tool-credentials/resolve;OAuth2 测试 POST /api/v1/tool-credentials/test | T2-3、T2-7 |
ui views/credentials/ | OAuth2「测试」按钮;密钥框占位串(CredentialInputHandler.jsx);删除被拒时的工具列表对话框 | T2-7 |
ui ToolUpsert/AuthConfig.jsx | 放开「关联固定凭证」、下拉与三种状态、新建凭证;请求头敏感值提示 | T2-7 |
| agent-base | 工具绑定查询接口;注入与打码;SSO 令牌挪位 | T2-4、T2-5、T2-6 |
| aimp-meta | 注入集契约、e2e;同步 tool-credentials.md 第 4、8 节与交接 T2-2、T2-7 的文字 | T2-8 |
回滚:OAuth2 凭证与其他凭证同表。回退代码后,已建的 OAuth2 凭证在列表里还在,类型定义没了就打不开编辑;删掉这些行即可,不影响其他凭证。占位串的改动只在前端,回退即恢复原行为。
9. 未决问题
| # | 问题 | 推荐 | 不定会卡住 |
|---|---|---|---|
| 1 | 删除时 agent-base 不可用:拒绝删除还是放行 | 拒绝(图 6 右)。放行可能删掉正在用的凭证,工具调用随即失败 | T2-4 |
| 2 | 绑定时要不要校验。agent-base 保存工具时读不到凭证表;不校验时,工具能存上别的团队的凭证 ID 或不可绑定的类型,到调用时才报错 | 校验:agent-base 保存「关联固定凭证」的工具时,调平台服务签名接口确认「凭证属于工具所属团队且是可绑定类型」;平台不可用则保存失败。任务卡里没有这项,是新增工作 | T2-5 的保存逻辑 |
| 3 | 工作流 HTTP 节点要不要也支持 OAuth2 类型。凭证公用,用户可能会在节点里找它 | 本次不做:要改 HTTP 节点的凭证清单与运行逻辑(换令牌、缓存),属于工作流的改动 | 不卡第二批。不做时,节点下拉里看不到 OAuth2 凭证 |
| 4 | 方案 B 之后,可选的密钥字段(如 AWS Session Token)没法清空(3.2) | 接受。要去掉可选密钥的场景少;真要去掉,新建一条不填它的凭证再改选。另一种做法是可选字段留空离开不恢复占位串,代价是误点一下就清掉密钥 | T2-7 的密钥框改动 |
10. 实施记录(2026-10-02)
提交与验证见 docs/tool-auth-handoff.md 文首第二批状态表。与示意图不同的地方:
- 图 4「测试」失败时显示平台给的完整文案,带凭证名,例如「凭证「工单系统 · 开放接口」获取令牌失败(令牌地址返回 HTTP 401)」;成功时耗时不到 1 秒按毫秒显示。
- 图 8 的敏感值提示分两种文案:值是
{{$vars.xxx}}时如图;值是字面量时为「「X」的值像是密钥,写在工具配置里是明文;建议改用认证方式「关联固定凭证」。」。 - 图 7「本团队没有可绑定的凭证」时,下拉的占位文字是这句,下拉下方另有一个「新建凭证」链接。
- 认证方式选「关联固定凭证」时,单选下方说明写「发请求前由平台把凭证写进请求,前置 Hook、后置 Hook 与模型都看不到它的值」。
- 页面上的
data-testid:tool-credential-select(凭证下拉)、tool-sensitive-header-hint(敏感值提示)、credential-test-result(测试结果)、credential-in-use-tools(删除被拒时的工具表)。 e2etests/e2e/tool-credential-binding.spec.ts按它们与可见文案断言。