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. admin is nobody but you, which is right for an RSVP list. own shows a visitor only their own rows, which is right for a tracker. contributors and public show them everybody's, and public in 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. single answers 409 already_submitted on a second submission, which is what stops one guest appearing twice.
  • writes — whether a visitor may change a row that exists. Nearly always append-only. Erasure works either way.
  • retentionDays — how long a row is kept. A finite number is required for anything classified sensitive, and expired rows are pruned rather than merely hidden.
  • fields — the shape of one submission, each with a type and a pii classification: none, contact (an email, a handle, a phone number) or sensitive. pii has 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 MCPsuper_get_responses for one artifact, super_get_collection_responses for a group that shares a collection label, read over one window.
  • A visitor, from inside the page, seeing only what the read policy 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.