Contract Review & Extraction
Automate contract analysis at scale. The agent reads uploaded contracts, extracts key terms into structured data, compares against your standard playbook, flags deviations and risky clauses, and routes findings for legal review. Every extraction and flag is auditable.
Architecture
Graduated review: Standard-term contracts can finish on the deterministic path. Contracts with deviations get AI-assisted analysis, and the approval step gives legal counsel the final decision. Tune routing percentages from your own contract history instead of treating sample rates as guarantees.
Required Actions
| Action | Kind | Purpose |
|---|---|---|
extract_contract_terms |
http |
Call an extraction endpoint that returns schema-validated terms |
assess_clause_risk |
llm |
Classify risk level of a specific clause |
draft_redline |
llm |
Generate suggested alternative language |
search_precedent |
http |
Search past executed contracts for similar clauses |
read_contract_review_cases |
custom-table |
Read this run's exceptions for the review agent |
curl -X POST https://your-hyphen.example.com/actions \
-H "X-Org-Id: your-org" \
-H "Content-Type: application/json" \
-d '{
"action_name": "extract_contract_terms",
"kind": "http",
"description": "Extract contract clauses and return a validated extracted_terms object",
"url": "https://your-extraction-service.example.com/contracts/extract",
"http_method": "POST",
"headers": {
"Authorization": "Bearer orgconfig:api:contract_extraction_token"
},
"passthrough": true
}'
Register read_contract_review_cases as a custom-table read action on contract_review_cases, with where.run_id set to @__run_id. That gives the agent a current-run default while keeping the tool on the existing custom-table action contract.
curl -X POST https://your-hyphen.example.com/actions \
-H "X-Org-Id: your-org" \
-H "Content-Type: application/json" \
-d '{
"action_name": "assess_clause_risk",
"kind": "llm",
"template": "Assess the risk of this contract clause for our organization.\n\nClause: {{input.clause_text}}\nOur standard position: {{input.standard_position}}\nContract value: {{input.contract_value}}\n\nClassify as:\n- low: Minor deviation, commercially acceptable\n- medium: Notable deviation, should be negotiated but not a blocker\n- high: Material risk, requires legal review before signing\n- critical: Unacceptable as written, must be changed\n\nReturn a concise assessment with the risk level, reasoning, and recommendation.",
"model": "gpt-4",
"max_tokens": 500
}'
Workflow Definition
{
"name": "contract_review_pipeline",
"definition": {
"actions": [
{
"type": "extract_contract_terms",
"properties": {
"keys": ["contract_text", "contract_type"],
"values": ["@input.contract_text", "@input.contract_type"]
}
},
{
"type": "matcher",
"properties": {
"left": "@extracted_terms.clauses",
"right": "@input.playbook_terms",
"matchOn": ["clause_type"],
"fuzzyThreshold": 80,
"descriptionKey": "clause_text",
"outputMatched": "standard_clauses",
"outputUnmatchedLeft": "deviations",
"outputUnmatchedRight": "missing_clauses"
}
},
{
"type": "loop",
"filter": {
"condition": {
"greaterThan": [{ "length": "@deviations" }, 0]
}
},
"properties": {
"mode": "foreach",
"items": "@deviations",
"itemKey": "deviation",
"actions_to_execute": [
{
"type": "custom-table",
"properties": {
"table": "contract_review_cases",
"operation": "write",
"keys": ["run_id", "case_type", "clause_type"],
"values": ["@__run_id", "deviation", "@deviation.clause_type"],
"fields": {
"contract_id": "@input.contract_id",
"counterparty": "@input.counterparty",
"contract_value": "@input.contract_value",
"case_data": "@deviation"
}
}
}
]
}
},
{
"type": "loop",
"filter": {
"condition": {
"greaterThan": [{ "length": "@missing_clauses" }, 0]
}
},
"properties": {
"mode": "foreach",
"items": "@missing_clauses",
"itemKey": "missing_clause",
"actions_to_execute": [
{
"type": "custom-table",
"properties": {
"table": "contract_review_cases",
"operation": "write",
"keys": ["run_id", "case_type", "clause_type"],
"values": ["@__run_id", "missing", "@missing_clause.clause_type"],
"fields": {
"contract_id": "@input.contract_id",
"counterparty": "@input.counterparty",
"contract_value": "@input.contract_value",
"case_data": "@missing_clause"
}
}
}
]
}
},
{
"type": "loop",
"filter": {
"condition": {
"or": [
{ "greaterThan": ["@input.contract_value", 100000] },
{ "greaterThan": [{ "length": "@deviations" }, 0] },
{ "greaterThan": [{ "length": "@missing_clauses" }, 0] }
]
}
},
"properties": {
"mode": "react",
"objective": "Review every contract exception for the current workflow run. Use read_contract_review_cases first. Assess risk, search precedent where useful, draft alternative language for material deviations, and complete with a concise recommendation for legal review.",
"tools": [
{ "type": "action", "name": "read_contract_review_cases" },
{ "type": "action", "name": "assess_clause_risk" },
{ "type": "action", "name": "search_precedent" },
{ "type": "action", "name": "draft_redline" }
],
"model": "gpt-4",
"max_iterations": 15,
"timeout_ms": 300000,
"on_stuck": {
"iterations": 4,
"action": "escalate"
},
"result_key": "review_analysis"
}
},
{
"type": "PbotApproval",
"filter": {
"condition": {
"or": [
{ "greaterThan": ["@input.contract_value", 100000] },
{ "greaterThan": [{ "length": "@deviations" }, 0] },
{ "greaterThan": [{ "length": "@missing_clauses" }, 0] }
]
}
},
"properties": {
"comment": "Contract review is ready for a legal decision. Review the extracted terms, deterministic exceptions, and AI-assisted analysis before approving.",
"request_payload": {
"counterparty": "@input.counterparty",
"contract_value": "@input.contract_value",
"extracted_terms": "@extracted_terms",
"deviations": "@deviations",
"missing_clauses": "@missing_clauses",
"ai_analysis": "@review_analysis"
}
}
},
{
"type": "custom-table",
"properties": {
"table": "contract_registry",
"operation": "write",
"keys": ["contract_id"],
"values": ["@input.contract_id"],
"fields": {
"counterparty": "@input.counterparty",
"contract_value": "@input.contract_value",
"effective_date": "@extracted_terms.effective_date",
"termination_date": "@extracted_terms.termination_date",
"liability_cap": "@extracted_terms.liability_cap",
"deviations_count": "@deviations.length",
"reviewed_at": "@now"
}
}
}
]
}
}
What the Agent Investigates
For each deviation from your standard playbook, the agent:
1. Classifies risk. Uses the assess_clause_risk LLM action with your standard position as context. A liability cap of $1M on a $50K contract is low risk. Unlimited liability on a $500K contract is critical.
2. Searches precedent. Queries your contract database for past agreements with similar deviations. "We accepted a 12-month non-compete from Vendor X in 2024" provides negotiating context.
3. Drafts redlines. For high/critical risks, generates alternative language that protects your position while remaining commercially reasonable.
4. Flags missing clauses. If your playbook requires a data processing addendum and the contract doesn't include one, the agent notes this as a gap requiring attention.
Sample Recorded Agent Trace
Iteration 1:
Summary: "3 deviations found. Starting with the most concerning: unlimited liability clause."
Action: assess_clause_risk
Input: { "clause_text": "Vendor shall be liable for all damages without limitation...",
"standard_position": "Liability capped at 2x annual contract value",
"contract_value": "250000" }
Result: { "risk_level": "critical", "reasoning": "Unlimited liability on $250K contract exposes us...",
"recommendation": "Require cap at 2x annual value ($500K)" }
Iteration 2:
Summary: "Critical risk. Checking whether a comparable term was accepted before."
Action: search_precedent
Input: { "counterparty": "TechVendor Inc", "clause_type": "liability" }
Result: { "found": true, "precedent": "2024 contract: liability capped at $300K" }
Iteration 3:
Summary: "The prior contract used a cap. Drafting alternative language."
Action: draft_redline
Input: { "original": "Vendor shall be liable for all damages without limitation...",
"position": "Cap at 2x annual value, consistent with 2024 agreement" }
Result: { "suggested_language": "Vendor's aggregate liability shall not exceed two times the annual fees..." }
Iteration 4:
Summary: "Logging progress and moving to the next deviation."
Action: __log_progress__
Input: { "message": "Liability clause: CRITICAL. Redline drafted. Precedent: 2024 cap at $300K." }
... [continues for remaining deviations] ...
Iteration 8:
Summary: "All deviations reviewed. One critical, one medium, and one low-risk issue found."
Action: __complete__
Input: {
"answer": "Overall risk: HIGH. One critical clause has a drafted redline, with one medium and one low-risk issue. Recommend negotiation before signing.",
"confidence": 0.9
}
Customization
Contract types: Configure the extraction adapter for your contract types, such as SaaS agreements, NDAs, MSAs, SOWs, and vendor agreements. Keep its response contract stable: { "extracted_terms": { "clauses": [...] } } plus the summary fields you want to record.
Playbook terms: The @input.playbook_terms dataset is your standard acceptable positions. Maintain this as a custom table that legal updates as policies change.
Risk thresholds: The sample sends any exception or contract over $100K to approval. Adjust the deterministic filter to your organization's materiality policy.
Approval routing: Use different workflows when different contract types need different decision owners. Procurement can own vendor agreements, legal can own customer-facing terms, and finance can own non-standard payment terms.
Term database: The contract_registry custom table creates a searchable record of extracted terms across contracts. It supports portfolio questions such as "how many contracts have unlimited liability?" and can feed the precedent search service.