Skip to content

Authenticated competitive messaging agent

This page explains how an authenticated competitive messaging agent accesses authorized competitor, channel, or storefront pages under delegated user authority and creates a reviewable messaging brief. After reading it, you will understand which modules this scenario needs, how the permission boundary narrows, and why brand positioning and forbidden claims belong in a policy store rather than Memory.

Use case

Marketing, sales, or channel teams need to inspect member pricing, regional pricing, promotions, inventory, product claims, or partner portal content visible only after sign-in. These pages have no public API, manual checks are slow and incomplete, and handing an employee's credentials to a script grants the full account's authority in one shot — with no way to tell afterwards who did what.

Typical triggers:

  • A competitor changes pricing or launches a product, and the battlecard must be updated within a business day.
  • A channel promotion window opens, and member pricing and inventory must be verified across several storefronts.
  • A new-market evaluation needs claims that are only visible after sign-in.

Engineering challenges

  • The target data sits behind login walls and keeps changing: member pricing, regional promotions, and inventory have no public API, page structures and prices shift with promotion windows, and manual checks cannot keep pace with battlecard updates.
  • Borrowed employee sessions concentrate risk: whatever the account can see, the script can see — customer data and order entry points outside the research scope have no boundary at all, and the extraction shows up in the target site's logs under the employee's identity.
  • Facts need sources and timestamps: competitor pricing changes at any time; a "fact" in the brief without a source URL and capture time cannot be verified a week later, and the battlecard's credibility keeps decaying.

Module composition

ModuleRoleNotes
GenAuthCoreRead-only delegation, revocation, and the audit chain for the specified competitor domains; the delegation acts only for the current user or workspace.
Web AgentCoreThe user completes sign-in inside the controlled browser session (Profiles can reuse login state), then pricing, promotions, inventory, and claims are extracted page by page, keeping a source URL and screenshot per fact.
GUMemNot usedBattlecards and messaging playbooks (for example, comparison frames proven to work) are team knowledge assets, managed by version in your policy store or battlecard store; this scenario has no genuine user-level long-term memory.

Authenticated competitive messaging agent architecture

Permission and delegation boundaries

The Agent holds no inherent permissions. The effective authority for each research task is the intersection of three sets: what the user actually holds ∩ what was explicitly delegated for this task ∩ what the enterprise has approved. Applied to this scenario:

  • The delegated scope covers only "read page content on the specified competitor domains" — no form submission, purchasing, or account settings.
  • Delegation credentials are short-lived; minute-level validity is recommended for a single research task. Expiry is the norm, not an exception.
  • The user or an administrator can revoke the grant at any time; new page extraction requests fail immediately after revocation.
  • Out-of-scope attempts (for example, a customer-privacy page outside the delegation) are rejected and recorded — the audit chain covers all attempts, not just successful actions.

Note: the SDK example requests product-level scopes (such as webagent.do_anything:read). Fine-grained boundaries — domain lists, page types, action whitelists — are enforced by the GenAuth Agent Profile or your policy layer, not by the task prompt; that configuration is not shown on this page. See Delegate token and attenuation for the full semantics.

Workflow

Authenticated competitive messaging agent workflow

  1. The user selects the competitors, channels, or products to research and confirms the interactive authorization in Qoni Console.

  2. GenAuth issues a least-privilege delegation credential for this task.

  3. Your app loads the current version of brand positioning, competitor mappings, and forbidden claims from the policy store and injects them into the task.

  4. Web Agent opens the target pages; on first access the user completes sign-in in the controlled session, and later runs can reuse login state through Profiles.

    Checkpoint: When a login wall, CAPTCHA, or risk-control page appears, the Web Agent should escalate to a human instead of silently bypassing it.

  5. Web Agent extracts authorized pricing, promotions, inventory, and claims page by page, keeping source URLs and screenshots; public context can be cross-checked with WebSearch.

  6. Your app validates the output contract: facts missing a source URL are dropped.

  7. The Agent returns a messaging brief and battlecard draft with a source list, the policy version, and an audit id; verified facts are archived to your battlecard storage.

    Checkpoint: Every competitive fact in the brief should trace back to a concrete page source; conclusions without evidence should not enter the deliverable.

Example code

The example below wires this scenario into your backend with the official Qoni SDK (@qoniai/qoni): interactive delegation (with the full callback) → load brand positioning and forbidden claims from your policy store → one doAnything.run() for the research → parse and validate the brief facts.

ts
import { Qoni, QoniScopes } from '@qoniai/qoni'

const qoni = new Qoni({
  accessKey: process.env.QONI_ACCESS_KEY!,
  secretKey: process.env.QONI_SECRET_KEY!,
})

// 1. Interactive delegation: sign-in is involved, so the user confirms
//    in Qoni Console
export async function startCompetitiveResearch(userId: string, taskId: string) {
  const { data: authorization } = await qoni.delegateToken({
    mode: 'interactive',
    agent: 'competitive-messaging',
    scopes: [QoniScopes.DO_ANYTHING_READ, QoniScopes.DO_ANYTHING_MANAGE],
    redirectUri: 'https://app.example.com/qoni/callback',
    state: taskId,
    user: { id: userId },
    expiresIn: 900, // minute-level validity for a single research task
  })
  redirectUserTo(authorization.authorizationUrl)
}

// GET /qoni/callback — after the user approves, exchange for the grant
// server-side and continue the task
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 runResearchTask(grant, await loadResearchTask(query.get('state')!))
}

async function runResearchTask(
  grant: { token: string; auditId: string; grantedScopes: string[] },
  task: { targets: string[] },
) {
  // 2. Before the run: load the current brand positioning and forbidden
  //    claims from YOUR policy store (versioned policy, not Memory)
  const policy = await loadMessagingPolicy() // e.g. { version: '2026-08', positioning: ..., competitorMap: ..., forbiddenClaims: [...] }

  // 3. One call runs the research: sign in, extract page by page, keep sources
  const run = await qoni.doAnything.run({
    token: grant.token,
    prompt: `
      Research the following competitor storefront pages: ${task.targets.join(', ')}.
      Extract member pricing, promotions, inventory and product claims, and
      return facts as a JSON array of { competitor, fact, quote, sourceUrl }
      objects — keep the source URL for every fact. Do not buy, submit forms,
      or change any account settings.

      Messaging policy (version ${policy.version}):
      ${JSON.stringify(policy)}
    `,
    capture: { screenshots: true },
  })

  const result = await run.wait({
    // Login walls / MFA / risk-control pages: forward to the user
    onInteraction: (interaction) => notifyUserActionRequired(interaction),
  })

  // 4. Validate the output contract on the app side: facts missing
  //    a source URL are dropped
  const facts = parseFacts(result.output).filter((f) => f.sourceUrl)

  return {
    facts, // verified facts are archived to your battlecard storage
    artifacts: result.artifacts,
    policyVersion: policy.version,
    audit: { auditId: grant.auditId, permissionBoundary: grant.grantedScopes },
  }
}

The output structure is a contract set by the task prompt: here it is an array of { competitor, fact, quote, sourceUrl }, parsed and validated by parseFacts on the app side, and any entry missing sourceUrl is dropped. The SDK itself returns the generic RunResult (runId, status, output, artifacts, and so on).

Data and memory boundaries

This scenario touches four kinds of data; none of them belongs in GUMem:

  • Versioned rules: brand positioning, competitor mappings, forbidden claims — managed by version in your policy store, referenced by version in the brief.
  • Business state: messaging briefs, battlecards, verified pricing facts and screenshots — archived to your battlecard storage with source pointers and capture times.
  • Audit records: the delegation and behavior chain formed by grantId and auditId — maintained by GenAuth.
  • User Memory: not applicable in this scenario. Team-confirmed comparison frames and messaging lessons are team-shared playbook / battlecard knowledge that evolves under version management — not user-level long-term memory.

Failure handling

SituationRecommended handling
Login state expiresSuspend the task, notify the user to sign in again, and resume from the checkpoint.
Page structure changes break extractionTreat it as a failure and replay the session recording; never emit conclusions without evidence.
Request outside the delegated scopeReject and record it; the attempted access remains visible in the audit chain.
A fact lacks a source URLApp-side validation drops the entry; it never enters the brief or battlecard.

Production notes

The Agent should not bypass access controls, buy products, submit forms, change account settings, or copy data outside the authorized scope. Accounts and login states used for research must be ones the enterprise is entitled to use — never run competitive research on personal accounts or credentials of unclear origin. Extraction must respect the target site's terms of service, and any crawling beyond what the ToS allows should stop until legal signs off; crawl frequency against research targets should be capped to avoid load on those sites.

Next steps