- an observable store holding the collected
valuesand whether the form wassubmitted— its completeness (missing,complete) is computed on read withderiveFormStatus, never stored - an
update_<name>function the agent calls to record values (it can call it many times, with any subset of fields) - a context entry sent with every message so the agent always knows the current values and what’s left
- an optional
submit_<name>function that sends the completed form
Create a Collector
name becomes the function names (update_order, submit_order), so it must contain only letters, numbers, underscores, or hyphens, and be at most 40 characters.
Define the form in the backend
Instead of writing the schema in your page, you can store it once in AGO and fetch it by name. The form then has a single source of truth: change a field in the admin interface and every page picks it up on next load, with no redeploy. Create the definition in the admin interface (its name, description, schema, and submit target), then reference it by name:handler, which can’t be stored on the server:
examples/simple-html/credit-form-backend.html.
React
useFormCollector registers the collector on mount, removes it on unmount, and returns the live state.
schema and submit object stable across renders (declare them outside the component or memoize them) so an inline handler isn’t captured stale.
To use a backend-defined form instead, pass only its name — the hook fetches the definition and exposes loading while it does:
State
The store holds only the canonical state:
Completeness is derived from the values, not stored. Compute it with
deriveFormStatus(schema, values) — or, in React, read it straight off order.state, which already includes it:
Restoring state after a reload
When a visitor reloads the page and you reopen their previous conversation, the collector rebuilds itself from the values the agent already recorded. Loading a conversation replays itsupdate_<name> and submit_<name> calls onto the store, so the collected values and the submitted flag come back exactly as they were (and missing/complete derive from them), and the visitor doesn’t have to start over.
This happens on its own once the collector is installed (with install or useFormCollector): loading a conversation restores any matching form. Loading a conversation that never used the form leaves it at its initial values.
If you build the conversation loading yourself, call order.hydrate(toolCalls) with the tool calls of the loaded messages to restore the state manually.
Submitting
Choose how the completed form is sent with thesubmit option.
- From the browser
- From the server
The browser sends the values to a URL you control, using the page’s existing session. Use this when the endpoint is your own API and needs no server-only secret.
submit_<name> only submits once every required field is present. If fields are still missing it returns them instead, so the agent asks for the rest before trying again. You can also submit from your own UI by calling order.submit().
Submission history
Every form submitted through the server ({ via: "backend" }) is kept in a history you can review in the admin interface. Open Form Collectors and click Form Submissions to see, for each submission:
- the date and time it was sent
- the form it belongs to
- whether it completed or failed
- the user who submitted it
- a preview of the submitted values
{ via: "client" }) never reach the server, so they don’t appear here.
Complete Example
A contact-intake form in plain JavaScript. The agent collects the prospect’s details through the conversation, the summary updates live, and the form submits once it’s complete.examples/simple-html/contact-form.html.
Related Documentation
- Client Functions — the lower-level browser functions this builds on
- JavaScript SDK — full SDK setup and usage
- SDK API Reference — REST API endpoints
