Skip to content

Agents 接入(自助配对与数据 API)

让外部 Agent 通过「owner 确认式自助配对」获得一个有作用域限制的只读数据 API 通道。

Ghome 管理后台为外部 Agent(如自研 Agent、第三方助手)提供一条受控接入通道:Agent 拿到一枚短期配对码,由应用 owner 登录后台确认后,换取一个带 Bearer token作用域(scope)的凭证,之后即可调用 /api/agent/v1/** 的数据 API。整套设计的出发点是不信任互联网、最小权限、可审计

核心概念

概念含义
Agent Client一个已授权的 Agent,持有唯一 Bearer token 和一组 scope,可启用/禁用、可设过期。
配对码(Pairing Code)一次性、30 分钟有效的 8 位短码,是人工配对的中介凭证。
自助配对(Self-Pairing)Agent 自行读取公开引导页取得配对码,再交由 owner 确认。
Owner 确认配对必须由登录态管理员在后台完成,不是免鉴权自助兑换。
Scope端点级权限,如 content:publishedanalytics:readops:contacts

数据模型

四张表(Prisma / PostgreSQL):

  • agent_clients —— Agent 凭证。关键字段:tokenPrefix(可读前缀)+ tokenHashsha256(token),原始 token 永不入库)、scopes[]disabledexpiresAtlastUsedAtoriginadmin 直建 / self-paired 配对)、createdByAdminId
  • agent_access_log —— 访问审计。endpointstatusok / denied)、ts
  • agent_pairing_codes —— 配对码。仅存 codeHash = sha256(码) + 与码无关的随机工单号 codePrefixusedAt 标记焚码,usedByAgentClientId 回填兑换出的 client。
  • agent_pairing_config —— 单行开关表(id = 'singleton'),enabled 控制公开配对通道,出厂默认 false

为什么只存哈希

原始 token 与原始配对码都不落库,只保存 sha256 哈希。库被读到也无法反推出可用凭证;原始值仅在创建那一刻一次性展示给 owner。

自助配对流程

text
① 管理员在后台开启「公开配对通道」        → agent_pairing_config.enabled = true(写审计)
② Agent 读取公开引导页 GET /agent/pair.md → 通道开则铸一枚 8 位短码 + 步骤指引(免鉴权)
③ Agent 把短码交给 owner
④ Owner 登录后台 → 「Agent 接入」引导卡第③步输入短码(+ 可选名称)
⑤ 后台校验:通道开启? 码存在? 未使用? 未过期?
   → 事务内原子焚码(updateMany where usedAt=null)防并发双花
   → 生成 token、建 AgentClient(scope 固定 content:published、origin=self-paired)
   → 写审计 agentClient.pair
⑥ 跳转编辑页一次性展示 Bearer token(关闭后库内仅哈希,不再可见)
⑦ Owner 把 token 配进 Agent,之后携 Authorization: Bearer <token> 调数据 API

配对码状态机:

text
已铸码(expiresAt = now + 30min)
   ├─ 已用(usedAt 置位 + 回填 client)  → 审计
   ├─ 已过期(expiresAt < now)          → 拒绝
   └─ 未用且未过期                        → 可确认

安全默认

自助配对出的 client 固定只有 content:published 权限。更高权限(analytics、ops)只能由管理员事后在编辑页手工勾选提权,并留审计——避免公开通道直接放出敏感数据访问权。

数据 API

认证:请求头 Authorization: Bearer <token>。后台用 sha256(token) 反查 agent_clients,校验 disabledexpiresAt 后放行。

个性化 Skill.mdGET /api/agent/v1/skill.md只列出该 client scope 内可用的端点,作为 Agent 的自描述接入说明。

端点分组(共 20+ 条,均在 /api/agent/v1/ 前缀下):

分组所需 scope代表端点
内容(读)content:published/apps/videos/guides/topics/albums/rankings/categories/tags(列表分页,详情按 :slug
内容(写)content:writePOST /appsPOST /videos … 创建并发布
分析analytics:read/analytics/clicks/daily/analytics/redirects/top
运营ops:*/redirects/audit-log/contact-submissions/admins

状态门控:无 content:all 时强制 status=published?status=draft 被静默忽略(防越权探测);有 content:all 时可查 draft/archived/all。

响应约定:列表统一信封 { data, page, pageSize, total }pageSize ≤ 100),详情直接返回对象,错误返回 { error: "..." }

错误码401 unauthorized / token_revoked / token_expired403 forbidden(scope 不足)、404 not_found400 invalid_request

后台管理界面

  • 列表页 /agent-clients —— 顶部三态引导卡(通道未开 / 已开无 Agent / 已开有 Agent),含可复制的接入话术、内联输码表单、pairError 中文错误透出;下方是 Agent 列表(名称 / 来源 / token 前缀 / scopes / 状态 / 最近使用 / 过期)。
  • 编辑页 /agent-clients/[id]/edit —— 一次性 token 展示条、scope 多选、启用/禁用、过期、备注,以及轮换 token吊销更新操作,全部走审计。
  • 配对码日志 /agent-clients/pairing-codes —— 只读表格,不显示原始码,仅展示创建/过期时间、状态、确认管理员、兑换出的 client。

安全设计要点

威胁防护
原始 token 泄露仅哈希入库,原始值一次性展示
配对码被猜需登录态管理员确认 + 8 位短码 + 30min TTL + 原子焚码
权限越界manifest 驱动的 scope 校验 + content:all 状态门控
敏感数据泄露contact-submissionsadmins 等仅在显式 ops scope 下可达
并发双花事务内 updateMany(where usedAt=null) 原子检测
吊销/过期滞后每次请求即时检查 disabledexpiresAt,无缓存

三层结构性兜底:公开通道默认关(管理员显式开启)→ 配对码一次性 + 短 TTL + 原子焚码配对出的 client 固定最小 scope + 全链路审计origin / createdByAdminId / agentClient.pair)。

关键实现位置

源项目:ghome(pnpm monorepo)。以下为仓库相对路径。

  • 数据模型:packages/db/prisma/schema.prisma;迁移 20260518000000_agent_clients20260518100000_agent_self_pairing
  • Agent API 库:apps/admin/lib/agent-api/token.ts 令牌、pairing.ts 短码、scopes.ts 作用域、manifest.ts 端点表、auth.ts 鉴权、queries.ts 查询、skill-md.ts 自描述文档)
  • 配对 DB 层:apps/admin/lib/agent-pairing-db.tsapps/admin/lib/agent-clients-db.ts
  • API 路由:apps/admin/app/api/agent/v1/[[...slug]]/route.ts、公开引导 apps/admin/app/agent/pair.md/route.ts
  • 后台 UI:apps/admin/app/(admin)/agent-clients/page.tsx[id]/edit/page.tsxpairing-codes/page.tsxactions.ts
  • 设计文档:docs/superpowers/specs/2026-05-18-admin-agent-data-api-design.md2026-05-18-agent-self-pairing-design.md2026-06-10-agent-onboarding-card-redesign-design.md