Skip to content

Part 3 of 7 · Offer letter generator series ~5 min read

How a term finds its clause

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.

How confirmed terms are matched to approved clausesA vertical chain of five steps entered by a box labelled Nine confirmed terms, from Part 2. Step one picks the base template from the employment basis, choosing between salaried, hourly and fixed-term. Step two matches each term to an exact option in the clause library of approved wording; an unmatched term exits to No clause exists, which stops and asks for one. Step three fills the variables, being a name, a number and a date. Step four orders the clauses by the template rather than by the order the terms were captured. Step five assembles the letter and diffs it against standard. A note says every path either finds approved wording or stops, and there is no third option.AWS ACCOUNTNine confirmed termsfrom Part 2Pick the base templatefrom the basisTemplatessalaried, hourly, fixedMatch each termto an exact optionClause libraryapproved wordingNo clause existsstop, and ask for oneunmatchedFill the variablesname, number, dateOrder by the templatenot by capture orderAssembleand diff against standardEvery path either finds approved wording or stops. There is no third option.
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

VariableExampleWhy it is safe
A nameKwame OseiSubstituting a name cannot change what a clause means
A number38,000Formatted, never rounded or interpreted
A date28 August 2026Formatted 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.

Why clause versions are recorded on every sent offerA horizontal row of five boxes. Clause version two: approved in January 2026. Letter sent: records version two. Clause version three: approved in June 2026. The letter: still says version two. Answerable: the question what did we agree can be answered exactly. A note says without this, re-rendering an old offer would silently apply today's wording.WHY CLAUSES CARRY VERSIONSClause v2approved Jan 2026Letter sentrecords v2Clause v3approved Jun 2026The letterstill says v2Answerablewhat did we agree?Without this, re-rendering an old offer would silently apply today's wording.
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.

All posts