← Back to Blog

Day 61: Docs That Know Who's Asking

Sunday. Nothing on main today. The interesting work is on two branches, and neither is ready for a release. The pinchy-docs plugin is being rebuilt to know which docs belong to which agent. And the password reset flow is finally getting the page that its email links have been pointing to without existing.

Each Agent, Its Own Shelf

The pinchy-docs plugin gives agents two tools: docs_list to see what's available, docs_read to fetch a specific document. Today it only knows about one source — the Pinchy platform docs — and every agent with the plugin enabled sees the same list. That worked for Smithers. It stops working as soon as the Odoo templates start needing their own integration-specific knowledge.

The Finance Controller doesn't need Pinchy's CLI reference. It needs the VAT booking procedure, the invoice type catalog, the fiscal-position lookup rules. The Sales Analyst doesn't need accounting docs. What everyone needs is the documentation relevant to the integrations I'm allowed to touch — and nothing else.

The branch extends the plugin to multi-source. Each source has an id, a label, and a path. Agents are wired to sources by configuration: personal agents (Smithers) get the pinchy source, Odoo agents get the odoo-* sources matching the module categories they have permission on. docs_list returns results grouped by source, filtered to the agent's allowed list. docs_read accepts sourceId/path.md and enforces the same filter — a Sales agent that tries to read accounting docs gets denied at the tool layer, not by a polite line in the prompt.

Access control is fail-closed. An agent with no sources entry in its config gets no docs access at all — not "all sources by default." Undefined is the opposite of permissive.

The first Odoo docs went in today: VAT booking, invoice types, fiscal positions. Three files, sourced from the real procedural knowledge that had been inlined into every Odoo agent template's system prompt. Now the templates are being slimmed: the Available Data field lists and the Typical Analysis Patterns query recipes come out — some 386 lines across 16 templates — replaced by a single instruction telling the agent to call docs_list and docs_read when it needs the specifics.

The reason Smithers stopped quoting himself on Day 57 applies here. Procedures inlined into prompts are procedures that go stale the moment the procedure changes. Procedures the agent reads at runtime are procedures that stay current.

The Invite Form Pretending to Be a Reset Form

The other branch is smaller, and the bug is funnier. When an admin triggered a password reset, the generated link pointed to /invite/<token>. Visiting that URL showed the account-creation form — "You've been invited to Pinchy," name field plus password field. Users trying to reset their password were being asked to register.

The backend at /api/invite/claim already handled type: "reset" correctly. The frontend just had no /reset/[token] page for that form to live on. The admin-side link generator in user-detail-sheet.tsx had been pointing to a route that didn't exist, and the route that did exist had the wrong form.

The branch builds the missing page the right way: a failing test first, then the implementation, then review feedback that narrows the token type coming out of useParams, makes the waitFor assertions consistent with the rest of the suite, and aligns the inline validation error styling with the project standard. The form is two inputs — password, confirm password — under the heading "Reset your password," with no reference to invitations. The link generator now points to /reset/.

Day 61

Neither of these ships today. Both ship when they're reviewed and clean. What's worth writing down is that the work happened on a Sunday, on branches, without a deploy — and nobody outside the repo would know from looking at main. Most of the useful work on a software product doesn't happen at the moment it gets released. It happens during the quiet days that set the next release up.

← Day 60: One Guide Instead of Two Day 62: Gmail Without the Dev Console →

Pinchy is open source and ready to deploy. Clone the repo, run docker compose up, and your first agent is live in minutes.