Review mining agent
This page explains how a review mining agent reads ecommerce, App Store, G2, or review dashboard sources under a read-only grant, extracts customer feedback from authorized and public reviews, clusters it into themes, and produces positioning insights. After reading it, you will understand which modules this scenario needs, how the permission boundary narrows, and why review verbatims and cluster results belong in your analytics store rather than Memory.
Use case
Marketing and product teams need to understand purchase motivations, objections, feature feedback, and competitor comparisons from customer reviews. Reviews are scattered across platforms, high-volume, and always growing — reading them manually cannot produce reviewable theme clusters, and "users are all saying" conclusions without sources cannot support positioning decisions.
Typical triggers:
- After a release or product launch, review themes across platforms must be summarized within a week.
- Before a positioning retrospective, purchase motivations and objections need evidence in users' own words.
- A competitor's rating shifts, and feature feedback must be compared across both products' reviews.
Engineering challenges
- High volume and high noise: thousands of cross-platform reviews mix fake reviews, off-topic complaints, and duplicates, so clustering easily produces conclusions that "look reasonable" without a single supporting verbatim.
- Insights must be traceable: a conclusion like "users all say it's too expensive" cannot be re-verified without review source URLs, and cannot defend itself when the positioning decision is challenged — an unsourced insight is no insight.
- The theme structure must stay comparable across cycles: change the classification rules and two cycles' theme distributions can no longer be compared; rules must be versioned, and cluster results must be archived together with the rule version for trend judgments to mean anything.
Module composition
| Module | Role | Notes |
|---|---|---|
| GenAuth | Core | Read-only delegation, revocation, and the audit chain for authorized review dashboards; the dashboard account's reply, report, and merchant-info powers stay outside the delegation. |
| Web Agent | Core | Controlled sessions sign in to review dashboards or visit public review pages, extracting ratings, verbatim excerpts, and source links page by page; public review pages can be located with WebSearch. |
| GUMem | Not used | Review verbatims, cluster versions, and trend data are analytics assets — archive them to your analytics store. Classification rules and competitor mappings are versioned policy — keep them in your policy store and inject them per version. Neither is Memory. |
Permission and delegation boundaries
The Agent holds no inherent permissions. The effective authority for each 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 authorized review dashboards and public review pages for the selected products" — no replying to reviews, reporting content, or editing merchant info.
- Delegation credentials are short-lived; minute-level validity is recommended for a single mining run.
- The user or an administrator can revoke the grant at any time; new review-extraction requests fail immediately after revocation.
- Out-of-scope attempts (for example, another product's review dashboard 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 — platform lists, product ranges, 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
The user selects a product, platform, and time range and confirms the interactive authorization in Qoni Console.
GenAuth issues a least-privilege, read-only delegation credential for this task.
Your app loads the current version of the classification rules, theme taxonomy, and competitor mappings from the policy store and injects them into the task.
Web Agent signs in to review dashboards or opens public review pages and extracts ratings, verbatim excerpts, and source links page by page.
Checkpoint: When a review platform shows a login wall, CAPTCHA, or risk-control page, the Web Agent should escalate to a human instead of silently bypassing it.
The Agent clusters reviews into themes — purchase motivations, objections, feature feedback, and competitor comparisons — each insight with a representative verbatim and source link.
Your app validates the output contract — insights missing a review source URL are dropped — and archives cluster results with the rule version to your analytics store.
The Agent returns theme clusters, representative excerpts, messaging suggestions, and a source list, with the taxonomy version and an audit id.
Checkpoint: Every sentiment or theme conclusion should trace back to concrete review source links; conclusions without excerpts 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 classification rules from your policy store → one doAnything.run() for extraction and clustering → parse and validate the insights.
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: review dashboard sign-in is involved —
// the user confirms in Qoni Console
export async function startReviewMining(userId: string, taskId: string) {
const { data: authorization } = await qoni.delegateToken({
mode: 'interactive',
agent: 'review-mining',
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 mining run
})
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 runMiningTask(grant, await loadMiningTask(query.get('state')!))
}
async function runMiningTask(
grant: { token: string; auditId: string; grantedScopes: string[] },
task: { product: string; platforms: string[]; timeRange: string },
) {
// 2. Before the run: load the current classification rules and taxonomy
// from YOUR policy store (versioned policy, not Memory)
const policy = await loadReviewTaxonomyPolicy() // e.g. { version: '2026-08', themes: [...], competitorMap: ... }
// 3. One call runs the mining: sign in, extract page by page, cluster themes
const run = await qoni.doAnything.run({
token: grant.token,
prompt: `
Mine customer reviews for ${task.product} on ${task.platforms.join(', ')}
within ${task.timeRange}. Extract ratings, verbatim excerpts and source
links, then cluster them into the themes defined in the taxonomy below —
motivations, objections, feature feedback, competitor comparisons.
Return insights as a JSON array of
{ theme, insight, quote, reviewUrl } objects.
Never reply, report or edit merchant info; exclude reviewer personal data.
Review taxonomy (version ${policy.version}):
${JSON.stringify(policy)}
`,
capture: { screenshots: true },
})
const result = await run.wait({
// Login walls / CAPTCHAs / risk-control pages: escalate to a human
onInteraction: (interaction) => notifyUserActionRequired(interaction),
})
// 4. Validate the output contract on the app side: insights missing
// a review source URL are dropped
const insights = parseInsights(result.output).filter((i) => i.reviewUrl)
// Archive cluster results with the rule version to YOUR analytics store
// (not Memory)
await archiveInsights(insights, policy.version)
return {
insights,
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 { theme, insight, quote, reviewUrl }, parsed and validated by parseInsights on the app side, and any entry missing reviewUrl 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 needs GUMem:
- Versioned rules: classification rules, the theme taxonomy, competitor mappings — managed by version in your policy store, with every cycle's clusters citing the rule version.
- Business state: review verbatims, cluster results, trend data — archived by rule version to your analytics store for cross-cycle comparison and review.
- Audit records: the delegation and behavior chain formed by
grantIdandauditId— maintained by GenAuth. - User Memory (optional): this scenario neither recalls nor writes back by default; review content is the reviewers' public expression and should not accumulate as anyone's Memory.
Failure handling
| Situation | Recommended handling |
|---|---|
| Review dashboard login state expires | Suspend the task, notify the user to sign in again, and resume from the checkpoint. |
| Review page structure changes break extraction | Treat it as a failure and replay the session recording; never emit insights without evidence. |
| Request for a product dashboard outside the delegated scope | Reject and record it; the attempted access remains visible in the audit chain. |
| An insight lacks a review source URL | App-side validation drops the entry and the report notes how many were dropped. |
Production notes
Do not expose private user information. Public review quotes should follow platform rules and use minimal necessary excerpts. The Agent only processes publicly visible or authorized review content; reviewer personal data is used for insight analysis only, never for outreach or profiling, and extraction frequency against public review pages should be capped in line with platform terms of service.
Next steps
- Read the Quickstart to run the shortest path for Agent identity and delegation.
- Read Authorization and browser sandbox for the security boundaries of controlled sessions.
- Continue with the Influencer vetting agent for an adjacent scenario.