auth + systemUser + sessionInit:身份与交互式表单 本节摘要:本节深入八步管道的前三步——身份确定的「三连」。auth 用密钥换出 userid,systemUser 解析系统用户身份,sessionInit 用交互式表单确定 team/agent/task 这个关键三元组。这三步是召回能够精准的前提——没有确定的身份与场景,召回就无的放矢。本节讲清这三步各自做什么、sessionInit 为什么用交互式表单、以及确定的三元组如何驱动后续装配过滤。
本节摘要:本节深入八步管道的前三步——身份确定的「三连」。auth 用密钥换出 user_id,systemUser 解析系统用户身份,sessionInit 用交互式表单确定 team/agent/task 这个关键三元组。这三步是召回能够精准的前提——没有确定的身份与场景,召回就无的放矢。本节讲清这三步各自做什么、sessionInit 为什么用交互式表单、以及确定的三元组如何驱动后续装配过滤。
八步管道的第 1 步是鉴权——用 Agent 带来的密钥,换出系统内部的 user_id:
auth 步骤 Agent 请求带: x-tdai-user-key(代理层签发的密钥) ↓ 代理层调用: /v3/meta/auth/verify ↓ 返回: user_id(系统内部身份) ↓ 后续步骤都用这个 user_id 做权限判断
| 输入 | 处理 | 输出 |
|---|---|---|
| x-tdai-user-key | 调 auth/verify 验证 | user_id |
关键概念:注意密钥的层次——Agent 带的是「代理层签发的密钥」(x-tdai-user-key),不是真正的 LLM 密钥。代理层用这个密钥换出 user_id,后续再用 user_id 判断权限;而真正的 LLM 密钥是代理层自己在内部用的(第 1 章讲过两组凭证)。这种「密钥分层」让 Agent 持有的是「可撤销的代理密钥」,而非「不可撤销的 LLM 密钥」,安全性更好。
拿到 user_id 后,systemUser 步骤解析这个用户的系统身份——属于哪些团队、有什么角色:
systemUser 步骤 user_id ↓ 解析: ├─ 所属团队列表 ├─ 角色(System Admin? Team Admin? Member?) └─ 权限范围 ↓ 这些信息用于后续的装配过滤(哪些资产可见)
这一步的产出是「用户的全景身份」,它决定了后续召回时第 3 章装配过滤的「Team/User」维度——这个用户在哪些团队、能看到哪些资产,都由 systemUser 解析出来。
| 步骤 | 产出 | 用途 |
|---|---|---|
| auth | user_id | 标识用户 |
| systemUser | 团队/角色/权限 | 装配过滤的 Team/User 维度 |
前三步里最特别的是 sessionInit——它不是「直接读取」,而是用「交互式表单」与用户确定 team/agent/task 三元组:
sessionInit 的交互式表单 首次接入时,代理层返回一个表单(而非直接转发): 「请选择: 团队(team): [Tiny but Serious Inc. ▼] Agent: [Builder ▼] 任务(task): [feature-x 开发 ▼](可选)」 ↓ 用户选择后,三元组确定 ↓ 后续请求自动带上这个三元组(不用每次选)
为什么要用交互式表单?因为这个三元组无法从密钥自动推断——同一个用户可能属于多个团队、用多个 Agent,代理层不知道「这次请求是哪个团队、哪个 Agent 的」:
| 三元组 | 为什么不能自动推断 |
|---|---|
| team | 用户可能属于多个团队 |
| agent | 同一用户可能用多个 Agent |
| task | 任务是动态的,每次可能不同 |
关键概念:sessionInit 解决的是「这次请求的上下文是什么」。没有它,代理层知道「谁(user_id)」但不知道「在哪个团队、用哪个 Agent、做什么任务」——而召回的装配过滤依赖这三个维度。交互式表单让用户明确指定,避免召回「张冠李戴」。
sessionInit 确定的三元组,直接驱动第 3 章的装配过滤:
三元组 → 装配过滤(接第3章) team_id → 只看该团队的资产 agent_id → 只看绑定给该 Agent 的资产(Loadout) user_id → 只看该用户可见性的资产 task_id → (可选)进一步缩小场景 → 四维过滤后,召回候选集大幅缩小 → 召回精准且不越权
这就把第 3 章的装配机制与代理层串起来了——sessionInit 产出的三元组,是装配过滤的输入。没有 sessionInit,装配过滤无从做起;有了它,召回才能「先过滤后检索」。
前三步串起来,构成「身份确定」的完整链路:
身份确定链路 Agent请求 + 密钥 ↓ auth user_id(知道是谁) ↓ systemUser 团队/角色/权限(知道能看什么) ↓ sessionInit team/agent/task(知道这次在什么场景) ↓ 身份完全确定 → 进入 injection(下一步)
每一步都可能失败,失败处理遵循「前置失败不继续」原则:
| 失败 | 处理 |
|---|---|
| auth 失败(密钥无效) | 直接拒绝,不进入后续 |
| systemUser 失败(无身份) | 拒绝或降级为无权限 |
| sessionInit 未完成 | 触发表单,等用户选择 |
⚠️ 注意:sessionInit 的「首次交互」是初学者常困惑的点——第一次接入时代理层不立刻转发,而是返回表单让你选团队/Agent。这不是故障,是正常的身份确定流程。选过一次后,后续请求自动带三元组,不再弹表单。第 1 章接入时若遇到「响应是个选择表单」,就是这个机制在工作。
身份与场景确定了,下一节看管道最核心的一步——injection,记忆如何被注入请求,以及 inject 与 toolize 的双策略权衡。