QR codes for people. Managed by your AI agent.
Your agent creates the codes, updates them after they are printed, and hands control back to you whenever you want it. Reading what is behind a code is a separate permission it does not hold by default — and every read you do grant is audited, capped, and yours to revoke.
// 01 · what your agent actually does
Three jobs, and you are in charge of all three
Create and share
You give your agent the content through an approved upload. It creates a gated code and asks for a recipient to be given access. The server does the sending. Your agent gets a code id and a delivery status — never the link a recipient will use.
Update after printing
The destination changed and the code is already on a thousand boxes. Your agent repoints it. The printed code stays valid, the gate stays in place, and if you edited the same code in the dashboard first, the agent's older edit is refused rather than silently winning.
Take over
You see which agent changed what, edit the same code yourself, and revoke that credential. Its next call is refused — including work it had already queued. Your own access is untouched.
// 02 · what enforces each promise
Every claim above, and the thing that makes it true
A security claim with no named mechanism is an invitation to take it on faith. These are the controls, not the aspirations.
| Claim | What enforces it |
|---|---|
| Reading the content behind a code is its own permission, off by default | Payloads are encrypted at rest under a per-workspace key and sealed to the code and workspace they belong to. Exactly one endpoint and one tool decrypt one, both behind a separate qr:content:read scope that is deliberately excluded from the older read/write expansion -- so a key that can list your codes cannot read them until you say so. Every such read writes an audit row and counts against an hourly cap per credential. Every other response marks content withheld rather than omitting it silently. |
| An agent cannot make a code public | Public mode and any move to a weaker gate are refused for machine credentials on every write path, including bulk. A person can make that change in the dashboard. |
| An agent cannot mint itself more authority | API keys, billing, team membership and the audit trail have no agent tool at any approval level. Delegated tokens are constrained to the intersection of what their parent key still holds, re-checked at use. |
| You can see which agent did what | Every machine action writes an audit row naming the credential and its label, with the request, job and approval ids that join it into one trail. |
| Revoking an agent stops it immediately | Authority is re-checked at use, not at issue -- including per item inside a running bulk job, which stops where it is rather than finishing the batch. |
| A printed code stays valid when its destination changes | The URL is opaque and permanent. Updating a code changes what it resolves to, never the code itself, and the gate is preserved across the change. |
| An agent's stale edit cannot overwrite yours | Every agent write is conditional on the revision it read. If you edited the code in between, the write is refused with an explicit conflict rather than winning. |
| A shared link never reaches your agent | Delivery is server-side: the agent asks for a recipient to be given access and the server sends it. The agent receives delivery status, never the link. |
// 03 · what this does not protect
The parts we do not claim
Read this section before you point an agent at a workspace. A boundary you find out about later is worse than one that was on the page.
Metadata your agent can read, it can copy
Titles, folder names, scan counts and analytics are visible to a credential with the right scope. Nothing stops an agent writing what it legitimately read into somewhere you did not intend. Scope the credential to what the job needs.
Content your agent is scoped to read, it can copy
The encryption protects the payload from us and from a database dump. It does not protect it from a recipient you authorised, nor from a credential you granted qr:content:read -- and a payload read into a model's context has left our controls. Grant that scope to the jobs that need it and no others; the audit trail says which credential read what, and when.
We do not police where a destination leads
Destinations are screened against reputation providers where they are configured, and a screening outage is reported rather than hidden. That is a filter, not a guarantee.
A prompt-injected agent is still your agent
Content the product returns is marked as untrusted and the tools refuse the actions that matter most. Within its granted scope, an agent that has been talked into something is acting with your authority -- which is why revocation is immediate and the audit trail names the credential.
// 04 · connecting an agent
An agent-native QR platform, not a plugin
The machine surface is the product, not a wrapper over the dashboard. Connect a hosted client and authorise it in a browser, or hand a key to something you wrote yourself — both arrive at the same controls.
A key for your own client
Create a scoped API key in the dashboard and give it to your agent. Scopes are per action, and a sandbox key lets you rehearse against separate data whose mail and webhooks are captured rather than sent.
A browser consent for a hosted one
A hosted client sends you to a consent screen that names it and lists exactly what it is asking for. You approve once; asking for more asks you again.
Written for a model to execute
The rules of engagement — what is refused, what each failure means and when to stop — are published as a short document your agent reads before its first call.
One door to content, and you hold the key
Metadata and lifecycle come with an ordinary read scope. Content has exactly one endpoint and one tool, both behind a scope of their own that no legacy key inherits, audited per call and capped per hour.
Machine-readable: /agents.md for the rules of engagement, /llms.txt for everything else an agent should read first.