Add web search to a contract review agent by extracting key clauses, building targeted search queries, fetching legal precedents and regulatory context, and compiling enriched context for the LLM to reference during review. Contract review agents that rely solely on training data miss recent regulatory changes, industry-specific clause benchmarks, and relevant case law. Adding a search layer gives the agent access to current legal context without requiring a specialized legal database subscription.
Prerequisites
- Python 3.8+ installed
- requests library installed
- A Scavio API key from scavio.dev
- A contract text or extracted clause list to review
Walkthrough
Step 1: Extract key clauses
Parse the contract to identify clauses that benefit from external context: indemnification, liability caps, termination, IP assignment, and non-compete.
import os, requests, re
API_KEY = os.environ['SCAVIO_API_KEY']
SEARCHABLE_CLAUSES = [
'indemnification', 'limitation of liability', 'termination',
'intellectual property', 'non-compete', 'confidentiality',
'force majeure', 'data protection', 'warranty',
]
def extract_clauses(contract_text: str) -> list:
found = []
text_lower = contract_text.lower()
for clause in SEARCHABLE_CLAUSES:
if clause in text_lower:
# Find the paragraph containing the clause
for para in contract_text.split('\n\n'):
if clause in para.lower():
found.append({'type': clause, 'text': para[:500]})
break
return found
sample = 'The limitation of liability shall not exceed 12 months of fees paid.\n\nForce majeure events include...'
print(f'Found {len(extract_clauses(sample))} searchable clauses')Step 2: Build search queries from clauses
Convert each extracted clause into a targeted search query that finds relevant precedents and benchmarks.
def build_queries(clauses: list) -> list:
queries = []
for clause in clauses:
clause_type = clause['type']
# Regulatory query
queries.append({
'clause': clause_type,
'query': f'{clause_type} clause standard 2026 SaaS contract',
'purpose': 'benchmark',
})
# Precedent query
queries.append({
'clause': clause_type,
'query': f'{clause_type} clause legal precedent enforceability',
'purpose': 'precedent',
})
return queries
clauses = [{'type': 'limitation of liability', 'text': 'Cap at 12 months fees'}]
for q in build_queries(clauses):
print(f"[{q['purpose']}] {q['query']}")Step 3: Fetch legal precedents via search
Run each query through Scavio and collect relevant results as context for the contract review.
def fetch_precedents(queries: list) -> list:
context = []
for q in queries:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': q['query']}, timeout=15)
results = resp.json().get('organic_results', [])[:3]
for r in results:
context.append({
'clause': q['clause'],
'purpose': q['purpose'],
'title': r.get('title', ''),
'snippet': r.get('snippet', ''),
'url': r.get('link', ''),
})
print(f'Collected {len(context)} precedent references')
return context
queries = [{'clause': 'limitation of liability', 'query': 'limitation of liability SaaS contract 2026', 'purpose': 'benchmark'}]
fetch_precedents(queries)Step 4: Compile review context
Organize the search results into a structured context block that the LLM uses during contract review.
def compile_review_context(clauses: list, precedents: list) -> str:
context_parts = []
for clause in clauses:
clause_type = clause['type']
relevant = [p for p in precedents if p['clause'] == clause_type]
context_parts.append(f'\n## {clause_type.title()}')
context_parts.append(f'Contract text: {clause["text"][:200]}')
benchmarks = [p for p in relevant if p['purpose'] == 'benchmark']
if benchmarks:
context_parts.append('Industry benchmarks:')
for b in benchmarks:
context_parts.append(f' - {b["title"]}: {b["snippet"][:150]}')
precs = [p for p in relevant if p['purpose'] == 'precedent']
if precs:
context_parts.append('Legal precedents:')
for p in precs:
context_parts.append(f' - {p["title"]}: {p["snippet"][:150]}')
return '\n'.join(context_parts)
clauses = [{'type': 'limitation of liability', 'text': 'Cap at 12 months'}]
precedents = [{'clause': 'limitation of liability', 'purpose': 'benchmark', 'title': 'SaaS Liability Caps 2026', 'snippet': 'Industry standard is 12-24 months of fees', 'url': ''}]
print(compile_review_context(clauses, precedents))Python Example
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def search_clause_context(clause_type):
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': f'{clause_type} clause SaaS contract standard 2026'}).json()
return [{'title': r['title'], 'snippet': r.get('snippet', '')} for r in data.get('organic_results', [])[:3]]
print(search_clause_context('limitation of liability'))JavaScript Example
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function searchClause(clauseType) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H,
body: JSON.stringify({platform: 'google', query: `${clauseType} clause SaaS contract standard 2026`})
});
return ((await r.json()).organic_results || []).slice(0, 3).map(r => ({title: r.title, snippet: r.snippet}));
}
searchClause('limitation of liability').then(console.log);Expected Output
A contract review agent enriched with current legal precedents, clause benchmarks, and regulatory context sourced from web search for each key clause.