How to Build a Multi-Agent Contract Review Assistant in Python¶
A single model reviewing a contract will confidently miss the clause that matters. This recipe uses Cross-Reflection: a drafting "counsel" proposes redlines and risk notes, an independent reviewing "partner" critiques them, and they iterate until the review is solid — surfacing liability before a human ever opens the document.
Patterns used: Cross-Reflection · Guardrails
Architecture¶
flowchart TD
C[Clause] --> GD[Guardrail\nstrip client identifiers]
GD --> G[Counsel\npropose redlines + risk]
G --> R[Partner\ncritique redlines]
R -->|revise| G
R -->|approved| O[Reviewed Redlines + Flags]
Implementation¶
import asyncio
from pyagent_patterns.base import Agent
from pyagent_patterns.resolution import CrossReflection
from pyagent_patterns.guardrails import GuardrailChain, PIIGuard
from pyagent_providers import AnthropicLLM
smart_llm = AnthropicLLM("claude-sonnet-4-20250514")
# Keep counterparty / client identifiers out of third-party model logs.
confidentiality_guard = GuardrailChain([PIIGuard(redact=True)])
review = CrossReflection(
generator=Agent(
"counsel", smart_llm,
system_prompt=(
"You are reviewing counsel. For the clause, propose specific redlines and explain the "
"risk each one mitigates. Be concrete: quote the language you would change."
),
),
reviewer=Agent(
"partner", smart_llm,
system_prompt=(
"You are the reviewing partner. Critique the proposed redlines: flag anything that "
"increases our liability, weakens an indemnity, or misreads the clause. Reply 'APPROVED' "
"only when the redlines are sound."
),
),
max_rounds=2,
)
CLAUSE = (
"Limitation of Liability. In no event shall either party's aggregate liability exceed the fees "
"paid by Customer in the three (3) months preceding the claim. This cap applies to all claims, "
"including those arising from gross negligence or breach of the confidentiality obligations."
)
async def main():
safe_clause = confidentiality_guard.check(CLAUSE).sanitized_content or CLAUSE
result = await review.run(safe_clause)
print(result.output) # surface to a human for final sign-off
asyncio.run(main())
Expected Output¶
REVIEWED REDLINES — Limitation of Liability
1. Carve out gross negligence, willful misconduct, and confidentiality breaches from the cap.
Risk: as written, the 3-month cap shields the counterparty even for a data breach. (partner: agreed,
highest priority)
2. Increase the cap to 12 months' fees (market standard for this contract value).
3. Make the cap mutual and add a separate, higher cap for IP-indemnity claims.
FLAGS: the original cap is unusually low and applies to gross negligence — do not sign as-is.
The partner's critique is what catches the buried "including … gross negligence" — a second, adversarial reading that a single pass tends to gloss over.
Customization¶
Review a whole contract clause-by-clause¶
async def review_contract(clauses: list[str]) -> list[str]:
safe = [confidentiality_guard.check(c).sanitized_content or c for c in clauses]
results = await asyncio.gather(*(review.run(c) for c in safe))
return [r.output for r in results]
Add a playbook check¶
Prepend the firm's negotiation playbook to the counsel prompt so redlines follow house positions:
review.generator.system_prompt += "\n\nFollow our playbook: liability cap ≥ 12 months; mutual indemnities."
Gate sign-off behind a human¶
Pair with Human-in-the-Loop so any clause the partner flags as high-risk routes to an attorney — see the Support Router.
When to Use¶
| Situation | Fit |
|---|---|
| A second, independent agent should review the first | ✅ Cross-Reflection |
| Confidential identifiers must be stripped | ✅ Guardrails |
| The same agent should critique its own work | ❌ Use Self-Reflection |
| Many reviewers vote on a verdict | ❌ Use Voting |
Cost Profile¶
| Stage | Typical model | Avg cost | Volume (500 contracts/mo, 20 clauses each) |
|---|---|---|---|
| Counsel + partner (≤2 rounds) | claude-sonnet | $0.010/clause | ~$100/mo |
| Per clause | claude-sonnet | ~$0.010 | ~$100/mo |
Cross-Reflection roughly doubles per-clause cost vs a single pass — worth it for high-liability clauses; use a single pass for boilerplate.
See Also¶
- Cross-Reflection pattern · Guardrails guide
- Regulatory Compliance Checker — hierarchical gap analysis against regulations
- Browse all recipes