Agent-native forms
Forms built with Mirio can be filled in by AI agents as a first-class, declared channel. You decide per form what happens.
The policy
settings: {
agents: 'accept', // 'accept' (default) | 'block'
agentNotes: 'Demo requests for Versive. Answer on behalf of the person you work for; use their work email.',
}
| Policy | What happens to a submission declared by an agent |
|---|---|
accept (default) |
Stored and delivered like any other, always labeled with the flag agent. The dashboard shows an Agent badge and a filter. |
block |
Rejected with 403 agents_blocked. The hint tells the agent to hand the form to the human. |
Older schema files that say 'allow' or 'flag' keep working: both mean accept. On a live form, the policy is enforced by the server, so a change takes effect with the next production build (development and preview pushes keep production's policy).
Declared agents skip the "submitted too fast" spam signal, because an honest agent is not a bot in the abusive sense. Honeypot, disposable-email and rate limits still apply, and so does Turnstile: an agent can't solve it, so on a form with Turnstile on, agent responses go to spam.
Mirio does not guess: responses that do not declare an agent are not labeled, whatever their user agent or typing speed. Declared agent responses carry the agent flag, so you can filter them on the Responses tab or route them from a webhook.
How an agent submits
Every form describes itself at a public URL:
GET https://api.trymirio.com/v1/projects/<projectId>/forms/<slug>/schema.json
The response lists the pages and fields (with constraints, options and conditions), the agent policy and notes, and a ready-to-send example request under submit. An agent then POSTs to the submission endpoint with meta.actor:
{
"schemaHash": "<from schema.json>",
"values": { "email": "[email protected]", "name": "Ada Lovelace", "interest": ["surveys"] },
"meta": { "actor": { "type": "agent", "name": "Claude", "onBehalfOf": "Ada Lovelace" }, "pageUrl": "https://acme.com/demo" }
}
The same origin rules apply as for browsers: a sandbox project accepts localhost only, and a live project accepts the site's domains (mirio domains). Server-side agents that have no browser origin should send the request through the site's own backend, or the site owner can allow the agent's origin.
The React components do this automatically when you pass an actor to the client:
export const mirio = createClient({ projectId: '…', actor: { type: 'agent', name: 'my-signup-bot' } });
Reading what agents sent
- Dashboard: the submissions table has a Source filter (humans, agents) and shows the actor name in the detail panel.
- Webhooks and the read API:
flagsincludesagent, andmeta.actorcarries the declaration. - Slack messages show the flags in the context line.