Skip to main content
These routes publish and install agent templates, which freeze a whole agent so it can be installed on other agents or deployed as a new one: create a template, publish and inspect versions, read the catalog and the served manifest, install a version onto an existing agent, deploy a fresh agent in one call, preview an update, and uninstall. Rolling a version out to installed agents, the installs ledger, health, outcomes, and evals are on Template fleet; single skills listed on the marketplace are on Marketplace skills. The CLI twin is lua marketplace template. Verified against lua-cli 3.33.0.

Base URL and authentication

Writes check automations:write, resolved against the template’s creator organization, the template’s source agent, or the target agent, as noted per route; reads check marketplace:read the same way. Ownership transfers check org:manage. Catalog reads need only an authenticated key and are visibility-filtered: a private template is visible only to its creator organization and answers 404 to anyone else. The host, the bearer header, the error envelope, and the catalog rate limits are on the REST API overview.

Template object

A template object carries id, name, displayName, description, creatorId, creatorOrgId, sourceAgentId?, sourceBaseAgentId?, visibility, listed, latestVersion, latestApprovedVersion?, installCount, activeInstallCount?, workflowCount?, hasScheduledWorkflow?, hasJobTier?, hasScriptForm?, workspaceBackend?, firstParty?, uses?, createdAt, updatedAt. sourceBaseAgentId is the base the source agent was created from and decides whether the template can be deployed as a new agent; the deploy route states the rule.

Template version object

A version object carries id, templateId, version, content?, envContract?, changelog?, sourceAgentVersion?, createdBy, createdAt, contentHash?, codeHash?, consentSurfaceHash?, approvalStatus?, approvalNotes?, the authored sections including installPolicy?, deprecated?, and warnings?. The authored sections (connections, personaTemplate, triggerPresets, paramsMeta, onInstall, onUninstall, installPolicy) are documented on the template manifest and lifecycle hooks pages. The version object’s contentHash is the publish-time digest; the install seal is the manifest’s contentHash.

Endpoints

POST /marketplace/templates

Creates a template. Scope automations:write on sourceAgentId or on creatorOrgId; send exactly one of the two. Omit sourceAgentId for a declarative template composed from marketplace skills, and then creatorOrgId is required. Equivalent: lua marketplace template create.
string
The source agent whose agent versions the template freezes.
string
Creator organization, for a declarative template.
string
required
Template name.
string
required
Display name.
string
Description.
string
public or private.
Response 201 with the template object.

POST /marketplace/templates/:templateId/versions

Publishes a version: freezes the source agent’s active agent version, or sourceAgentVersion, into a new template version. Scope automations:write, creator organization or source agent. Equivalent: lua marketplace template publish. An authored section that is omitted inherits the previous version’s value; an empty array, empty object, or null clears it.
number
Agent version to freeze. Defaults to the active version.
string
What changed in this version.
object
Env contract, keyed by variable name; each { description, required, example? }.
object[]
Triggers the version declares.
object[]
Marketplace skills a declarative template composes. At most 50.
object[]
Authored section; see the template manifest.
object
Authored section; see the template manifest.
object
Authored section; see the template manifest.
object
Authored section; see the template manifest.
object
Authored section; see lifecycle hooks.
object
Authored section; see lifecycle hooks.
object
{ perWorkspace: "single" | "multiple" }. single caps the template at one install per organization.
object
Outcome units the version records.
object[]
Channels the version declares.
object[]
Features the version declares.
string
Eval run to attach as the reference.
boolean
Do not fan the publish out to installs that consented to creator updates.
Response 201 with the template version object, plus autoApplyRunId and autoApplyTargetCount when the publish fanned out to installs that consented to creator updates. Poll that run on Template fleet.

POST /templates/:templateId/versions/draft

Composes a proposed template: section for lua.skill.yaml from the frozen source and never persists it. Scope automations:write, creator organization or source agent. Equivalent: lua marketplace template draft.
boolean
Replace existing authored sections wholesale instead of merging additively.
boolean
Add advisory copy proposals from the model; they are never merged automatically.
number
Agent version to draft from. Defaults to the active version.
Response 201 with { templateId, draft, diff, proposals?, warnings? }, where warnings lists pinned workflows or jobs that no longer exist on the source agent (snapshot-workflow-missing, snapshot-job-missing).

PATCH /marketplace/templates/:templateId

Updates the template’s listing text. Scope automations:write, creator organization.
string
New display name.
string
New description.
Response 200.

PUT /marketplace/templates/:templateId/visibility

Sets the template’s visibility. Scope automations:write, creator organization. Flipping private to public enqueues a review.
string
required
public or private.
Response 200.

PUT /marketplace/templates/:templateId/unlist

Unlists the template. Scope automations:write, creator organization or source agent. Response 200.

PUT /templates/:templateId/versions/:version/deprecate

Deprecates one version, which blocks new installs of that version only. Scope automations:write, creator organization.
string
Why the version is deprecated.
Response 200.

PUT /templates/:templateId/owner

Transfers the template to another organization. Scope org:manage on both organizations.
string
required
The receiving organization.
Response 200.

GET /marketplace/templates

Lists the catalog. Any authenticated key; visibility-filtered.
number
Page number.
number
Page size.
boolean
true filters to templates published by Lua.
Response 200 with { templates, total }, each entry a template object.

GET /marketplace/templates/:templateId

Returns one template. Visibility-filtered; a scoped key needs marketplace:read. Equivalent: lua marketplace template view. Response 200 with the template object.

GET /marketplace/templates/:templateId/versions

Lists a template’s versions. Same access as the template read. Equivalent: lua marketplace template versions.
number
Page number.
number
Page size.
Response 200 with template version objects.

GET /marketplace/templates/:templateId/versions/:version

Returns one version. Same access as the template read. Equivalent: lua marketplace template view --version <n>. Response 200 with the template version object.

GET /marketplace/templates/:templateId/manifest

Returns the manifest of the latest version: the safe requirements view with no source code. Same access as the template read.
string
Agent to reconcile against; adds reconciliation to the response.
string
Organization to reconcile against instead of an agent.
Response 200 with { id, name, displayName, description, version, latestVersion, visibility, contentHash?, agent: { model? }, skills[], connections[], triggers[], params[], workflows?[], personaTemplate?, channels?, features?, onInstall?, onUninstall?, installPolicy?, latestApprovedVersion?, installable?, deprecated?, reconciliation, policy? }.
object[]
Present when the version froze a workflow. Each { key, displayName, description?, version, form: "graph" | "script", stepCount, hasApproval, hasSchedule, hasSignalWait, hasJobTier, jobSecondsMax?, inputSchema? }.
object
Present when the version declares one: { perWorkspace: "single" | "multiple" }.
object
Per connection requirement, whether the agent or organization in the query already satisfies it (satisfied, multiple-matches, insufficient-scope, verify-access, unmet-required, unmet-optional) and which existing connections are candidates.
string
The install seal: echo it as contentHash on install or deploy. The version object’s contentHash is the publish-time digest and is not the seal.

GET /marketplace/templates/:templateId/versions/:version/manifest

Returns the manifest of one version, with the same query parameters and shape as the latest-version manifest. Same access as the template read.

GET /marketplace/templates/:templateId/review

Returns the review status of every version, newest first. Scope marketplace:read, creator organization or source agent. Resubmitting for review means publishing a new version. Response 200 with { templateId, visibility, latestApprovedVersion?, versions: [{ version, approvalStatus?, approvalNotes?, approvedBy?, approvedAt?, provenanceAlerts?, holdout? }] }.

GET /templates/:templateId/eligible-targets

Lists the caller’s own agents and whether each can take the template. Any authenticated key. Response 200 with [{ agentId, name, orgId, installable, reason? }]; reason is one of already-installed, shared-agent-requires-org-admin, apply-in-progress.

POST /marketplace/templates/:templateId/install/:agentId

Applies a template version to an existing agent and answers synchronously with the install result. Scope automations:write on the agent. Equivalent: lua marketplace template install. skipEnvCheck is not accepted: unknown body fields are stripped, and the CLI’s --skip-env-check therefore has no server-side effect. A refused install leaves no install record.
number
Template version. Defaults to latest.
string
The manifest’s contentHash, echoed verbatim. When the template changed in between, the install refuses with 409 CONTENT_HASH_MISMATCH. Omit to skip the seal.
object
Env values written before validation, keyed by env contract key.
object
Capability key to { type, connectionId }: which existing connection satisfies each requirement. Re-derived server-side.
object
Trigger key to { enabled?, params?, input? }. On a fresh install this is the sole source of the armed set: keys you omit are installed disarmed. On a re-install, keys you send win and omitted keys keep their current state. params sets declared editable schedule paths such as preset.seconds; input sets declared workflow-trigger input paths.
object
Answers for the persona template’s declared variables, keyed by name.
string | object
Installer-edited persona; legal only when the persona template is editable. Stored verbatim and never re-expanded.
boolean
Opt in to replacing a persona the agent already has.
boolean
Consent to the creator pushing future versions onto this install.
string[]
kind/key entries the update may overwrite even though they were modified since the last install (the answer to MODIFIED_SINCE_INSTALL).
string[]
key.path entries whose stored value you accept dropping because the new version no longer declares them editable.
object
Move parked workflow runs onto the installed version: { strategy: "resume-on-new" | "cancel-and-reseed", keys?, onIncompatible?: "leave" | "cancel", reason?, include?: "suspended" | "all" }. Installing organization only.
string
Model code for the agent; "" selects the default model instead of a specific one. Maximum 200 characters.
Response 201 with the install result.

POST /marketplace/templates/:templateId/deploy

Creates a fresh agent in your organization and installs the template on it in one call. The scope is checked on the target organization. Deploy is legal only for templates whose source is a base agent, that is, an agent created from the standard base rather than a Space or a catalog integration agent; the template object records this as sourceBaseAgentId equal to baseAgent, and any other source answers 409 TEMPLATE_NOT_DEPLOYABLE.
string
required
[A-Za-z0-9_-], 16 to 128 characters. A retry with the same key returns the original outcome and never creates a second agent.
number
Template version. Defaults to the latest approved version, or the latest version when none is approved.
string
The manifest’s contentHash; same meaning as on install.
string
Name for the new agent. Maximum 120 characters.
string
Organization to create the agent in. Defaults to your default organization; a caller with no organization gets a personal one created.
Same meaning as on install.
Response 201 with the deploy result when the deploy finishes within 10 seconds; otherwise 202 with { deployId }, to poll on the deploys route.

GET /marketplace/templates/deploys/:deployId

Polls a deploy that answered 202. Scope marketplace:read, resolved from the deploy. Response 200 with { deployId, status: "running" | "succeeded" | "failed" | "rolled_back" | "rollback_pending", stage?, stages?, result?, error? }; result is the deploy result and error uses the envelope under Errors.

GET /marketplace/templates/:templateId/deploy-session

Returns the caller’s deploy session for one template version: the draft answers and per-connection connect progress a wizard stores so it can resume. Signed-in user; the caller’s own session only.
number
Template version the session belongs to.
Response 200 with { session, copy }.

PUT /marketplace/templates/:templateId/deploy-session

Deep-merges the body into the caller’s deploy session. Signed-in user; the caller’s own session only.
number
Template version the session belongs to.
object
Draft answers.
object
Per-connection connect progress.
string
Idempotency key held for the deploy.
Response 200 with { session, copy }.

GET /marketplace/templates/install-requests/mine

Lists the caller’s install requests in an organization. Scope marketplace:read on the organization.
string
required
The organization.
Response 200.

GET /marketplace/templates/agent/:agentId

Lists the templates installed on an agent. Scope marketplace:read on the agent. Equivalent: lua marketplace template installed. Response 200 with [{ templateId, displayName, installedVersion, appliedAt, installedBy?, status }].

GET /agents/:agentId/templates

The rich form of the installed-templates list. Scope marketplace:read on the agent. Response 200 with the same entries plus latestApprovedVersion?, updateAvailable, allowCreatorUpdates, lastError, appliedBy?, updatePendingConsent?, bindings[], triggers[], outcomes[], paramValues, params[], setup?, onInstallWorkflowRunId?, onInstallError? per install; setup is { status: "running" | "ok" | "failed", error?, code?, workflowRunId? } for the post-install hook.

GET /agents/:agentId/templates/:templateId/update-preview

Answers the diff an update would apply. Scope marketplace:read on the agent.
number
Version to preview the update to.
Response 200 with { fromVersion, toVersion, changelog?, sections, envContract, consentSurfaceChanged, codeChanged, scopeDelta, armedTriggersSurviving, driftedPrimitives, workflowRunsInFlight?, droppedEditableParams? }.

PATCH /agents/:agentId/templates/:templateId

Changes whether the creator may push updates onto this install; the only post-install way to change that consent. Scope automations:write on the agent.
boolean
required
Consent to creator updates.
Response 200.

POST /agents/:agentId/templates/:templateId/setup/retry

Re-runs a failed post-install hook. Scope automations:write on the agent. Response 201 with { onInstallFired?, onInstall?, onInstallWorkflowRunId?, onInstallError?, startWorkflow }, where startWorkflow is { outcome: "started", runId }, { outcome: "already-started", runId? }, { outcome: "failed", error }, or { outcome: "not-declared" }.

GET /marketplace/templates/:templateId/installs/:agentId/removal-preview

Answers what deleting the agent through uninstall with removeAgent=true would affect. Scope automations:write on the agent. Response 200 with { agentId, agentName, minted, soleInstall, otherTemplates, members, memberTotal, workspaceRoleHolders, workspaceRoleHolderTotal, rooms, roomTotal, automations, connections, billing, warnings }.

DELETE /marketplace/templates/:templateId/installs/:agentId

Uninstalls the template: runs the version’s onUninstall hook as the caller, removes the managed primitives, and promotes a new local agent version. Scope automations:write on the agent. Equivalent: lua marketplace template uninstall.
boolean
Also delete the agent afterwards. Allowed only for an agent this template created through deploy; otherwise 409 agent-not-template-minted.
Response 200 with { success, onUninstall?: { ran, ok?, error? }, agentRemoved? }. The hook is fail-soft, so read onUninstall rather than success for its outcome.

Install result

Returned by install, and on Template fleet by the installs ledger and the creator retry.
string
The template.
string
The agent installed on.
string
The agent’s organization.
number
Template version applied.
number
The agent version the install promoted.
boolean
Whether the creator may push updates onto this install.
string
Install status, for example installed, already_current, apply_failed.
string
Error of the last failed apply.
string
User ID of the last apply.
string
Timestamp of the last apply.
string
User ID of the first install; never rewritten.
string[]
Trigger keys this apply armed.
object[]
Each { key, reason }: triggers that could not be armed.
object[]
Each { key, reason }: armed schedules whose runs deposit no inbox card because the author marked them to run as the system rather than a user.
object[]
Each { key, url }: per-install dispatch URLs for webhook-source triggers.
string[]
Params or persona variables hidden by a showIf condition under the effective values; a submitted or stored value for them was cleared without validation.
boolean
true when the template declares a persona but the write was skipped to preserve a user-edited persona.
boolean
true when this apply claimed and fired the post-install first run; absent otherwise.
object
{ toolRan, ok? }. toolRan is true when this apply claimed the version’s onInstall.tool; the tool runs in the background and records its result on the install, readable as setup on the rich installed-templates read. A failed tool never fails the install.
boolean
true when the hooks were deferred to the caller, as the deploy path does; onInstallFired and onInstall then come from that later fire.
string
The run onInstall.startWorkflow started on the installed copy, or the run an earlier same-version install already started.
object
Why onInstall.startWorkflow started no run; the install itself succeeded. code is one of workflow-not-materialized, control-plane-unavailable, control-plane-dark, start-refused, start-failed. Retry with POST /agents/:agentId/templates/:templateId/setup/retry.
object
{ migrationIds, counts, pending?, skipped? } per workflow key when migrateRuns was sent.

Deploy result

Returned by deploy with 201, and as result on the poll route.
string
The created agent.
string
Organization the agent was created in.
number
The agent version the install promoted.
string
installed, already_current, or apply_failed.
string[]
Trigger keys armed.
object[]
Each { key, url }.
object[]
Each { key, reason }.
object[]
Each { key, reason }; same meaning as on the install result.
boolean
Same meaning as on the install result.
string | null
Error of a failed apply.
string[]
Same meaning as on the install result.
boolean
true when the install inside this deploy fired the post-install first run.
object
{ toolRan }; the outcome is reported through setup on the rich installed-templates read.
string
The run onInstall.startWorkflow started on the deployed agent.
object
Why no run started; same codes as on the install result.

Errors

Install, deploy, and the poll route’s error share one envelope: { code, message, capabilityKey?, field?, allowedValues?, primitives?, reason?, missingScopes?, key?, blockedTriggers?, jobs?, sourceAgentId?, kind?, items?, issues?, reconciliation? }. reconciliation is recomputed for every 409, so it always reflects the agent’s current connections.

Example

Install a template on an existing agent with the hash seal, so a template that changed after you read its manifest is refused instead of applied.

See also