Case study

Agentic industry research for a national competition regulator

A deep-research system that drafts the industry-background section of merger-review reports — built so that an ungrounded sentence cannot be emitted.

The problem

When a competition authority reviews a merger, its economists and lawyers first need an industry background: how the sector's value chain works, who the players are, how each stage is regulated, and what the candidate relevant markets might be. Assembling that picture from official sources is slow, and the output is a legal artifact — a wrong or unsourced claim isn't a typo, it's a defect the review inherits.

Generic LLM chat tools fail this job in a specific way: they write fluent prose first and attach sources afterwards, if at all. For a regulator, that order is backwards.

What we built

A multi-pass agentic research system. Given a sector, the transacting parties, and the transaction type, it runs three bounded research passes — regulatory framework first (to orient the rest), then the value chain, then candidate relevant markets — and produces a draft report, a verification worklist, and a per-claim evidence audit with archived source documents.

System architecture Flow diagram: sector and parties enter an agentic research loop with three passes (regulatory framework, value chain, candidate markets). The loop records claims into a claim ledger. Python code — not the model — assigns source tiers and confidence grades, archives every cited source, and assembles the report, worklist, and evidence audit from approved claims only. sector + parties agent loop 1 regulatory 2 value chain 3 markets search · fetch record claims → claim ledger python tier + grade + archive outputs report worklist evidence audit archived sources
The claim ledger is the artifact; prose, tables, and figures are derived views of approved claims.

How do you make an agent that can't fabricate?

You don't do it with prompt instructions alone. The system's core design decision is claim-first generation: the agent's only job is to record claims — each with a source URL and a locator — into a structured ledger. Deterministic Python code, not the model, then decides what happens to every claim:

  • Source tiering. Every source is classified into four tiers — transaction parties, third parties to the record, reputable published sources, and everything else. The lowest tier (blogs, forums, unknown sites) is discovery-only: it can point the agent at better sources but is never cited.
  • Two-axis confidence grading. Source authority × extraction risk, recency, and corroboration produce a High / Medium / Low / Unverified label with written reasons — no fake-precision scores. Market-wide economic claims require independent corroboration; syndicated reprints of one wire story are collapsed to a single origin so they can't fake it, and coverage that merely restates a party's press release doesn't count as independent.
  • Citability gating. A claim enters the draft only if its source was actually fetched and archived (with a content hash for the audit trail). Blocked or unreachable sources push the claim to the verification worklist instead.
  • Abstention as a feature. If no reputable source supports a needed fact, the system records a gap with the queries it attempted and a suggested information request to the parties — never a guess.

What we deliberately kept away from the model

The output is a legal artifact, so the boundary between model and code is strict: the agent asserts claims and locators; Python owns identifiers, source tiers, publisher authority, confidence labels, and document assembly. Language guards flag quantitative sentences without citations and legally loaded terms (the system describes market structure; concluding "dominance" is the regulator's job, not the tool's). A dedicated pass identifies candidate relevant markets with the evidence an economist would need to test them — and is explicitly prevented from concluding the market definition itself.

What was hard

  • Official sources that block automation. Government sites behind aggressive bot protection required a tiered fetch ladder — plain HTTP, TLS-impersonating clients, and a human-in-the-loop path for the hardest cases — because "we couldn't fetch it" must degrade to a worklist entry, not a missing source.
  • Making "done" measurable. Early versions relied on the model deciding it had finished. We replaced that with an incremental ledger and a completeness gate: the pipeline assembles a report from whatever was recorded, and status footers tell the agent — in numbers — what remains.
  • Reviewability over fluency. Stakeholder feedback pushed the design toward inline claim-level citations in every narrative sentence, a research trail showing planned and executed queries, and a "changes since previous run" diff so reviewers see what moved between report versions.

Outcome

The system is deployed and in use by the client's review teams. Its reports arrive with the properties reviewers asked for: every claim cited and graded, every source archived and hashed, every gap flagged with a suggested next step — so expert time goes into vetting claims and refining analysis instead of hunting for sources.

Client identity, jurisdiction, sectors analyzed, and deployment details remain confidential. We publish the methodology because that's what a technical evaluator needs to judge the work.

Discuss a similar system