Skip to main content

Form Automation

Form filling is the highest-value thing an in-app agent does — and the place where sloppy metadata hurts most. This guide covers how to make a form the agent can fill correctly on the first try.

1. Register every field

Each input the agent should fill needs a registry entry. Pick the mechanism that fits your codebase (details in Registering elements):

  • Hooks, for precise control:

    const [plate, setPlate] = useState('');
    useAppilotsField('plate', {
    value: plate,
    onChangeText: setPlate,
    fieldType: 'text',
    label: 'License Plate',
    screen: 'VehicleCreate',
    });

    Use useAppilotsToggle for switches and useAppilotsSlider (with min, max, step) for numeric ranges — the executor clamps and snaps slider values for you.

  • Auto-tracking, for existing forms: enable enableAppilotsAutoTracking() and give each TextInput a testID. The testID becomes the field id.

  • HOC factories (createAppilotsInput), if you have a design-system input component — wrap it once and every instance registers itself from its label prop.

2. Describe the form in registerScreen

Registration makes fields operable; screen metadata makes them understandable. Declare labels, types, required flags, and options:

registerScreen({
name: 'VehicleCreate',
title: 'New Vehicle',
description: 'Form to register a new vehicle for the account.',
fields: [
{ id: 'plate', label: 'License Plate', type: 'text', required: true },
{ id: 'model', label: 'Model', type: 'text', required: true },
{
id: 'fuelType',
label: 'Fuel Type',
type: 'select',
required: false,
options: [
{ label: 'Gasoline', value: 'gasoline' },
{ label: 'Electric', value: 'electric' },
],
},
],
actions: [
{
id: 'submitVehicle',
label: 'Save Vehicle',
type: 'submit',
effect: 'write',
riskLevel: 'low',
},
],
});

The CLI also extracts much of this from your JSX statically, but explicit registerScreen metadata is authoritative and survives refactors better. The generated MCP document carries it all to the agent.

3. Fill-and-submit in one step

A form_fill action can carry submitAfterFill: true (see Agent actions), meaning: after all fields are set, press the screen's primary submit button. The submit button is resolved from your registerScreen metadata first — declare an action with type: 'submit' (as above) so resolution is exact rather than heuristic.

If submission is a mutating or risky operation, say so — effect: 'write' at minimum, riskLevel: 'high'/requiresConfirmation: true for anything the user should approve explicitly. The metadata lint flags submit actions missing this.

Practical tips

  • Ids and labels are the interface. The agent matches user intent ("fill in the plate") against your field ids and labels. plate with label "License Plate" works; input3 doesn't.
  • Prefer explicit fieldType. select, date, number, and toggle fields behave differently at fill time — don't make the executor guess.
  • Mark required fields. The agent uses required to know when a form is complete enough to submit.
  • Keep option values enumerable. For select fields, provide options so the agent maps "electric car" to electric instead of free-typing.
  • Test with identifiable values. Ask the agent to "create a vehicle with plate TEST-0001" and confirm exactly that value lands in exactly that field.

Troubleshooting

If the agent fills the wrong field or reports it can't find one, check the resolution chain in Troubleshooting — it's almost always a missing/ambiguous field id or a stale MCP document (appilots sync fixes the latter).