Inspiration

Most forms ask for more personal information than they actually need. I wanted to test a simple idea: could an agent help finish a form without getting a free pass to read an entire profile?

That became 5 of 23. The name is literal. The demo profile has 23 fields, but the sample application only needs five of them and an over-18 check. The point is not to make form filling faster at any cost. It is to make the boundary visible: what is needed, why it is needed, and who gets to release it.

What it does

The agent can inspect the application requirements and see what is missing without receiving the raw profile. For the age requirement, it calls an allow-listed is_adult check and gets a boolean result instead of a date of birth.

It then requests the five fields required by the form. The request appears in the page, but it does not grant access. I approve or reject each field in the interface. Once the approved values have been applied, the form reaches 6/6 requirements and the temporary write capability disappears.

There is still no submit tool. Final review remains a separate UI action. If that review is approved, the page exposes a local packet marked submitted: false. Revoking city removes the value, clears the reviewed copy and makes the old tool handle fail because it belongs to an earlier consent version.

Everything in the demo is synthetic. It does not send an application anywhere.

Why WebMCP

This flow depends on the agent and the person sharing the live state of the same page: requirements, missing answers, approved scope, consent version and review status.

WebMCP gives the agent a semantic tool surface instead of making it scrape buttons and labels. More importantly, the page can register a capability only while that capability is valid. The available tools change with consent, and the callbacks check the consent version again when they run.

That is why this is not a chat box added to a form. The agent works out what the task needs and carries out the approved part. The person controls disclosure and review. The page enforces the boundary.

How I built it

I built the project in React and TypeScript with Vinext and Vite. The page registers its tools at the top level with document.modelContext.registerTool(...) so a compatible browser can discover them directly.

A deterministic in-browser state engine owns the synthetic profile, form progress, disclosure requests, approvals, consent versions, receipts and reviewed packet. The normal interface and the WebMCP callbacks use that same store. The schemas use narrow enums, reject extra properties and bind dynamic writes to the current consent version.

The prototype has no application API, database, login, analytics, payment flow or external submission handler. That kept the build focused on the consent model rather than infrastructure. The source code is public under the MIT License.

Challenges I ran into

The hard part was not the happy path. It was keeping six states separate and understandable: request, approval, application, review, revocation and stale authority.

Dynamic tools also needed two layers of protection. A tool has to disappear when its authority disappears, but its callback must still reject an old handle that was fetched before the change. I also had to keep the proof honest: a mocked test is useful, but it is not the same thing as a real browser discovering and invoking the final page.

What I am proud of

  • In the local end-to-end browser run, the available tool count moved 8 → 9 → 8 → 9 → 8 as consent and review changed.
  • The minimum path completed 6/6 requirements using 5 of 23 fields and one boolean age check. The other 18 fields stayed sealed in the tool/UI flow.
  • Revoking city returned the form to 5/6, left 4 of 23 fields disclosed, removed the reviewed-packet tool and rejected its old handle.
  • The deterministic suite passed 14/14 tests, along with typecheck, lint, the production build and the recorded npm audit.

The demo data lives in the public client bundle, so “sealed” describes the exercised interface and tool behavior, not source-code secrecy. This is a synthetic prototype, not a claim of production-grade security or measured user impact.

What I learned

Tool discovery is only the start of an agent-native product. The more interesting question is when a capability should exist, how small its scope can be, and what should happen to authority the moment consent changes.

I also learned that privacy needs visible negative evidence. A good demo should show not only what the agent can do, but what it cannot read, cannot approve and can no longer use after revocation.

What's next

I would add property-based tests around redaction and stale versions, a small policy language for purpose and expiry, and a proper accessibility review of the consent controls. The next product question is whether people clearly understand the difference between a request, a grant and a reviewed local packet.

Built With

Share this project:

Updates

Submission history