Skip to main content
A skill is markdown the assistant loads when your extension is the right thing to reach for. A prompt is a question the owner can put in the chat composer with one click, from chat, from your widget, from your page, or under a card one of your tools produced.
Both need the ai:skills scope, and that scope carries a justification the owner reads at install.

The manifest entry

The command writes this entry. You can hand-edit tappify.extension.json instead — the $schema line gives your editor completion and validation, and tappify extension doctor checks the result.

Writing a skill

skills/growth-review.md is a procedure for the assistant, at most 4,000 words. Write the steps, not the sales copy: which of your tools to call first, what your numbers mean, and when your data does not answer the question.
A longer file fails publish with bundle.skill_size, because the assistant reads all of it the moment it picks the skill. Reference material belongs in a knowledge file instead, which is retrieved a paragraph at a time. name is at most 60 characters and description 10 to 300. Together they are all the assistant sees until it picks your skill: Tappify lists your skills by name and description on every turn and loads the body only when the assistant selects one, so length costs you nothing until it is used. tools lists your own tool ids. A skill may only rely on the tools its own extension declares; naming another extension’s tool fails the publish with skills.tools. Tappify registers your skills when the install is created, when the owner grants ai:skills, and when an install is resumed, and re-reads them from the new manifest whenever one of your releases goes live. A paused, retired or uninstalled install keeps none. At most 5 skills.

Writing a prompt

template is the question, with placeholders Tappify fills in. {{project.*}} is resolved on the server before the chip reaches the browser; {{context.*}} and {{input.*}} are resolved in the owner’s browser when they click. Those three are the whole of {{project.*}}. A chip in the chat’s suggestion row or under a result card carries no context of its own, so a {{context.*}} there resolves to nothing — and so does any other key Tappify does not recognise. The sentence around it is tidied up rather than left with a gap, which is why a template reads better when the placeholder is a whole clause. A template that leans on the surface — Why did {{project.name}} lose users at {{context.stage}}? — belongs on a prompt declared for widget or page, which are the surfaces that carry one. surfaces says where the chip is offered: after names your own tool ids, and the manifest refuses any other extension’s. A result_card chip is offered only under a card one of the tools in after produced. title is at most 60 characters, template at most 2,000, and the resolved question a chip carries is cut to 500. At most 20 prompts.

Asking for input first

Tappify draws that schema as a form in a host dialog, and the composer fills only once the owner submits it. A chip that asks first carries a trailing ellipsis, so the owner knows the click opens a form rather than filling the composer.

What the owner sees

A chip with your tile and your title. Clicking it puts the finished question in the owner’s composer and stops there: they read it, edit it if they want, and press send themselves. Nothing you write is ever sent on their behalf. Tappify offers at most two of your chips in any one row, after its own. When the owner does send, the turn records a prompt_sent against the chip it came from. A chip naming a prompt the live release no longer declares is refused with PROMPT_NOT_DECLARED.

Opening the chat from your own surface

Your widget and your page can reach the composer directly, without a declared prompt.
The prompt lands in the composer, and the context object lands under it on a visible line reading From <your extension name>:, which the owner can read and edit before they send. That context is capped at 2 KB and a cut is marked with an ellipsis.
With insights:write, that puts your card into the transcript as a card the host draws, and opens the chat drawer. Without the scope it falls back to a sentence Tappify writes about the card, in the composer, for the owner to send.