Collecting data
An artifact can store what a visitor types, in a database that comes with it. One field on the deploy switches it on.
An artifact is a static bundle, and that used to be the end of the sentence. It is not: a page published here can collect what a visitor types into it — a survey answer, an RSVP, a tracker entry, an order — and the agent that built the page reads the rows back with its own key. The database comes with the artifact. There is nothing to provision, host or sign up for.
It is off until the deploy declares a policy. That is the one thing worth knowing before anything else, because an artifact without a policy renders its form, runs its submit handler, and drops every answer — and nothing about the page looks wrong while it does. The first sign is an empty read a week later.
What to ask your agent for
Ask for the thing you want. "A page to collect RSVPs for my son's birthday — kid's name, parent's name, and whether they're coming." "A sign-up sheet for the Saturday shift." "Ask the team how the retro went and show me the answers."
Your agent does not need to be told about policies, tokens or endpoints. All of it is in the skill it re-fetches before every artifact, and the craft of it is in the Magic Prompt playbook for the kind it settled on.
If an agent tells you this platform cannot store form responses, it is wrong and its
copy of the skill is stale. Ask it to re-fetch SKILL.md from the platform that issued
its key and read the Collecting what a visitor types section. The answer is never a
mailto: link, a WhatsApp message, or a Google Form — each of those hands your data to
somebody else and loses the read-back that is the point of collecting it here.
What a policy declares
Four decisions and a list of fields, sent as policy alongside metadata and files on
the deploy. The deploy contract has the wire format; what the
decisions mean:
read— who may read a row back from inside the page.adminis nobody but you, which is right for an RSVP list.ownshows a visitor only their own rows, which is right for a tracker.contributorsandpublicshow them everybody's, andpublicin particular is a decision to make rather than a default to inherit. None of these limit you: your key reads every row regardless.perUser— one row per person, or many.singleanswers409 already_submittedon a second submission, which is what stops one guest appearing twice.writes— whether a visitor may change a row that exists. Nearly alwaysappend-only. Erasure works either way.retentionDays— how long a row is kept. A finite number is required for anything classifiedsensitive, and expired rows are pruned rather than merely hidden.fields— the shape of one submission, each with a type and apiiclassification:none,contact(an email, a handle, a phone number) orsensitive.piihas no default, on purpose. A field's type may never change between versions.
The deploy response says what was actually accepted, including any field the platform
reclassified on its own — an unconstrained free-text box declared pii: none is stored and
masked as contact whatever the declaration said, because that is the field most likely to
end up holding an email address.
Reading it back
Three ways, all reading the same rows:
- The dashboard, at
/data. Every artifact of yours that collects, what it has, and an export. - Your agent, over MCP —
super_get_responsesfor one artifact,super_get_collection_responsesfor a group that shares acollectionlabel, read over one window. - A visitor, from inside the page, seeing only what the
readpolicy allows.
A visitor erases their own rows themselves. Deleting the artifact closes the data with it: the tombstone is written before a single byte is removed, so a write token minted seconds earlier cannot land afterwards.
What this is not
It is not analytics. Analytics is what the platform observes about a request — views, devices, errors. Collected data is what the page asked for and the visitor chose to give. They are stored, read and erased separately, and neither answers the other's question.
It is not a database you get to query freely. One submission is one flat row of declared fields, capped in size and in count. That constraint is what makes the rows legible to the next version, to the dashboard and to an agent that did not write them.