Armand Labs
Builds

I made my contract drawer answer questions

Every operator has a drawer of leases, vendor agreements, and insurance PDFs nobody reads until it's a problem. I made the whole pile answer questions — and open the signed page to prove the number before it tells me anything.

3 min read · by AJ Barragan

Every operator has the same drawer. Leases. Vendor agreements. Insurance binders. Signed PDFs nobody opens until a renewal date sneaks up or someone asks a question you can't answer from memory.

Mine lived across hundreds of files. The answer to "what's the renewal option on this commercial lease" was in there. So was the percentage-rent clause, the CAM share, the insurance limit. I just couldn't get to any of it without opening the right PDF, scrolling to the right page, and squinting at a number I'd then have to trust I read correctly.

So I pointed my OpenClaw (@steipete's agent) at the whole drawer and made it answer questions. Not "summarize this contract." Answer the actual question, with the clause, the page, and the signed document open as proof.

The part most people get wrong: snippets lie

The lazy way to do this is the standard RAG pipeline. Embed every document, retrieve the top few text snippets for a question, hand them to the model, done. That works right up until it doesn't — and on contracts it doesn't.

The number you actually need is usually a fillable form field, a DocuSign overlay, or a clause buried past the ~600-character snippet window. A truncated snippet will confidently hand you the wrong figure. On a signed lease that's not a typo, that's a decision made on bad data.

So this is not a one-shot retrieval pipeline. It is a verification loop. First it finds the likely source. Then it opens the actual file and reads the real page before answering. That last step matters: the number you need is often sitting in a form field, signature overlay, or page detail a shallow text extract misses entirely.

The system prompt has one non-negotiable rule: always open the real file for tax forms, signed leases, and fillable PDFs. Snippets are for finding the document. They are never the final answer on a number or a clause. The model has to open the page and read it before it's allowed to tell me anything.

The stack, since that's the interesting part

And here's the thing nobody tells you: newer is not automatically better. I ran controlled retrieval tests on my own documents before locking the approach. The general benchmark was not the answer for dense legal English and long operating documents. The only test that mattered was whether it found the right signed page on the real corpus.

The index is local and rebuildable. Scanned PDFs get handled on-device. The system keeps source locators, so even when a file is messy, the answer still points back to where it came from instead of pretending the document disappeared.

One detail I had to learn the hard way: indexing can fail quietly if the batching logic is wrong. You think the whole drawer is searchable, but pieces are missing. So the build has to prove what it read, log what it skipped, and make failed files visible instead of hiding them.

What it actually does now

I ask it a question about a commercial lease in plain English. It finds the right signed PDF, opens it, reads the clause off the page, and answers with the verbatim language, the dollar figure, and the page number. Renewal options, percentage rent, CAM, insurance limits — the things that live in the drawer until they cost you.

The drawer didn't get smaller. It started answering.

No SaaS does this, and the reason is structural. The off-the-shelf document tools hand the model a truncated snippet and hope. The whole point here is the verification step — open the real file, read the real page, cite it — which is the difference between a tool that summarizes a contract and one that answers a question about it correctly.

Something in your business work like this should but doesn't?

Tell me what's broken and I'll tell you what I'd build.

Tell us what's hurting →
← All builds