Clause matching sounds like the interesting part and is deliberately the dullest. Everything here is a lookup, and the design work went into shaping the library so that a lookup is sufficient.
Key takeaways
The library holds options, not ranges. Three months and six months are two clauses.
Only three kinds of variable are ever substituted: a name, a number and a date.
A clause carries its own version, and a sent letter records which versions it used.
Ordering is fixed by the template, not by the order terms were captured.
A clause that has never been used is flagged annually, because unused clauses go stale.
Options, not ranges
The instinct when building a clause library is to write one probation clause with the length as a variable. It is tempting, it is fewer clauses, and it lets somebody type “seven weeks” and get a letter.
The alternative is to hold a small set of exact options — no probation, three months, six months — each as its own approved clause. It is slightly more to maintain and it removes an entire category of problem: nobody can produce a letter with a probation length that has never been approved, because there is no clause for it. A seven-week probation stops the draft, which is exactly what should happen the first time anybody agrees one.
Fig 1. How terms become a letter. The single exit is the whole safety story: an unmatched term cannot produce improvised wording because there is no code path that writes any.
Database
Machine learning
Security & identity
Management
Analytics
Front-end & mobile
The three safe variables
Variable
Example
Why it is safe
A name
Kwame Osei
Substituting a name cannot change what a clause means
A number
38,000
Formatted, never rounded or interpreted
A date
28 August 2026
Formatted long-hand, never computed from another date
That is the complete list. Anything else — a duration, a condition, a job description — is part of the clause rather than a variable in it, which means changing it means choosing a different approved clause. This is more restrictive than most templating systems and it is the restriction that makes the output trustworthy.
Numbers are formatted, not interpreted
A salary of 38000 becomes “£38,000” and never “£38,000 per annum (thirty-eight thousand pounds)” unless the approved clause says so. An hourly rate of 14.5 becomes “£14.50” and never “£14.50 per hour, approximately £28,275 per year”, because that second figure is a calculation with assumptions in it and it does not belong in a letter unless somebody approved the assumption.
Clause versions
Contract wording changes: a solicitor revises a notice clause, legislation moves, the business changes its probation policy. A sent letter has to record which version of each clause it used, because the letter that went out in March is the contract, not whatever the library says today.
Fig 2. Why every clause carries a version and every sent letter records the ones it used. Re-rendering an old offer from today’s library would produce a document that never existed.
App integration
Management
Analytics
Unused clauses
A clause nobody has used in a year is either obsolete or is quietly wrong in a way that makes people avoid it, and both are worth knowing. The system lists unused clauses once a year alongside the ones used most, which is a five-minute review that keeps the library from accumulating dead wording nobody dares delete.
Next: what happens when a term has no clause at all.