Extracting Terms From a Non-Solicitation Clause
9 min read · updated August 11, 2026
A non-solicitation clause typically restrains two different things — approaching the other side’s employees, and approaching its customers — in one sentence, and the two are reached by different law. An extraction that returns one boolean and one duration has lost the document.
Two restrictions, one sentence
A typical clause reads: neither party shall, during the term and for twelve months thereafter, directly or indirectly solicit for employment any employee of the other party, or solicit or accept business from any customer of the other party with whom it had contact during the term.
That is at least two restrictions and often three. The objects are different classes of person — employees, customers, sometimes suppliers or contractors. The prohibited acts are different: solicit is an approach, accept covers the case where the customer approached you, and a no-hire formulation prohibits hiring at all, whoever initiated it. Those are three materially different obligations and drafters mix them freely in one list.
They also live under different bodies of law. Restrictions on hiring employees and restrictions on dealing with customers are assessed differently across jurisdictions, and in some places the rules for employment-related restraints have moved recently while commercial non-solicits have not. That is not the concern of an extraction pipeline — and this page does not attempt to say what is enforceable where — but it is precisely why the schema must keep the limbs apart. A downstream question of the form “which of our contracts restrict hiring, as opposed to restricting selling?” cannot be answered from a single non_solicit: true field, and re-extracting a corpus because a field was too coarse is the expensive kind of rework.
One row per restricted class
Emit an array of restrictions, not an object — the nested-versus-flat schema question in its usual form. Each element carries its own scope:
{
"restrictions": [
{
"restricted_class": "employees",
"prohibited_acts": ["solicit_for_employment"],
"bound_party": "both",
"duration_months": 12,
"duration_start_trigger": "termination",
"class_qualifier": "any employee of the other party",
"carve_outs": ["general_advertisement"],
"indirect_included": true,
"verbatim": "..."
},
{
"restricted_class": "customers",
"prohibited_acts": ["solicit", "accept_business"],
"bound_party": "both",
"duration_months": 12,
"duration_start_trigger": "termination",
"class_qualifier": "with whom it had contact during the Term",
"carve_outs": [],
"indirect_included": true,
"verbatim": "..."
}
]
}Three fields there do disproportionate work. class_qualifier holds the words that narrow the protected class — “with whom it had contact”, “employed at any time during the twelve months preceding”, “introduced by the Disclosing Party” — and the difference between “any customer” and “any customer you personally served” is most of the practical scope of the clause. carve_outs holds the exceptions, of which the most common by far is the general-advertisement carve-out: a published job advertisement not targeted at the other party’s staff is usually excluded, and a clause without that exception is meaningfully broader than one with it. And bound_party records whether the restriction is mutual or one-way, which the sentence signals only through the subject — “neither party” versus “the Supplier shall not” — and which reverses the commercial reading of the clause.
Which modifier binds to which limb
The hard parsing question is scope. In “shall not, for twelve months following termination, solicit any employee or accept business from any customer”, does the twelve months attach to both limbs? Here, yes: the duration is stated before the verb list and governs it. But drafters routinely produce the other shape — “shall not solicit any employee, or for a period of twenty-four months accept business from any customer” — where a duration appears inside the second limb and the first limb has its own, or none.
A model asked for a flat list of fields will happily broadcast one duration across every limb, because that is the more common pattern and the output is fluent either way. Two things reduce it. First, ask for the verbatim span of each limb before asking for its fields: a limb whose own text contains no duration and whose duration field is populated is a broadcast, and you can detect that mechanically by checking whether the duration’s surface form appears in the span or in the shared preamble. Second, extract the preamble — the words before the verb list — as its own field, so that “inherited from preamble” and “stated in this limb” are distinguishable rather than both arriving as 12.
The same discipline — capture the span, then derive the field from the span — is what makes a liability cap expressed as a formula tractable. Clause extraction is generally two passes: locate and delimit, then interpret what you delimited.
The operative words are defined elsewhere
Commercial contracts capitalise defined terms, and the definitions sit in a schedule twenty pages away. A clause restricting solicitation of any “Restricted Person” or any “Customer” is not self-contained: the definition might limit Customer to entities that purchased in the preceding twelve months, or extend it to prospects in an active sales process. Some agreements go further and define “Solicit” itself, occasionally in a way that expressly includes or excludes responding to an approach.
So the extraction needs a resolution step: detect capitalised terms inside the clause span, look each up in the definitions section, and attach the resolved text to the restriction. Where a term is used but not defined anywhere in the document — which happens, usually because the clause was pasted from another agreement — that is a real finding worth surfacing, not a null to swallow — how a missing required field is handled is the general form of that choice. Retrieving the right definition across a long document is a retrieval problem before it is a reading one; the published page on separating extraction from the reasoning done on top of it covers why doing both in one prompt tends to degrade both.
Where it goes wrong
- The survival sentence is in a different clause. “Sections 9, 11 and 14 survive termination” may be the only thing that makes the restriction outlast the term. Extracting the non-solicit without checking the survival list can produce a duration that is right and an end date that is wrong.
- Severability rewrites the clause conditionally. A sentence stating that if the restriction is held excessive it applies for the longest permissible period is not a duration, and a model asked for “the duration” sometimes returns that sentence. Keep it as a separate boolean,
has_reduction_clause. - Numbers written twice. “twelve (12) months” is redundant on purpose, and about as often as you would expect, the two disagree. Extract both surface forms and flag the mismatch rather than picking one.
- The clause continues after a page break. A limb whose carve-out sits at the top of the next page loses the carve-out if the clause span was cut at the page boundary. Delimit clauses by numbering, not by page.
- Governing law is a field of this clause too. Not because you will opine on it, but because the same words mean different things in different places, and a corpus-level answer without a governing-law column cannot be filtered sensibly.