Present forms through a Skill
Ship a declarative form with an extension: this page covers manifest registration and packaging. For a standalone skill that submits to chat, start with the declarative business form guide.
Outcome: Trigger a Skill in chat and see the declared form.
Before you begin: Prepare the files and tools specified on this page. The previous page in the learning path is not automatically a dependency.
On this page
01Choose how to deliver it
An extension provides business operations. A standalone skill can be imported directly and use chat submission without an extension.
Create a standalone business form first02Prerequisites and file locations
First build and install the default scaffold. Create skills/intake/ in the project. This tutorial uses a single-step chat submission without business writes. The declarative-intake sample is a ready-to-run version.
Open the complete runnable sample03Declare the Skill directory
Merge skills at the top level of extension.json. Each entry points to a directory containing SKILL.md, not to a YAML file. Preserve existing operations and contributes.
"skills": ["skills/intake"]04Write the Skill
The description says when the Skill applies; the body explains tool use and user confirmation. amble-form-ref associates it with a packaged template. Its path is relative to the SKILL.md directory, not an arbitrary Markdown link.
---
name: team-intake
description: Collect a team plan with a form in chat.
---
When the user wants to submit a team plan, call forms_list.
Select team-intake from this extension, then call forms_present.
Wait for the user to fill and confirm the form.
Do not claim a business record has been created.
```amble-form-ref
path: intake.yaml
```05Define the form
Save the complete file below. Each name is a stable field identifier; required requires user input. submit.kind: chat sends confirmed content to the current chat and does not create a backend record.
version: 1
id: team-intake
title: Team plan
description: Review your information before sending.
fields:
- name: title
type: text
label: Plan name
required: true
maxLength: 120
- name: people
type: number
label: Participants
integer: true
minimum: 1
maximum: 100
required: true
- name: confirmed
type: checkbox
label: I have checked this information
required: true
submit:
kind: chat
label: Confirm and send06Package the Skill and YAML together
Add this copy statement inside the build.cjs async function after output is created. Preserve the directory structure. Copying only SKILL.md leaves the template undiscoverable. Rebuild, validate, pack and install.
await fs.cp(path.join(root, 'skills'),
path.join(output, 'skills'), { recursive: true });07Verify in chat
Start a conversation and ask: “Use the team-intake form to collect a team plan.” The model must support tools. Expect discovery → host-rendered form → validation of required fields → confirmed content in chat. If absent, inspect installed Skill paths and references, extension enablement/trust, then model tool support.
08Next: connect business operations
forms_list and forms_present are Agent tools, not an importable backend forms API. To persist a business record, use declarative operation submission with idempotency and recovery.
Build a multi-step business formCheck the result and troubleshoot
Trigger a Skill in chat and see the declared form.
Check actual results using this page’s verification steps. For business integrations, inspect UI submission, tool receipts and server records separately.
Open the error reference →