How to Build a Contract Template Automation System
Generate contracts from templates with automated data population.
Jay Banlasan
The AI Systems Guy
Contract template automation for legal documents turns a 45-minute manual process into a 2-minute form fill. I built this for a firm that drafts the same types of agreements repeatedly with minor variations. The attorney fills in the variables, the system populates the template, AI reviews for consistency, and a clean draft comes out ready for review.
What You Need Before Starting
- Python 3.8+
- Anthropic API key
- Contract templates in text format with placeholder markers
- A form or CLI for inputting deal terms
Step 1: Create the Template System
import re
import os
TEMPLATE_DIR = "contract_templates/"
def load_template(template_name):
path = os.path.join(TEMPLATE_DIR, f"{template_name}.txt")
with open(path) as f:
return f.read()
def get_template_variables(template_text):
return list(set(re.findall(r"\{\{(\w+)\}\}", template_text)))
def populate_template(template_text, variables):
result = template_text
for key, value in variables.items():
result = result.replace(f"{{{{{key}}}}}", str(value))
missing = re.findall(r"\{\{(\w+)\}\}", result)
return result, missing
Step 2: Define Common Templates
Create contract_templates/service_agreement.txt:
SERVICE AGREEMENT
This Service Agreement ("Agreement") is entered into as of {{effective_date}}
by and between:
{{provider_name}}, a {{provider_entity_type}} organized under the laws of
{{provider_state}} ("Provider")
and
{{client_name}}, a {{client_entity_type}} organized under the laws of
{{client_state}} ("Client")
1. SERVICES
Provider shall perform the following services: {{scope_of_services}}
2. TERM
This Agreement begins on {{start_date}} and continues for {{term_length}},
unless terminated earlier per Section 6.
3. COMPENSATION
Client shall pay Provider {{payment_amount}} {{payment_frequency}}.
Payment is due within {{payment_terms}} days of invoice.
4. CONFIDENTIALITY
Both parties agree to maintain the confidentiality of proprietary information
disclosed during the term of this Agreement for a period of {{confidentiality_years}} years.
5. LIABILITY
Provider's total liability under this Agreement shall not exceed {{liability_cap}}.
6. TERMINATION
Either party may terminate with {{notice_period}} days written notice.
7. GOVERNING LAW
This Agreement shall be governed by the laws of {{governing_state}}.
Step 3: Build the Generation Engine
import anthropic
from dotenv import load_dotenv
load_dotenv()
def generate_contract(template_name, variables):
template = load_template(template_name)
document, missing = populate_template(template, variables)
if missing:
return {"error": f"Missing variables: {', '.join(missing)}", "document": None}
reviewed = review_populated_contract(document, variables)
return {
"document": document,
"review": reviewed,
"template": template_name,
"variables_used": list(variables.keys())
}
def review_populated_contract(document, variables):
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="""Review this populated contract for:
1. Internal consistency (dates, names, terms match throughout)
2. Missing information or placeholder text that was not replaced
3. Potentially problematic terms based on the deal structure
4. Formatting issues
Return a brief checklist of issues found, or confirm the document looks clean.""",
messages=[{
"role": "user",
"content": f"Review this contract:\n\n{document}"
}]
)
return response.content[0].text
Step 4: Build the CLI Interface
import json
def interactive_contract_generation(template_name):
template = load_template(template_name)
variables = get_template_variables(template)
print(f"Generating {template_name}")
print(f"Fill in {len(variables)} fields:\n")
values = {}
for var in sorted(variables):
label = var.replace("_", " ").title()
value = input(f" {label}: ")
values[var] = value
result = generate_contract(template_name, values)
if result.get("error"):
print(f"\nError: {result['error']}")
return
output_file = f"drafts/{template_name}_{values.get('client_name', 'draft').replace(' ', '_')}.txt"
os.makedirs("drafts", exist_ok=True)
with open(output_file, "w") as f:
f.write(result["document"])
print(f"\nContract saved to {output_file}")
print(f"\nAI Review:\n{result['review']}")
Step 5: Add Clause Library Support
CLAUSE_LIBRARY = {
"non_compete": """NON-COMPETE
During the term and for {{non_compete_period}} following termination,
Provider shall not provide similar services to direct competitors of Client
within {{non_compete_geography}}.""",
"force_majeure": """FORCE MAJEURE
Neither party shall be liable for delays caused by circumstances beyond
reasonable control, including natural disasters, government actions, or
pandemic-related restrictions.""",
"ip_assignment": """INTELLECTUAL PROPERTY
All work product created under this Agreement shall be the exclusive
property of {{ip_owner}}. Provider assigns all rights, title, and interest
in such work product to {{ip_owner}}."""
}
def add_clause(document, clause_name, variables=None):
clause = CLAUSE_LIBRARY.get(clause_name)
if not clause:
return document
if variables:
clause, _ = populate_template(clause, variables)
return document + "\n\n" + clause
if __name__ == "__main__":
interactive_contract_generation("service_agreement")
What to Build Next
Add version tracking. When a contract goes through revisions, store each version with a diff showing what changed. That creates an audit trail of negotiation history.
Related Reading
- AI for Proposal and Document Creation - document generation patterns
- AI in Legal and Compliance - legal AI applications
- AI for Workflow Optimization - workflow automation
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment