Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill contract-clause-analyzergit clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_ConstructionWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/contract-clause-analyzer)<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/contract-clause-analyzer"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/contract-clause-analyzer/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/contract-clause-analyzer"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/contract-clause-analyzer.svg" alt="Reviewed on agentmods" width="80" height="20"></a>- NVIDIA SkillSpector pass
What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00022 | $0.02817 |
| Opus 5.5 | $0.00009 | $0.01127 |
| Sonnet 5.5 | $0.00004 | $0.00563 |
| Haiku 4.5 | $0.00002 | $0.00282 |
Grade A, and why
contract-clause-analyzer scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 1mo ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
Copies of this mod
1 near-identical copy found in the catalogue:
- contract-clause-analyzer — 100% identical, 0 lines differ
How it starts
The opening of the file, as written. The whole thing — 333 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Contract Clause Analyzer
Business Case
Problem Statement
Contract review is time-consuming and error-prone:
- Important clauses missed
- Risk provisions overlooked
- Inconsistent interpretation
- Long review cycles
Solution
AI-assisted contract clause analysis that identifies key provisions, flags risks, and extracts critical terms.
Technical Implementation
import pandas as pd
from datetime import datetime, date
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from enum import Enum
import re
class ClauseType(Enum):
SCOPE = "scope"
PAYMENT = "payment"
SCHEDULE = "schedule"
CHANGE_ORDER = "change_order"
TERMINATION = "termination"
INDEMNIFICATION = "indemnification"
INSURANCE = "insurance"
WARRANTY = "warranty"
DISPUTE = "dispute"
LIABILITY = "liability"
FORCE_MAJEURE = "force_majeure"
SAFETY = "safety"
COMPLIANCE = "compliance"
OTHER = "other"
class RiskLevel(Enum):
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
INFO = "info"
@dataclass
class ContractClause:
clause_id: str
section: str
title: str
text: str
clause_type: ClauseType
risk_level: RiskLevel
key_terms: List[str] = field(default_factory=list)
obligations: List[str] = field(default_factory=list)
deadlines: List[str] = field(default_factory=list)
amounts: List[str] = field(default_factory=list)
notes: str = ""
@dataclass
class AnalysisResult:
contract_name: str
analyzed_date: datetime
total_clauses: int
clauses: List[ContractClause]
risk_summary: Dict[str, int]
key_dates: List[Dict[str, str]]
key_amounts: List[Dict[str, str]]
class ContractClauseAnalyzer:
"""Analyze construction contract clauses."""
RISK_KEYWORDS = {
'high': ['indemnify', 'sole discretion', 'waive', 'forfeit', 'liquidated damages',
'consequential', 'unlimited liability', 'hold harmless', 'no limit'],
'medium': ['shall', 'must', 'required', 'obligated', 'responsible', 'liable',
'penalty', 'default', 'breach'],
'low': ['may', 'should', 'reasonable', 'mutual', 'consent', 'approval']
}
CLAUSE_PATTERNS = {
ClauseType.PAYMENT: ['payment', 'invoice', 'retainage', 'progress payment'],
ClauseType.SCHEDULE: ['schedule', 'completion date', 'milestone', 'time is of the essence'],
ClauseType.CHANGE_ORDER: ['change order', 'modification', 'additional work', 'variation'],
ClauseType.TERMINATION: ['termination', 'terminate', 'cancellation'],
ClauseType.INDEMNIFICATION: ['indemnif', 'hold harmless', 'defend'],
ClauseType.INSURANCE: ['insurance', 'coverage', 'policy', 'insured'],
ClauseType.WARRANTY: ['warranty', 'guarantee', 'defect', 'workmanship'],
ClauseType.DISPUTE: ['dispute', 'arbitration', 'mediation', 'litigation'],
ClauseType.LIABILITY: ['liability', 'damages', 'limitation'],
ClauseType.FORCE_MAJEURE: ['force majeure', 'act of god', 'unforeseen'],
}
def __init__(self):
self.clauses: List[ContractClause] = []
def analyze_text(self, contract_name: str, text: str) -> AnalysisResult:
"""Analyze contract text."""
self.clauses = []
# Split into sections/clauses
sections = self._split_into_sections(text)
for i, section in enumerate(sections):
clause = self._analyze_clause(f"CL-{i+1:03d}", section)
self.clauses.append(clause)
# Generate summary
risk_summary = {
'high': sum(1 for c in self.clauses if c.risk_level == RiskLevel.HIGH),
'medium': sum(1 for c in self.clauses if c.risk_level == RiskLevel.MEDIUM),
'low': sum(1 for c in self.clauses if c.risk_level == RiskLevel.LOW)
}
key_dates = []
key_amounts = []
for clause in self.clauses:
for d in clause.deadlines:
key_dates.append({'clause': clause.clause_id, 'date': d})
for a in clause.amounts:
key_amounts.append({'clause': clause.clause_id, 'amount': a})
return AnalysisResult(
contract_name=contract_name,
analyzed_date=datetime.now(),
total_clauses=len(self.clauses),
clauses=self.clauses,
risk_summary=risk_summary,
key_dates=key_dates,
key_amounts=key_amounts
)
def _split_into_sections(self, text: str) -> List[Dict[str, str]]:
"""Split contract into sections."""
sections = []
# Simple split by numbered sections
pattern = r'(\d+\.[\d\.]*\s+[A-Z][^\.]+)'
parts = re.split(pattern, text)
current_title = ""
for i, part in enumerate(parts):
if re.match(r'\d+\.[\d\.]*\s+[A-Z]', part):
current_title = part.strip()
elif part.strip() and current_title:
sections.append({
'title': current_title,
'text': part.strip()
})
current_title = ""
# If no sections found, treat whole text as one
if not sections and text.strip():
sections.append({'title': 'Contract Text', 'text': text.strip()})
return sections
def _analyze_clause(self, clause_id: str, section: Dict[str, str]) -> ContractClause:
"""Analyze single clause."""
text = section.get('text', '')
title = section.get('title', '')
text_lower = text.lower()
# Determine clause type
clause_type = self._determine_type(text_lower)
# Assess risk level
risk_level = self._assess_risk(text_lower)
# Extract key terms
key_terms = self._extract_key_terms(text)
# Extract obligations
obligations = self._extract_obligations(text)
# Extract dates
deadlines = self._extract_dates(text)
# Extract amounts
amounts = self._extract_amounts(text)
return ContractClause(
clause_id=clause_id,
section=clause_id,
title=title,
text=text[:500] + "..." if len(text) > 500 else text,
clause_type=clause_type,
risk_level=risk_level,
key_terms=key_terms,
obligations=obligations,
deadlines=deadlines,
amounts=amounts
)
def _determine_type(self, text: str) -> ClauseType:
"""Determine clause type from content."""
for clause_type, keywords in self.CLAUSE_PATTERNS.items():
if any(kw in text for kw in keywords):
return clause_type
return ClauseType.OTHER
def _assess_risk(self, text: str) -> RiskLevel:
"""Assess risk level of clause."""
high_count = sum(1 for kw in self.RISK_KEYWORDS['high'] if kw in text)
medium_count = sum(1 for kw in self.RISK_KEYWORDS['medium'] if kw in text)
if high_count >= 2:
return RiskLevel.HIGH
elif high_count >= 1 or medium_count >= 3:
return RiskLevel.MEDIUM
elif medium_count >= 1:
return RiskLevel.LOW
return RiskLevel.INFO
def _extract_key_terms(self, text: str) -> List[str]:
"""Extract key defined terms."""
# Look for quoted terms or capitalized multi-word phrases
patterns = [
r'"([^"]+)"',
r"'([^']+)'",
r'\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)+)\b'
]
terms = []
for pattern in patterns:
matches = re.findall(pattern, text)
terms.extend(matches[:5])
return list(set(terms))[:10]
def _extract_obligations(self, text: str) -> List[str]:
"""Extract obligation statements."""
patterns = [
r'(?:contractor|owner|party)\s+shall\s+([^\.]+)',
r'(?:contractor|owner|party)\s+must\s+([^\.]+)',
r'(?:contractor|owner|party)\s+is\s+(?:required|obligated)\s+to\s+([^\.]+)'
]
obligations = []
for pattern in patterns:
matches = re.findall(pattern, text, re.IGNORECASE)
obligations.extend(matches[:3])
return obligations[:5]
def _extract_dates(self, text: str) -> List[str]:
"""Extract date references."""
patterns = [
r'\b\d{1,2}/\d{1,2}/\d{2,4}\b',
r'\b(?:January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{1,2},?\s+\d{4}\b',
r'\b\d+\s+(?:calendar|working|business)\s+days\b',
r'\bwithin\s+\d+\s+days\b'
]
dates = []
for pattern in patterns:
matches = re.findall(pattern, text, re.IGNORECASE)
dates.extend(matches)
return dates[:5]
def _extract_amounts(self, text: str) -> List[str]:
"""Extract monetary amounts."""
patterns = [
r'\$[\d,]+(?:\.\d{2})?',
r'\b\d+(?:,\d{3})*(?:\.\d{2})?\s*(?:dollars|USD)\b',
r'\b\d+(?:\.\d+)?%\b'
]
amounts = []
for pattern in patterns:
matches = re.findall(pattern, text, re.IGNORECASE)
amounts.extend(matches)
return amounts[:5]
def get_high_risk_clauses(self) -> List[ContractClause]:
"""Get all high-risk clauses."""
return [c for c in self.clauses if c.risk_level == RiskLevel.HIGH]
def export_analysis(self, result: AnalysisResult, output_path: str):
"""Export analysis to Excel."""
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
# Summary
summary_df = pd.DataFrame([{
'Contract': result.contract_name,
'Analyzed': result.analyzed_date,
'Total Clauses': result.total_clauses,
'High Risk': result.risk_summary['high'],
'Medium Risk': result.risk_summary['medium'],
'Low Risk': result.risk_summary['low']
}])
summary_df.to_excel(writer, sheet_name='Summary', index=False)
# Clauses
clause_data = [{
'ID': c.clause_id,
'Title': c.title[:50],
'Type': c.clause_type.value,
'Risk': c.risk_level.value,
'Key Terms': ', '.join(c.key_terms[:3]),
'Obligations': len(c.obligations),
'Dates': ', '.join(c.deadlines[:2]),
'Amounts': ', '.join(c.amounts[:2])
} for c in result.clauses]
pd.DataFrame(clause_data).to_excel(writer, sheet_name='Clauses', index=False)
return output_path
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 1mo ago First seen · 333 lines · 22 tokens per session scan A 5f215be7ee99
contract-clause-analyzer is a skill published in the GitHub repository datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction (373 stars, last pushed 8d ago), licensed MIT. It adds 22 tokens to every session and 2,817 once invoked, about $0.0001 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
klauselinhalt-und-verbote-pruefen
Prüft eine AGB-Klausel anhand von Kontrollfähigkeit, gesetzlichen Klauselverboten und Interessenabwägung. Für B2C und B2B; liefert ein Klauselvotum mit Leitbild, Gegenposition und konkreter Rechtsfolge.
write-outreach-outreach-qa
Step of the write-outreach playbook: the checks a finished outreach pack and send file must pass before delivery, covering facts, proof, compliance, length, asks and tone. Run write-outreach instead; not for direct use.
wcag
Expert WCAG (Web Content Accessibility Guidelines) advisor covering WCAG 2.0, 2.1, and 2.2 — the W3C international accessibility standards. Use this skill whenever a user asks about WCAG success criteria, conformance levels (A/AA/AAA), accessibility audits, POUR principles, accessibility statements, ARIA patterns…
compliance-checker
Audits a codebase or business process for regulatory compliance across GDPR, HIPAA, SOC2, CCPA, and PCI-DSS. Scans for PII handling, data retention, encryption, access controls, audit logging, consent management, and data transfer issues. Generates a structured compliance report with findings, gap analysis…
cease-desist-bossmann007
Draft uma notificação extrajudicial (modo envio) ou faça a triagem de uma recebida (modo recebimento). Use para fazer valer direitos contra um infrator com carta de cobrança calibrada à postura de enforcement, ou quando uma notificação recebida precisa virar memorando estruturado de opções com recomendação.
software-copyright
A guided workflow for preparing Chinese software copyright registration materials from a real software project. It produces drafts such as application details, source-code documents, and a user manual.