---
title: "Smart Category Routing for Contract Review"
canonical_url: "https://cognilium.ai/blogs/smart-category-routing-contract-review"
slug: "smart-category-routing-contract-review"
section: "blogs"
date_published: "2026-05-05"
date_modified: "2026-08-24"
word_count: 1300
reading_time_minutes: 6
author: "Mudassir Marwat"
author_identifier: "0009-0008-1927-2598"
person_same_as:
  - "https://www.linkedin.com/in/mudassir-marwat/"
  - "https://orcid.org/0009-0008-1927-2598"
  - "https://github.com/mudassirmarwat"
  - "https://medium.com/@mudassir-marwat"
  - "https://www.youtube.com/@mudassir-marwat"
  - "https://dev.to/mudassirmarwat"
  - "https://hashnode.com/@mudassirmarwat"
  - "https://huggingface.co/mudassirmarwat"
  - "https://bsky.app/profile/mudassir-marwat.bsky.social"
  - "https://substack.com/@mudassirmarwat"
  - "https://topmate.io/mudassirmarwat"
  - "https://fueler.io/mudassirmarwat"
  - "https://www.instagram.com/mudassirmarwat/"
  - "https://www.facebook.com/mudassir.marwat"
  - "https://www.reddit.com/user/mudassirmarwat/"
  - "https://www.f6s.com/member/mudassir-marwat"
  - "https://cognilium.ai/founder"
entities: []
related:
  - "https://cognilium.ai/blogs/production-llmops-stack"
  - "https://cognilium.ai/blogs/llm-judge-temperature-escalation-retry"
  - "https://cognilium.ai/blogs/smart-category-score-routing-cost"
  - "https://cognilium.ai/blogs/hybrid-retrieval-prefetch-metadata-filtering"
---
# Smart Category Routing for Contract Review

A focused application of the LLMOps routing pattern to legal contract analysis — the analyst-selection logic that ships fewer clauses to fewer agents and finishes a 3,300-call review in 154 seconds.

## Key takeaways

- Score cheaply, analyze expensively: a cheap scoring pass across every category decides which specialist analysts a chunk deserves, so the expensive models run only where routing says they will pay.
- The playbook is customer configuration, not code — categories, severity weights and party-specific clauses steer routing without a redeploy.
- Retrieval is enriched at ingestion: each playbook term carries hypothetical-answer text, so matching works even when the contract and the playbook use different vocabulary.
- A wide, cheap retrieval pass followed by an LLM reranker keeps recall high and analyst context tight — the reranker, not the vector search, sets precision.

Contract review is a domain where the LLMOps routing pattern earns its complexity. A typical contract has 50-100 chunks. Each chunk is potentially relevant to one or two of 11 specialist analysts (compliance, indemnity, IP, payment, termination, etc.). Running every analyst on every chunk is 1,100+ LLM calls. Routing cuts that to ~250.

## Playbook-driven configuration

Each customer has a playbook in S3 — categories that matter to them, severity weights, and party-specific clauses (one customer cares deeply about IP indemnity; another cares about data-residency clauses). At job start, the system loads the playbook and configures analysts accordingly.

- Categories: 12 standard, 1-3 customer-specific
- Severity weights: how much to escalate findings in each category
- Party-specific clauses: customer-defined patterns the analyst should specifically look for

## Per-chunk scoring

Each chunk runs through 12 category scorers (cheap model, $0.25/M tokens). Each scorer emits a 0-100 score for "is this chunk relevant to my category?" The router selects analysts to run based on the scores: above-threshold categories trigger their analyst; below-threshold categories skip.

## HyDE-augmented retrieval

HyDE runs at ingestion, per playbook term. The enrichment agent generates a hypothetical ideal answer for each term — search-optimized text embedded alongside the term itself — so retrieval matches contract chunks against what a relevant clause would say, not against the term's literal wording. Better recall than embedding the label alone, especially when the playbook uses legal jargon and the contract uses plain English (or vice versa).

## LLM reranking after HyDE

Vector search returns the top ten candidate chunks per playbook term; an LLM reranker scores each candidate and narrows to the three most relevant, which are deduplicated before anything reaches an analyst. The wide first pass is allowed to be cheap and loose because the reranker pays the precision bill.

## Numbers from production

- 22 chunks → 116 LLM calls per chunk (12 scorers + ~3 routed analysts × ~30 LLM calls each) = ~660 calls per chunk on the misleading top-line
- Actually: 22 chunks × 12 scorers + ~3 selected analysts per chunk × 8 calls = 264 + 528 = ~800 calls per contract typical
- P50 review time: 154 seconds end-to-end
- Per-contract cost: $0.50-2.00 depending on contract length and customer playbook
- Reduction vs. naive fan-out: ~75%

## Where this fails

Customer playbooks with overlapping categories (the "compliance" category overlaps with "regulatory" and "data-handling" 70% of the time). Routing collapses to "everyone." Mitigation: routing analytics dashboard shows per-category overlap rates; surfaces the problem; encourages playbook tightening.

## Frequently asked questions

### How does this differ from the LLMOps routing chapter?

Same routing pattern, applied to contract analysis specifically. This chapter walks the legal-domain choices: how categories are defined, how the playbook is loaded per job, how HyDE-augmented retrieval seeds the per-chunk context.

### What is HyDE-augmented retrieval?

Hypothetical Document Embeddings: generate a pretend "ideal answer" to the query, embed that, retrieve similar real chunks. Often retrieves better than embedding the literal query — particularly when query language differs from corpus language.

### Why ChromaDB instead of Pinecone or Qdrant?

Per-job ephemeral storage. Each contract review creates a fresh ChromaDB instance with that job's chunks; tear down at job end. No tenant cross-contamination, no long-running index to maintain. Pinecone would work; the cost-per-job is lower with ephemeral Chroma.

### How is the playbook loaded?

Each customer has a playbook in S3 (categories, severity weights, party-specific clauses). At job start, the playbook loads into the analyst configuration. Different customers analyze the same contract differently — playbook-driven configuration handles that.

### Where does this break?

When the playbook is poorly defined (categories overlap, severity weights are uniform), routing collapses to "everyone." Encourages teams to invest in playbook precision; provides routing analytics to show where overlaps cause routing failures.

---

Canonical HTML: https://cognilium.ai/blogs/smart-category-routing-contract-review
