An Indian SME owner receives a six-page services agreement on a Friday evening with "please sign by Monday". The lawyer is a phone call away but costs money by the hour, so the owner pastes the text into a chatbot and asks "is this fine?". The chatbot says yes, mostly, with a confident summary. The summary says payment is due in 30 days. The contract says 60.
The short answer: use an LLM for contract clause extraction only if every extracted item carries a verbatim quote that code checks against the document, with a required-clause list that flags what was missed. That turns a plausible summary into something you can audit in ten minutes. This is a reading aid for the person who will then sit with a lawyer. It is not legal advice, it cannot tell you whether a clause is enforceable in India, and I have not checked any Indian law for this post. Ask a qualified professional about that.
I ran a checker on an invented agreement I wrote for testing (no real parties) and pasted the real output. The "model output" in the run is hand-written JSON with deliberate mistakes, because I had no model API in this session. So the run shows what the checker catches, not how often a model errs.
What should you extract from an SME contract?
Pick a short, fixed list so nothing is missed by accident. This is a reading checklist, not a legal standard.
| Field | Why a business owner looks at it |
|---|---|
| Term and renewal | Auto-renewal with a notice window is easy to miss |
| Payment terms | Days to pay, and from which date |
| Late-payment interest | Rate and the date it starts |
| Termination | Who can leave, how quickly, for what |
| Liability cap | What the other side can lose you versus what you can claim |
| Indemnity | Who pays when a third party sues, and how broad |
| IP ownership | When rights transfer, and what stays with the creator |
| Confidentiality | How long it lasts after the contract ends |
| Governing law, disputes | Court or arbitration, place, who picks the arbitrator |
Stamp duty, registration, GST wording and sector rules are also relevant to many Indian contracts, and each needs a professional. I have deliberately not stated any rule on them here.
How should the extraction prompt be written?
The prompt below is an untested template; I did not run it on a live model for this post. The design matters more than the wording: demand a quote, allow "not found", and forbid interpretation.
You are extracting clauses from a contract for a reader who is not a lawyer.
Use ONLY the CONTRACT text below. Do not give legal advice or say whether a
clause is fair or enforceable.
For each type in this list, return one item, or {"type": "...", "found": false}
if the contract has no such clause:
term, renewal, payment_terms, late_interest, termination, liability_cap,
indemnity, ip_ownership, confidentiality, governing_law, dispute_resolution
Each found item must be:
{"type": "...", "found": true, "value": "<short plain-English value>",
"quote": "<exact sentence(s) copied from the contract, unchanged>",
"clause_number": "<number from the contract or null>"}
Rules:
- "quote" must be copied character for character. Do not paraphrase it.
- If a clause has several parts (for example termination by both sides),
quote all the relevant sentences.
- If two clauses conflict, return both quotes and add "conflict": true.
- Numbers in "value" must appear in "quote".
Return a JSON array only.
CONTRACT:
[PASTE TEXT, WITH PERSONAL DETAILS REMOVED WHERE POSSIBLE]
Notice "if the contract has no such clause". Without an explicit way to say "not found", models tend to fill the slot with something plausible.
How does the checker work?
Three checks, none needing a model:
- Quote exists. Normalise whitespace and case, then require the quote to appear in the contract text.
- Numbers match. Every number in
valuemust appear inquote(with "three" treated as 3 in my version). - Coverage. Every required type must appear in the output. A missing type is flagged "check the contract, do not assume absent", because the model failing to extract a clause is not evidence that the clause isn't there.
I also added plain-regex flags run directly on the contract text, independent of the model, for patterns a reader should see: an arbitrator appointed by one party, a one-sided immediate termination right, auto-renewal, a broad one-way indemnity, and a late-payment interest rate.
The core of the script (the invented contract and the simulated JSON are omitted; the invented contract states 60-day payment terms, a 24% late-interest rate and an arbitrator appointed by the Supplier):
import re
def norm(s):
return re.sub(r"\s+", " ", s).strip().lower()
NC = norm(contract)
problems = []
seen = set()
for item in model_output:
seen.add(item["type"])
q = norm(item["quote"])
if q not in NC:
problems.append("%s: quote NOT FOUND verbatim in contract" % item["type"])
for n in re.findall(r"\d+", item["value"]):
qn = re.sub(r"\bthree\b", "3", item["quote"].lower())
if n not in qn:
problems.append("%s: number %s in value is not in the quote" % (item["type"], n))
for r in REQUIRED:
if r not in seen:
problems.append("%s: MISSING from extraction (check the contract, do not assume absent)" % r)
FLAGS = [
(r"appointed by the (supplier|customer)", "arbitrator appointed by one party"),
(r"immediately if any invoice", "immediate termination right for one party"),
(r"renews automatically", "auto-renewal with notice window"),
(r"indemnify the \w+ against all claims", "one-way broad indemnity"),
(r"interest at (\d+)% per annum", "late-payment interest rate present"),
]
Output from running it on 2026-10-09:
== checker problems ==
- payment_terms: quote NOT FOUND verbatim in contract
- termination: number 15 in value is not in the quote
- indemnity: MISSING from extraction (check the contract, do not assume absent)
- confidentiality: MISSING from extraction (check the contract, do not assume absent)
== regex flags on contract ==
- arbitrator appointed by one party -> 'appointed by the Supplier'
- immediate termination right for one party -> 'immediately if any invoice'
- auto-renewal with notice window -> 'renews automatically'
- one-way broad indemnity -> 'indemnify the Supplier against all claims'
- late-payment interest rate present -> 'interest at 24% per annum'
What did the checker catch, and what did it miss?
I planted four problems in the simulated extraction. Three were caught:
- Wrong payment term. The simulated extractor wrote "30 days" in a quote the contract doesn't contain. The real clause says 60. Caught by the quote check.
- Incomplete quote. The termination entry mentioned a 15-day unpaid-invoice trigger but quoted only the convenience-termination sentence. Caught by the number check.
- Skipped clauses. Indemnity and confidentiality were not extracted. Caught by coverage.
The fourth was not caught. The IP entry says "Customer owns on signing", but its quote (which does exist in the contract) says ownership stays with the Supplier until full payment. The quote check passes because the quote is real; the value is wrong. This is the failure to worry about most, because everything looks verified. Defences, none perfect:
- Show the reader the quote next to the value, and have the reader read the quote, not the summary.
- Add a second check that asks a model, separately, whether the value is supported by the quote, and treat disagreement as a flag. This is an untested idea, and a model can be wrong twice.
- For any clause involving money or ownership, a human reads the clause itself.
The regex flags worked on this contract because I knew the patterns I wanted, having written it. On a real contract, drafting varies, so use them as a nudge, not a clean bill of health. Silence from a flag means nothing.
What does a sensible review workflow look like?
- Remove what you can. Names, amounts and addresses are often unnecessary for extraction. Before pasting, check the contract's own confidentiality clause and your tool's data policy. See what not to paste into ChatGPT and the data retention and training opt-out table. For redaction in code, see PII redaction before LLM calls.
- Extract with the prompt above. Prefer a model API or a plan where you know the retention settings.
- Run the checker. Fix or discard every failed item. Treat missing types as "go and read".
- Read the flagged clauses yourself, quote first, summary second.
- Write your questions. For each worrying clause, one line: what does this do to me, and what would I want changed?
- Take the questions to a lawyer. You will spend their time on judgement rather than on finding the clauses.
A prompt for step 5, again an untested template:
I am a small-business owner, not a lawyer. For each clause below, write
(a) one plain sentence on what it says, quoting the key words, and
(b) one question I could ask a lawyer about it. Do not say whether the
clause is legal, fair or enforceable. Do not suggest replacement wording.
CLAUSES: [PASTE THE VERIFIED QUOTES]
What are the limits of this approach?
- Long contracts. A 60-page master agreement with annexures and cross-references needs chunking, and clauses that refer to other clauses ("subject to clause 14.2") get lost. Use the same quote check per chunk, and see chunking strategies compared on real documents.
- Scanned PDFs. OCR errors alter numbers. Compare numbers against the original page image. The PDF and invoice extraction agent post covers the extraction side.
- Regional-language contracts. Quote matching depends on exact text. For Hindi or other languages, verify the OCR, and be careful with translations. See the translation quality checklist.
- Judgement. Whether a 24% interest rate or a one-sided arbitrator clause is acceptable, enforceable or negotiable in your case is a legal question. This workflow does not answer it.
- The checker is mine. It was tested on one invented contract with simulated output. Test it on your own past contracts, where you already know the answers, before relying on it.
If you want a broader view of how lawyers themselves use AI with citations, see prompt engineering for lawyers and research memos with citation checks.
What to do this week
- Pick two signed contracts you understand well. Run the extraction and checker on them and see what fails.
- Add your own required types (for example, a non-compete or exclusivity clause) to the list.
- Add flags for patterns that have hurt you before.
- Before your next signing, run the workflow and take the question list to your lawyer.
When to skip it: if the contract is high-value, unusual or involves property, equity or regulated activity, go straight to a lawyer. The tool saves reading time. It does not substitute for advice.



