Demos / Form copilot · Plinth
Add a new employee
An HR admin screen with six sections and a dozen rules. Tell the copilot about the new hire and it fills the form field by field, catches a salary outside its pay band, explains it, and leaves Save to you.
The copilot fills a long HR form alongside the admin, one field at a time, and the admin still presses Save.
One tool, one field
set_field is the only way the agent changes the form.
src/demos/admin-form/pageTools.ts
{
name: 'set_field',
description:
'Set one field on the Add a new employee form and get its validation result back. ' +
…
jsonSchema: {
…
required: ['section', 'field', 'value'],The form answers back
A readable value is set even when it breaks a rule, and the rule comes back to the agent.
src/demos/admin-form/pageTools.ts
const read = normalize(def, args.value)
if (!read.ok) return `Not set: ${read.reason}`
…
const problem = validateField(def.key, next, today)
…
return [
`Set ${def.key} to ${shown}.`,
problem ? `Problem: ${problem}` : 'OK.',
…
]Where the form stands
Every turn carries what is filled, what is wrong and whether Save is ready.
src/demos/admin-form/form.ts
return {
page: 'Plinth admin, Add a new employee, for Fernway Studio',
completion: `${s.percent}% (${s.done} of ${s.total} required fields done)`,
errors: s.problems.length ? s.problems.map((p) => `${p.key}: ${p.message}`).join(' | ') : 'none',
save: saved ? 'saved by the admin' : s.canSave ? 'enabled: the admin can press Save' : 'disabled until every required field is filled and has no problem',
…
}Save stays with the admin
No tool saves. The button opens only when the form itself says it is complete.
src/demos/admin-form/index.tsx
<button type="button" data-save disabled={!canSave} onClick={onSave} className="pl-save flex-1 rounded-md px-3 py-2 text-[13px] font-semibold">