品牌一致性 Agent
本页说明品牌一致性 Agent 如何在只读委托下读取官网、帮助中心、社媒主页、marketplace listing 或 CMS 草稿,对照版本化的术语表和 claims 规则跨渠道检查一致性,并输出带来源的差异清单。读完本页,你能理解这个场景需要哪些模块、权限边界如何收窄,以及术语规则和巡检基线各自应该放在哪里。
适用场景
Marketing、内容和产品团队需要在发布前或周期性检查多个页面是否符合品牌规范。品牌表达散落在官网、社媒、商店页和帮助中心等多个渠道,各渠道由不同团队维护,术语漂移和过期 claims 很难靠人工发现;渠道改版后差异还会持续累积。
典型触发时机:
- 品牌术语表或 claims 口径更新后,需要排查全部渠道的存量表达。
- 周期性品牌巡检,需要对官网、社媒和商店页做一致性抽查。
- 某个渠道页面改版后,需要确认改动没有偏离品牌规范。
工程挑战
- 渠道分散且各自演进:官网、社媒、商店页、帮助中心由不同团队维护,术语漂移是渐进发生的,人工抽查只能看到单页快照,看不到跨渠道差异的全貌。
- 差异需要证据而不是印象:"这个页面语气不对"驱动不了改写;每条差异必须落到具体页面、具体表述和触发的具体规则,否则内容 owner 无从下手。
- 一致性基准本身在变:术语表和 claims 口径持续更新,巡检结论必须绑定规则版本、基线必须按版本归档,否则新旧两期巡检结果无法对比,也说不清一条差异是新漂移还是旧问题。
模块组合
| 模块 | 角色 | 说明 |
|---|---|---|
| GenAuth | 核心 | CMS、渠道后台等授权页面的只读委托、撤销与审计链;周期性巡检每次触发新签发凭证。 |
| Web Agent | 核心 | 受控会话逐页抽取文本、CTA 和视觉上下文并保留来源;关键页面可用 Track 持续盯守变化——变化判定由确定性规则决定,不由模型措辞决定。 |
| GUMem | 不使用 | 术语表和 claims 规则是版本化配置,放在你的规则库(policy store)按版本注入;巡检基线和差异结论是业务状态,归档到你的结构化存储。这个场景没有需要进入 Memory 的用户长期偏好。 |
权限与委托边界
Agent 本身不持有任何固有权限。每次巡检任务的实际权限是三个集合的交集:用户真实权限 ∩ 本次显式委托范围 ∩ 企业批准边界。落到这个场景:
- 委托范围只覆盖"读取指定站点、CMS collection 和渠道页面",不包含编辑内容、发布页面或修改 listing。
- 委托凭证短时效,单次巡检任务建议分钟级有效期;周期性盯守由每次触发时新签发的凭证执行。
- 用户或管理员可随时撤销授权;撤销后新的页面读取请求立即失败。
- 越权尝试(例如读取委托清单外的 workspace)会被拒绝并留痕——审计链覆盖全部尝试,不只是成功行为。
注意:SDK 示例申请的是产品级 scope(如 webagent.do_anything:read)。站点清单、CMS collection 范围和动作白名单这类细粒度边界由 GenAuth 的 Agent Profile 或策略层配置强制执行,不由任务 prompt 承担;本页示例未展示该配置。完整语义见 Delegate Token 与缩权。
工作流程
用户选择要检查的站点、渠道或页面列表,以及巡检维度(术语、语气、claims),并在 Qoni Console 确认本次交互式授权。
GenAuth 为本次任务签发最小权限的只读委托凭证。
应用从规则库读取当前版本的术语表、品牌 voice 和 claims 规则,注入任务描述。
Web Agent 逐页抽取各渠道页面的文本、CTA 和视觉上下文,保留来源 URL 与截图。
检查点:渠道后台或 CMS 预览遇到登录墙、验证码或风控页时,Web Agent 应升级给人处理,而不是静默绕过。
Agent 对照规则比对各渠道表达,标注术语漂移、语气偏离和过期 claims,每条附页面来源和触发的规则编号。
应用侧校验输出契约:缺少页面来源或规则编号的差异直接丢弃;本期巡检基线按规则版本归档到你的结构化存储。
对需要持续盯守的关键页面,配置 Track 按确定性规则监测后续变化。
Agent 输出差异清单、建议改写和来源列表,附规则版本号与 audit id。
检查点:差异清单中每条不一致项都应能回溯到具体页面来源;无来源支撑的结论不应进入交付物。
示例代码
下面的示例使用官方 Qoni SDK(@qoniai/qoni)把这个场景接到你的服务端:交互式委托(含完整回调)→ 从规则库读取术语与 claims 规则 → 一次 doAnything.run() 启动巡检并用 events() 事件流消费执行过程 → 解析并校验差异清单。
import { Qoni, QoniScopes } from '@qoniai/qoni'
const qoni = new Qoni({
accessKey: process.env.QONI_ACCESS_KEY!,
secretKey: process.env.QONI_SECRET_KEY!,
})
// 1. 交互式委托:涉及渠道后台和 CMS 登录,让用户在 Qoni Console 确认授权
export async function startBrandPatrol(userId: string, taskId: string) {
const { data: authorization } = await qoni.delegateToken({
mode: 'interactive',
agent: 'brand-consistency',
scopes: [QoniScopes.DO_ANYTHING_READ, QoniScopes.DO_ANYTHING_MANAGE],
redirectUri: 'https://app.example.com/qoni/callback',
state: taskId,
user: { id: userId },
expiresIn: 900, // 单次巡检任务给分钟级有效期
})
redirectUserTo(authorization.authorizationUrl)
}
// GET /qoni/callback —— 用户同意后在服务端兑换 grant,继续执行任务
export async function handleQoniCallback(request: Request) {
const query = new URL(request.url).searchParams
const { data: grant } = await qoni.completeDelegateToken({
grantId: query.get('grantId')!,
code: query.get('code')!,
state: query.get('state')!,
})
return runPatrol(grant, await loadPatrolTask(query.get('state')!))
}
async function runPatrol(
grant: { token: string; auditId: string; grantedScopes: string[] },
task: { channelPages: string[] },
) {
// 2. 任务前:从你的规则库读取当前版本的术语表与 claims 规则(不是 Memory)
const policy = await loadBrandConsistencyPolicy() // 例如 { version: '2026-08', glossary: [...], claimRules: [...] }
// 3. 启动跨渠道巡检:逐页比对,只输出差异清单
const run = await qoni.doAnything.run({
token: grant.token,
prompt: `
Patrol the following channel pages: ${task.channelPages.join(', ')}.
Extract each page's text, CTAs and visual context, compare them against
the brand policy below, and return diffs as a JSON array of
{ page, diff, quote, ruleId, sourceUrl } objects.
Report only — never edit, publish or change listings.
Brand policy (version ${policy.version}):
${JSON.stringify(policy)}
`,
capture: { screenshots: true },
})
// 4. 用事件流消费执行过程:进度与截图流式转发,登录墙升级给人
let output = ''
for await (const event of run.events()) {
if (event.type === 'progress') appendTrace(event.data)
if (event.type === 'screenshot') broadcastScreenshot(event.image)
if (event.type === 'interaction') notifyUserActionRequired(event.data) // 后台登录墙 / 验证码交给人处理
if (event.type === 'done') output = event.data.output
}
// 5. 应用侧校验输出契约:缺来源或规则编号的差异直接丢弃
const diffs = parseDiffs(output).filter((d) => d.sourceUrl && d.ruleId)
// 巡检基线按规则版本归档到你的结构化存储(不是 Memory)
await archivePatrolBaseline(diffs, policy.version)
return {
diffs,
policyVersion: policy.version,
audit: { auditId: grant.auditId, permissionBoundary: grant.grantedScopes },
}
}输出结构由任务描述约定:这里约定返回 { page, diff, quote, ruleId, sourceUrl } 数组,应用侧 parseDiffs 负责解析与校验,任何缺少 sourceUrl 或 ruleId 的条目被直接丢弃。SDK 顶层只返回通用的 RunResult(runId、status、output、artifacts 等);events() 的事件类型常量见 QoniEventTypes。
数据与记忆边界
这个场景涉及四类数据,都不需要进入 GUMem:
- 版本化规则:术语表、品牌 voice、claims 规则——放在规则库(policy store)里按版本管理,每条差异引用规则版本号。
- 业务状态:巡检基线、差异清单、页面截图——按规则版本归档到你的结构化存储,供跨期对比与追溯。
- 审计记录:
grantId与auditId构成的委托与行为链——由 GenAuth 维护。 - 用户 Memory(可选):这个场景默认不召回也不写回;如果未来出现需要跨任务保留的用户长期偏好,再评估是否引入 GUMem。
失败处理
| 情况 | 推荐处理 |
|---|---|
| 渠道后台登录态失效 | 任务挂起,通知用户重新登录,从断点继续。 |
| 页面结构变化导致抽取失败 | 按失败处理并回放会话记录,不输出无证据的差异项。 |
| 委托范围外的 workspace 请求 | 直接拒绝并记录,事后可在审计链中查到未遂访问。 |
| 输出差异缺少页面来源或规则编号 | 应用侧校验直接丢弃该条目,并在差异清单中标注丢弃数量。 |
生产注意点
不要自动覆盖发布内容。批量修改前需要内容 owner 确认。Agent 只输出差异清单与建议,不直接修改任何渠道的线上内容;差异清单应带规则版本号,术语表更新后旧基线不追溯改判。对外部渠道页面的巡检频率应设置上限,避免对目标站点造成压力。
下一步
- 阅读 快速开始 跑通 Agent 身份与委托的最短路径。
- 阅读 授权与浏览器沙盒 了解受控会话的安全边界。
- 继续查看 本地化 Messaging Agent 了解相邻场景。