Partner Portal Monitoring Agent
本页说明 Partner Portal Monitoring Agent 如何在负责人交互式委托下登录 partner portal,用 Track 对政策、价格表、返点和公告页面建立长期监控,命中变化时带证据通知负责人。读完本页,你能理解登录态监控为什么必须走交互式委托、Profiles 如何让后续巡检复用登录态,以及政策基线为什么进监控存储而不是 Memory。
适用场景
渠道、品牌或市场团队需要监控 partner portal 中的产品标题、图片、价格、库存、促销和描述是否符合要求,同时关注登录后才可见的政策文档、价格表、返点规则和公告。这类页面没有公开 API,人工逐个登录巡检既慢又容易漏掉更新。
典型触发时机:
- partner portal 发布新的返点规则或价格表,需要在生效前通知渠道负责人。
- 促销窗口开启前,需要核对多个 portal 中的产品展示是否符合品牌规则。
- 渠道协议续签前,需要确认 portal 内政策文档相对上一周期有哪些变化。
工程挑战
- 登录态维护:portal 内容在登录墙后面,会话过期、MFA 和风控页是常态。无人值守监控的成败取决于登录态能否安全复用、失效时能否升级给人而不是静默中断。
- 变化定级:portal 每天都有例行更新,真正需要上报的是"返点规则改了""政策生效日期提前了"这类实质变化。没有带版本的政策基线,定级只能靠人重读全文。
- 多 portal 异构:每家 portal 的页面结构、术语和更新方式都不同,基线口径难以统一;一处结构改版就可能让整条监控链路输出噪音。
模块组合
| 模块 | 角色 | 说明 |
|---|---|---|
| GenAuth | 核心 | portal 登录态属于高风险委托:交互式授权、短时凭证、可撤销、越权留痕,全部由 GenAuth 承担。 |
| Web Agent | 核心 | Profiles 保存并复用已授权的登录态;Track 维护长期 monitor,按 schedule 取数比对并回调通知。 |
| GUMem | 可选 | 仅保存负责人确认的长期风险偏好(例如"返点类变化一律升级")。政策与价格基线是业务状态,进监控基线存储按版本管理,不进 Memory。 |
权限与委托边界
Agent 本身不持有任何固有权限。每次监控任务的实际权限是三个集合的交集:用户真实权限 ∩ 显式委托范围 ∩ 企业批准边界。落到这个场景:
- 委托范围只覆盖"读取指定 partner portal 的政策、价格、返点、公告和商品展示页面",不包含下单、改价、修改商品信息或联系 partner。
- portal 登录属于高风险操作,必须走
mode: 'interactive':负责人在 Qoni Console 确认授权,凭证在服务端回调中兑换,不暴露给浏览器。 - 委托凭证短时效;长期监控依靠按计划重新签发凭证,而不是一张长期有效的凭证。
- 越权尝试(例如访问委托范围外的订单管理页面)会被拒绝并留痕——审计链覆盖全部尝试,不只是成功行为。
注意:SDK 示例申请的是产品级 scope(如 webagent.do_anything:read)。portal 域名、页面范围和动作白名单这类细粒度边界由 GenAuth 的 Agent Profile 或策略层配置强制执行,不由任务 prompt 承担;本页示例未展示该配置。完整语义见 Delegate Token 与缩权。
工作流程
负责人选择 partner、portal、页面范围和通知渠道。
应用发起交互式委托;负责人在 Qoni Console 确认授权,服务端回调兑换凭证。
应用创建 Track monitor;首轮运行打开 portal,负责人在受控会话中完成登录,登录态由 Profiles 保存供后续 tick 复用。
检查点:登录墙、MFA 或风控页出现时升级给人处理,不静默绕过。
首轮取数建立政策、价格表、返点和公告页面的基线;基线连同规则版本写入监控基线存储。
之后每次按 schedule 运行,Track 抓取当前页面并与基线比对;变没变由规则判定,不由模型措辞决定。
命中变化时,Track 回调你的应用:变化字段、截图证据和来源 URL 构成变化记录。
应用按政策基线为变化定级(可选:结合负责人确认过的风险偏好),推送异常、证据、建议动作和 audit id 给负责人。
检查点:每条异常都应能回溯到具体页面截图和来源 URL;无证据支撑的变化判断不应进入通知。
示例代码
下面的示例使用官方 Qoni SDK(@qoniai/qoni)接入这个场景:交互式委托(完整 callback)→ 从监控基线存储读取带版本的政策基线 → 创建 Track monitor 建立长期监控。
import { Qoni, QoniScopes } from '@qoniai/qoni'
const qoni = new Qoni({
accessKey: process.env.QONI_ACCESS_KEY!,
secretKey: process.env.QONI_SECRET_KEY!,
})
// 1. 入口:发起交互式委托——涉及 portal 登录态,让负责人在 Qoni Console 确认授权
export async function startPortalMonitoring(ownerId: string, portalPages: string[]) {
// 任务参数存应用存储,state 只放任务 ID,回调时按 ID 取回
const taskId = await taskStore.save({ portalPages })
const { data: authorization } = await qoni.delegateToken({
mode: 'interactive',
agent: 'partner-portal-monitoring',
scopes: [QoniScopes.DO_ANYTHING_READ], // 登录巡检所需的产品级只读 scope
redirectUri: 'https://app.example.com/qoni/callback',
state: taskId,
user: { id: ownerId },
expiresIn: 900, // 秒;长期监控按计划重新签发,而不是延长有效期
})
redirectUserTo(authorization.authorizationUrl)
}
// 2. 负责人同意后,在服务端回调中兑换委托令牌,并继续创建监控
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')!,
})
// 按 state 里的任务 ID 取回 startPortalMonitoring 存下的页面清单
const { portalPages } = await taskStore.load(query.get('state')!)
return createPortalMonitor(grant, portalPages) // grant.token 只保存在服务端
}回调中拿到 grant 后调用 createPortalMonitor 建立监控。登录态由 Profiles 在首轮登录后保存,后续 tick 复用,不需要每轮重新登录。
Draft interface
统一 SDK 的 Track 接口签名尚未定稿,下面的示例只表达集成意图;Track 的产品语义见 Track。
// Track 所需 scope 以正式签名为准(Draft interface);此处沿用产品级只读 scope 示意
export async function createPortalMonitor(
grant: { token: string; auditId: string; grantedScopes: string[] },
portalPages: string[],
) {
// 3. 创建前:从监控基线存储读取当前版本的政策基线(不是 Memory)
const baseline = await loadPortalPolicyBaseline() // 例如 { version: '2026-Q3', watchedPages: [...], escalation: ... }
// 4. 创建长期 monitor:首轮登录建立基线,之后按 schedule 反复比对
// (登录态复用字段以 Track 正式签名为准,此处不展示)
const { data: monitor } = await qoni.track.create({
token: grant.token,
intent: `
Watch these partner portal pages for policy, price list, rebate and
announcement changes: ${portalPages.join(', ')}.
Report only substantive changes with the changed fields, a screenshot
and the source URL. Read only: never place orders, change prices,
edit listings or contact partners.
Policy baseline (version ${baseline.version}):
${JSON.stringify(baseline)}
`,
schedule: { kind: 'interval', intervalSeconds: 3600 },
notify: { kind: 'callback_url', url: 'https://app.example.com/hooks/portal-track' },
})
await saveMonitorRef(monitor.id, { baselineVersion: baseline.version })
// 促销冻结期或 portal 维护期间暂停调度,结束后恢复
await qoni.track.pause(monitor.id, { token: grant.token })
await qoni.track.resume(monitor.id, { token: grant.token })
}命中变化时 Track 回调你的应用:解析变化记录,丢弃没有截图或来源 URL 的条目,把新基线连同版本号写入监控基线存储,再按定级规则通知负责人。若团队使用 GUMem 保存负责人确认过的风险偏好,由你的应用在定级时读取注入;偏好写入必须先经负责人确认。
数据与记忆边界
这个场景涉及四类数据,只有最后一类可选地属于 GUMem:
- 版本化规则:政策基线、监控页面清单、定级与升级规则——放在监控基线存储里按版本管理,每条通知引用基线版本号。
- 业务状态:页面快照、变化记录、截图证据——由 Track 的 run 记录和你的监控存储承载,可回放。
- 审计记录:交互式授权、每次取数与越权拒绝构成的行为链——由 GenAuth 维护。
- 用户 Memory(可选):负责人确认的长期风险偏好(例如"返点类变化一律升级")——这才是 GUMem 的位置;政策与价格基线不进 Memory。
失败处理
| 情况 | 推荐处理 |
|---|---|
| 登录态失效 | monitor 发出需要人介入的信号(intervene);负责人重新登录后继续,这是无人值守监控闭环的关键。 |
| portal 页面结构改版导致比对失败 | 按失败处理并回放该次 run,人工确认后重建基线,不输出无证据的变化结论。 |
| 委托范围外的页面请求 | 直接拒绝并记录,事后可在审计链中查到未遂访问。 |
| 回调条目缺少截图或来源 | 应用侧校验直接丢弃该条目并记录丢弃数量;无证据不通知。 |
生产注意点
Agent 不应下单、改价、修改商品信息或联系 partner;输出应作为 review report,由负责人决定后续动作。监控只读、只通知,不代替人执行任何变更。schedule 间隔应结合 portal 更新频率设置下限,避免对目标站点造成压力;委托撤销后 monitor 的下一次取数会立即失败,这是预期行为而不是故障。
下一步
- 阅读 Track 了解 monitor 的完整生命周期与事件流。
- 阅读 快速开始 跑通 Agent 身份与委托的最短路径。
- 继续查看 供应商监控 Agent 了解公开页监控的相邻场景。