A 30-person UK professional services firm found out in March that three supplier contracts had auto-renewed without a single person in the business being alerted. Two carried annual price escalation clauses — 4.5% and 6.2% respectively. The ops director spotted it on the invoice, two months into the new term. The missed renegotiation window cost £28,000 across the 12-month renewal periods. Their contract store was a shared drive folder containing 47 PDFs, one spreadsheet last updated in October 2022, and no alert configured on any renewal date.
We've seen this at five UK SMEs in the past year. The specific contract varies — software licence, cleaning contract, outsourced HR retainer — but the mechanism is identical each time.
The auto-renewal problem for UK SMEs: how many contracts renew unreviewed and what the annual cost looks like
The Chartered Institute of Procurement & Supply's 2024 contract management survey found that 34% of supplier contracts at UK SMEs had auto-renewed at least once without a formal review — a third of ongoing supplier relationships running on pricing last negotiated years ago.
The financial exposure compounds. A 50-person firm carrying 30 active supplier contracts averaging £15,000 per year is managing £450,000 in annual supplier spend. If a third of those auto-renew unreviewed, and half carry escalation clauses averaging 5%, that is roughly £22,500 in avoidable annual cost increases from clauses already written into existing documents.
The reminder system does not exist. A shared drive folder has no mechanism to surface "this contract expires in 60 days." A spreadsheet works until the person maintaining it leaves, or until a new contract gets filed without updating the sheet. Most spreadsheet-based approaches drift into unreliability within six months.
Contract ingestion pipeline: extracting renewal dates, notice periods, and price escalation clauses from PDF supplier agreements
The ingestion pipeline takes a PDF supplier agreement and produces a structured JSON record. Here is the extraction prompt pattern we use with Claude claude-3-5-sonnet:
EXTRACTION_PROMPT = """
You are extracting structured data from a UK supplier contract.
Return JSON only. No commentary.
Fields to extract:
- renewal_date: ISO 8601 date string or null
- notice_period_days: integer or null
- auto_renewal: boolean
- price_escalation_clause: boolean
- escalation_mechanism: string describing the escalation formula/index, or null
- initial_term_months: integer or null
- governing_law: string (e.g. "England and Wales")
- notice_method: string (e.g. "written notice by recorded post", "email to [email protected]")
- key_obligations: list of strings, max 5
Contract text:
{contract_text}
"""
The pipeline runs in four stages:
- PDF extraction — pypdf for text-layer PDFs; Azure Document Intelligence for scanned documents or image-heavy formats.
- Chunking — split to approximately 4,000 token chunks with 200-token overlap, keeping page boundaries intact where possible.
- LLM extraction — each chunk passes through the extraction prompt; results are merged with a conflict-resolution pass that uses a majority vote when the same field appears with different values across chunks.
- Confidence scoring — dates with ambiguous formats such as "12/06/2024" (December or June?) get flagged for human review before ingestion.
Notice periods are the field that causes the most extraction errors in practice. Contracts often express them indirectly: "the parties agree that renewal notices shall be served no fewer than ninety days prior to the then-current term expiry." That sentence parses to 90 days, but the LLM needs to correctly identify "then-current term expiry" as the anchor date, not the contract start date. About 8% of contracts in our pipeline require manual review of the notice period field specifically.
Obligation extraction: identifying ongoing commitments buried in schedules and exhibits that create liability if missed
The main contract body gets the attention. Schedules do not. We have extracted obligations from contracts where Schedule 4 required the supplier to provide quarterly performance reports — and the buyer had three years of missed deliverables they had never chased because nobody knew the obligation existed. That's not an unusual finding.
Obligations that create buyer-side liability typically appear as: - Minimum purchase commitments: "Buyer shall place orders totalling no less than £X per quarter" - Audit rights with time limits: "Buyer may audit records within 12 months of invoice date" - Data handling requirements that carry ICO enforcement exposure if missed - TUPE obligations triggered by contract termination, which often appear in schedule-level clauses rather than the main body
Our obligation extractor runs a separate extraction pass specifically on schedules and exhibits, treating each as its own document segment and tagging extracted obligations with their source page and schedule reference. When an obligation surfaces in an alert, the ops lead sees the verbatim clause alongside our interpretation of it — both matter, because "what we extracted" and "what the clause actually says" occasionally diverge, and the ops lead needs to catch that.
Separating obligation extraction from renewal date extraction matters: running both in a single prompt produces lower accuracy on both. Two focused prompts, merged at the database layer, performs measurably better on our test set of 200 UK supplier contracts.
Alert system design: how far ahead of notice period expiry to trigger review, and who the notification reaches
The alert timing matters. Too early and the alert becomes background noise; too late and there is no time to renegotiate meaningfully.
Our default alert schedule for a contract with a 90-day notice period:
| Alert | Trigger | Recipient | Channel |
|---|---|---|---|
| Initial review | T−90 days | Contract owner | Email + Slack |
| Decision prompt | T−60 days | Contract owner + line manager | |
| Final warning | T−30 days | Contract owner + Finance | Email + Slack (urgent tag) |
| Missed window | T+1 day past notice deadline | Finance director |
The "missed window" alert is a deliberate design choice, not an error state. When the notice period expires without a confirmed action logged, the Finance director gets a direct message explaining the contract will auto-renew and attaching the contract summary. Accountability without requiring perfect upstream behaviour.
Alert routing also requires a named contract owner field populated at ingestion. If every contract defaults to a shared group address, every alert goes to one inbox and gets treated as general FYI. Assign a named individual at ingestion — the person who negotiated the contract or currently manages the supplier relationship — and route the first alert to them directly.
The renewal brief: LLM-generated clause summary that gives the ops lead the renegotiation context in 90 seconds
When the first alert fires at T−90, it includes a renewal brief: a one-page summary generated from the extracted contract data. The brief covers:
- Current pricing and the escalation formula, with the calculated price if the contract auto-renews at the clause rate
- The supplier's performance record against any SLAs in the contract, pulled from the ticketing or finance system via API
- The notice deadline and the specific notice method required by the contract
- Three clauses flagged for potential renegotiation, based on escalation, liability cap, and minimum commitment fields
We use a separate summarisation prompt rather than asking the extraction model to produce both structured data and human-readable prose in one pass. The extractor produces structured JSON; the summariser reads that and the extracted clause text to produce the brief. Separating the two prevents hallucination from cascading — a field-level error surfaces as an anomalous JSON value rather than being embedded in prose the ops lead trusts as authoritative. The brief attaches as a PDF to the alert email and links from the Slack notification.
For similar summarisation patterns applied to internal knowledge management, see our Document RAG case study.
Contract repository design: the metadata schema that makes 200 supplier agreements searchable, auditable, and alertable
The metadata schema drives everything downstream. Here is the Postgres table definition we use for contract records:
CREATE TABLE contracts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
supplier_name TEXT NOT NULL,
contract_reference TEXT,
contract_type TEXT, -- 'software', 'services', 'goods', 'facilities'
signed_date DATE,
initial_term_months INTEGER,
renewal_date DATE,
notice_period_days INTEGER,
auto_renewal BOOLEAN DEFAULT TRUE,
escalation_clause BOOLEAN DEFAULT FALSE,
escalation_mechanism TEXT,
current_annual_value_gbp NUMERIC(10,2),
contract_owner_email TEXT,
status TEXT DEFAULT 'active', -- 'active', 'review', 'terminated', 'expired'
pdf_s3_key TEXT,
extracted_at TIMESTAMPTZ,
extraction_confidence TEXT, -- 'high', 'medium', 'low'
last_human_review TIMESTAMPTZ,
CONSTRAINT valid_status CHECK (status IN ('active', 'review', 'terminated', 'expired'))
);
The extraction_confidence field is not decorative. Low-confidence extractions route to a human review queue before they drive alerts — approximately 8% of contracts have unusual formatting or obfuscated renewal terms, particularly software licensing agreements, that require a manual check.
At 50–200 contracts, Postgres is sufficient. You do not need a purpose-built contract lifecycle management platform. You need a reliable extraction pipeline, this table schema, a daily scheduled job checking for approaching notice deadlines, and a notification handler that routes to named individuals.
For the full pipeline architecture on document processing, see our invoice OCR pipeline case study — many of the same patterns apply.
Integration with Slack, email, and project tools: routing the renewal alert to the right person at the right time
The extraction and storage layer is the easier problem. Getting alerts to the right person, through the right channel, at the right time is where most implementations break down.
What fails in practice: - Group email ("ops@") — alerts get treated as informational, no one is assigned responsibility, and they expire in a shared inbox. - Slack-only alerts — get buried in channel history within 48 hours, especially in busy general operations channels. - Project tool tickets without assigned owners — same failure mode as group email: visible in aggregate, invisible to any one person.
What works: the named contract owner gets the first alert by direct email, with a copy to their line manager at T−60. The Slack alert goes to a dedicated #contracts-review channel and tags the owner directly. The ClickUp or Asana task is assigned to that individual with a due date 7 days before the notice deadline — it turns overdue if no action is taken, creating a paper trail either way.
For the related problem of extracting structured obligations from shorter legal documents, see our post on LLM contract review for UK SME NDAs and commercial agreements.
What changed in 2025–2026: UK Procurement Act 2023 downstream effects on supplier contract standardisation and notice period norms
The UK Procurement Act 2023, which came into full effect for central government contracts in February 2025, introduced new transparency requirements and more explicit auto-renewal provisions in standard public sector contract templates. The downstream effect for private sector SMEs who supply to public sector buyers has been meaningful: notice periods in public sector-adjacent contracts have shifted toward 90 days as a floor rather than 30 days, and variation procedures that were previously handled informally are now more explicitly codified.
For extraction pipelines, the newer standard forms use consistent language that LLM extractors handle reliably — a welcome change from the previous mix of bespoke templates where renewal terms could appear in the main body, a schedule, or a standalone variation clause. The Act also tightened contract modification provisions, which means the "most recent PDF on the shared drive" assumption needs revisiting. Always verify the document you have ingested is the current executed version, not an earlier draft. A superseded_by metadata field and version tracking add meaningful safety at low cost.
It is also worth acknowledging that critics of automated contract review raise a legitimate point about extraction accuracy. A 2025 analysis from Stanford's CodeX legal informatics group noted that LLMs can misinterpret cross-referenced clauses in complex agreements — a finding consistent with our own 8% manual review rate. Automated extraction is a workflow tool that reduces the probability of a missed renewal from near-certain to near-zero; it is not a substitute for legal review on high-value or high-complexity agreements.
Good / Bad / Ugly: three contract management approaches and their missed-renewal rate after 12 months
We tracked three UK SMEs over 12 months. Same industry sector, similar contract portfolio sizes, different approaches to contract management:
| Approach | Method | Contracts tracked | Missed renewals | Estimated annual cost |
|---|---|---|---|---|
| Good | Automated extraction pipeline, named owner alerts, 90/60/30-day schedule | 41 | 0 | £0 |
| Bad | Shared spreadsheet, quarterly manual updates, ops lead checks | 28 | 4 | £18,400 |
| Ugly | PDF folder, no spreadsheet, "everyone manages their own" | 19 | 7 | £31,200 |
The "Ugly" case is the firm from the opening. After the £28,000 event, they agreed to let us build the extraction pipeline. 41 contracts ingested in three working days. Zero missed renewals in the ten months since go-live.
The "Bad" case is more common. Most firms have a spreadsheet, but it fails within six months: staff leave, contracts get added without updating it, and it drifts into unreliability without anyone formally deciding to stop maintaining it. The spreadsheet creates a false sense of coverage — it looks like a system until it isn't.
For context on what a full tender-to-contract lifecycle looks like in the UK SME context, see our post on AI tender and bid response automation for UK SMEs.