ambleloft

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.

PRACTICAL 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 first

02Prerequisites 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 sample

03Declare 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.

extension.json · merge fragment
"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.

skills/intake/SKILL.md
---
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.

skills/intake/intake.yaml
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 send

06Package 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.

build.cjs · insert inside async function
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 form

Check 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 →
SDK / CLI 0.1.0-alpha.9 · Contract baseline Compatibility and preview notes · Sample source