From agent to template
You never hand-write a template manifest. You build a real agent, and the platform does the heavy lifting: publishing freezes every primitive from your promoted agent version automatically, and a draft composer infers the rest — connections, persona variables, trigger presets — into your project’slua.skill.yaml for you to review like a diff. Your job is the product decisions: which connections are required, what the installer-facing copy says, which automations should be on by default.
This guide follows one agent end to end: Standup Sidekick, a small agent that logs the wins a user mentions during the day (log_win / list_wins tools in a standup-skill), nudges them before standup with a scheduled standup-nudge job, and has a persona (“You are the Standup Sidekick for Acme Demo Co…”).
New to templates? Read Agent Templates first for the model — what a template contains, lifecycle, and consent. This page is the hands-on authoring journey.
Step 1 — Build and promote the source agent
Nothing template-specific yet: build Standup Sidekick the normal way.Step 2 — Create the template listing
Run this from the project connected to your source agent:--visibility public to head for the public catalog (which adds a review step, below).
Step 3 — Run the draft composer
template: section into your lua.skill.yaml, composed from what your agent actually is:
Re-running
draft later (say, after adding a skill for v2) performs an additive merge: newly inferred entries are appended, your existing keys are never modified, and the CLI prints a per-section diff of what it added versus kept. A full overwrite of your authored sections requires an explicit --force. Use --source-version <n> to compose from a specific promoted agent version instead of the active one.
Step 4 — Edit the template: section
Here’s a realistic authored section for Standup Sidekick after the composer ran and the creator polished it. The persona got two variables, the nudge job’s interval became installer-editable, and an optional chat connection was declared for posting nudges:
- Every installer-facing entry needs
displayNameanddescription. The deploy screen renders its copy straight from this section — a raw key is never shown as a form label, and publish rejects entries missing them. - Keys are identity. A connection
key, trigger key, param name, or persona var name is its stable identity across versions — renaming one means “remove + add”, which costs installers their setting for it. Keep keys stable across versions. - The whole section is serialized on every publish. When a
template:section exists, all four subsections (connections,personaTemplate,triggerPresets,paramsMeta) are always sent — an empty or deleted subsection is an explicit clear, not “keep the previous version’s”. Clearing or narrowing anything prompts you with the consequence before publishing (see below). - The env contract is declared at publish, via the
--env-contractflag —paramsMetacarries the display metadata for those variables:
Step 5 — Publish
template: section into an immutable, integer-numbered template version (v1, v2, v3 — not semver). Use --source-version <n> to freeze a specific promoted version instead of the active one.
If this publish clears or narrows previously authored sections (you removed a declared connection, dropped a persona var), the CLI prints the consequence per section and asks for confirmation. --yes auto-confirms only that consequence prompt — useful in CI — without skipping any other confirmation the way --force does.
The lint battery
Publish is the quality gate: a version that would fail on an installer’s agent — or render an unusable deploy screen — is rejected at publish, with actionable errors, and a rejected publish burns no version number. Among what it checks:-
Schedules must actually be schedulable. Interval schedules run on whole minutes only — a fractional-minute interval would silently never fire, so it’s rejected up front. Publishing Standup Sidekick with
seconds: 90fails with: -
Persona variables must be declared, both ways. Every
{{VAR}}in the persona template needs a matchingvarsentry, and vice versa — across every persona branch, including voice text. Reserved names (likepersona) are rejected. -
Declarations must be self-consistent. Enum lists non-empty, defaults satisfying their own type, every
editableParams.pathresolving into its trigger entry, optional vars carrying a default. - Connections must be real. Every platform in an allow-list must exist in the integration catalog and match the declared capability; OAuth platforms must declare their scopes (that’s what the installer consents to).
- Portability must be authored, not hoped. A capability may list multiple platforms only when the skills bound to it reach the connection through the capability, not through platform-specific calls — otherwise the allow-list is narrowed to the platform the code actually uses.
- No secrets in frozen code. A hardcoded API key in skill source is caught and rejected, pointing at the file and line, with the fix: declare it in the env contract so each installer supplies their own.
- No voice yet. A source agent with voices or device triggers can’t publish — voice templates aren’t supported in V1, and the error says so rather than shipping a template that deploys half-working.
Step 6 — Visibility and review
Private templates are installable by your org the moment they’re published — this is the fleet path, and it needs no review. Going public adds platform review, and review is per version:- Flipping a private template public enqueues its latest version for review; it lists publicly once approved. Older published versions stay org-only unless republished.
- Every version you publish while public enters review, and isn’t installable by others — including through the update badge — until approved.
- Your own self-test installs are exempt: you can install a pending version onto your org’s agents to verify it before anyone else can.
- A rejection leaves your prior approved versions listed. Versions are immutable — resubmitting means publishing a new version with the fix.
Step 7 — Versioning and consent
Two kinds of change behave differently when you ship v-next, and it pays to know which you’re making:- Code-only changes — you rewrote a tool’s implementation, fixed a bug, improved a prompt inside a skill — flow to opted-in installs (
allowCreatorUpdates) under their standing consent. This is the everyday fleet-update path. - Consent-surface changes — a widened OAuth scope, an added or changed connection, a changed trigger instruction — require re-consent from every install, opted-in included. Your push is rejected per target until the installer reviews and accepts the new surface themselves.
Step 8 — Roll out
apply aimed at a smaller target list. Check the per-target result table (and the agents themselves) before going wide. Pass --no-wait to get the run ID immediately and check on it later with status.
What a rollout will and won’t do on each target:
- Won’t arm anything new. Renamed or newly added triggers land disabled, awaiting the installer’s confirmation. A trigger the installer paused stays paused.
- Won’t strand targets on a new required env key. Targets missing it flip to a pending-input state with an installer prompt, rather than shipping a broken agent.
- Won’t overwrite installer customizations silently. Installer-edited personas are skipped; installer-tuned schedule params are re-applied over your new preset; hand-edits to managed primitives surface an explicit confirm instead of a silent revert.
- Fails loudly. Any failed target marks the run
failedand exits non-zero; successful targets are unaffected and a re-run is safe.
Step 9 — Retire
- Deprecate a version to block new installs of it — existing installs are unaffected, and the changelog carries the reason. You can’t deprecate the only approved version of a still-listed public template; unlist first.
- Unlist the template to soft-retire it: no new installs, no more creator applies. Existing installs keep running with what they have, can still uninstall, and can still re-run their same installed version to rebind a connection.
Related
- Agent Templates — the model: what a template contains, lifecycle, consent
- Template Manifest Reference — every attribute: fields, types, defaults, constraints, lints
- Deploying Templates — what your installers experience
- Marketplace Command reference
- Publishing Skills — the single-skill equivalent

