Skip to main content
A supplier sends a master services agreement. Your side has a playbook: what you accept, what you push back on and with what wording, and what you never sign. Someone has to read every clause against it, write the redlines, and decide what to hold and what to concede, before the lawyer’s hour. You want every clause covered, not the ones a tired reader noticed. You want redlines in the wording the playbook allows, no further, and a negotiating note that says what a walk-away is. You want the lawyer to decide what is sent, and nothing sent without them. Obversa makes the playbook the brief and the lawyer a step. One model maps every clause to the rule it meets or breaks, writes the redlines in the playbook’s wording, and writes the negotiating note. A model from another family checks each redline against the playbook and fails the set when a clause is missing or a redline goes further than its rule. A judge, Jev, says when another round on the redlines is worth it. Then the run waits for the lawyer. This file is a four-stage team: clauses, redline, positions, negotiate.

Run it

Set the project up as Installation describes, put briefs/playbook.md, contracts/msa.md and judge.json from examples/use-cases/business/ beside the file, sign in to Claude Code and Codex, and run it. Without JUDGE=jev the judge replays the answers in judge.json; with it, and a TypeSafe endpoint and key in the environment, the judge is Jev:
Terminal
When the run reaches the lawyer, it waits and prints a page to answer on. The lawyer answers there, and the run finishes. Keep the process running until then: if it stops, the next run starts again from the first stage. Every event prints as one line as it happens, and the outcome prints last as JSON. The output below is the proof’s offline run, with scripted seats standing in for the models, a recorded judge, and the proof answering as the lawyer on the page, so the words are the script’s and the shape is the run’s:
Output, from the offline proof
Seven clauses mapped, two rounds of redlines, two answers from the judge. The first set of redlines left out the two clauses the playbook never signs; the checker tagged each a block, the judge acted on both, and the set went back. The second set covered every clause and drew one taste note, and the judge said the redlines hold. The negotiating note passed its check first time. The run waited at negotiate with the redlines and the positions in review/, and the lawyer’s yes on the page finished it. A no goes to redline with the lawyer’s note as the finding.

The file

Write every rule you want applied in briefs/playbook.md. Everything a seat knows about what’s acceptable comes from that file, and only the rules written there are applied. files: ["contracts/msa.md"] in the brief’s front matter names the contract as a workspace file: every seat knows it exists, and the review seat may not write it.
examples/use-cases/business/contract-playbook.ts (excerpt)
The clause list has no reviewer, so only its own seat judges whether every clause is on it. The redlines and the negotiating note are each checked by the Codex seat. On the redlines, refine: judge(judgeSeat) asks the judge whether another round is worth it each time the checker fails the set, and the rounds end when the judge stops them or the checker passes the set. The negotiating note keeps a plain count of three, so the two shapes sit side by side:
examples/use-cases/business/contract-playbook.ts (excerpt)
The “done when” sentences are each stage’s gate. The package doesn’t check them itself; it checks what each stage declares. A file in writes that’s missing or empty fails the stage, a reviewed stage passes only when its reviewer accepts, and a person stage waits until the person answers.
examples/use-cases/business/contract-playbook.ts

The team’s shape

When the loop stops

When the checker fails the set, the judge reads the use case from the brief, the findings and every round so far, and says whether another round is worth it. A finding the checker tags block, here a never-sign clause with no redline, goes to the judge too. The judge skips a block only when the case it names is outside how the work is really used, or when the same class of finding keeps returning after it was answered. The loop goes round again on continue and stops when the judge chooses a reason to stop. With no cap, a run ends when the judge stops it or the review passes. To bound the rounds as well, pass judge(judgeSeat, { cap: 3 }): it allows three refinements, the judge reads the review of the last draft too, and the run fails unless it lets the redlines stand. The judge’s recorded answer for the offline run is in judge.json. A judge stops the loop has the questions and the rule.

Next steps