Reference

Pack manifest

The fields of a pack file, and the checks a pack must pass.

A pack is the box Recued installs. Its manifest is the list on the box. It names the recipes and other capabilities that arrive together. It pins every version it points at. And it holds the notes people see before they install. When you install a pack, those files are copied to your server. The publisher gets no ongoing control over the install after that.

Use manifest_version: 2 for new packs. Version 1 still works for older packs that hold only recipes.

#Minimal app pack

Here is the smallest useful app pack:

json
{
  "manifest_version": 2,
  "artifact_type": "pack",
  "pack_kind": "app_pack",
  "service_kind": "workflow",
  "slug": "sales-review",
  "publisher": "your-handle",
  "name": "Sales Review",
  "description": "Reads CRM opportunities and prepares a weekly review for the owner.",
  "version": 1,
  "contents": [
    {
      "type": "ingredient",
      "slug": "crm-opportunity-reader",
      "version": 2,
      "role": "operation_wrapper"
    },
    {
      "type": "recipe",
      "slug": "weekly-sales-review",
      "version": 1,
      "visible": true
    }
  ],
  "requires": ["install_bulk_pack"],
  "tags": ["pack:sales-review", "crm", "weekly-review"]
}

This example pins one ingredient and one recipe. It grants nothing by itself. The install screen still asks the owner three things. Which connection? Which access tier? And who may use the pack?

#Envelope fields

The envelope is the outer part of the pack file. These fields are required. The tags field is not required, but you should set it:

Field Required Meaning
manifest_version Yes 1 for a pack that holds only recipes. 2 for typed contents and dependencies.
slug Yes The pack's name in a web address. Use small letters, numbers, and hyphens. It must start and end with a letter or a number.
publisher Yes Your publisher handle. A public pack is shown as publisher/slug.
name Yes The name people see in Discover and in the install dialog.
description Yes What the pack does, and what kind of data it touches. An empty string is allowed, but it helps nobody.
version Yes A whole number above zero. Raise it when the contents change, or when the install works differently.
requires Yes The permissions the pack asks for. It must include install_bulk_pack.
tags Recommended Words for search and grouping. Leave the list out, and you get a warning.

#Optional envelope fields

Field Required Meaning
repo No An HTTPS link to the source code or the support page.
artifact_type No If you set it, it must be pack.
pack_kind No recipe_pack, app_pack, or foundation_pack.
service_kind No What kind of service the pack adds. See the table below.
min_recued_version No The lowest Recued this pack runs on, such as 26.10.12. Name a release that has shipped. A server older than that will not install or update the pack, and the install dialog says to update Recued. If a recipe in the pack names one, name the same version or a later one here, so people learn it before they press Install. Only servers that know this field check it.

The pack's version is separate from the versions inside it. Say a recipe goes from version 2 to version 3. Then you need a new recipe pin and a new pack version.

#Service kinds

The service_kind field helps Discover and the install review say what is arriving. It does not change how an operation runs.

Value Use for
entity_platform A vendor or data platform, with a catalog of records and operations. A catalog is the list of what a pack can talk to and call
tool_function One small service you can call, such as weather or address lookups
cli A command that runs on the server
channel_door A chat channel, or a place where messages come in
ai_connection A connection to an AI model provider
mcp_door A door that AI agents reach over MCP
storage Shared storage, or the warehouse
workflow One or more recipes that get a job done

#Version 1: recipe-only packs

Version 1 needs a recipes list with at least one entry. It allows at most 50 recipe entries.

json
{
  "manifest_version": 1,
  "slug": "personal-review",
  "publisher": "your-handle",
  "name": "Personal Review",
  "description": "Installs the weekly review and its two quiet data producers.",
  "version": 1,
  "recipes": [
    { "slug": "collect-review-signals", "version": 1 },
    { "slug": "refresh-review-rollup", "version": 1 },
    { "slug": "weekly-review", "version": 2 }
  ],
  "requires": ["install_bulk_pack"],
  "tags": ["pack:personal-review", "weekly-review"]
}

Recipes install in the order you list them. It helps to list the recipes that pull in data, and the ones that make facts, before the recipes that use them. That also makes the pack easier to review. Version 1 ignores contents and dependencies, with a warning. Move to version 2 before you use either field.

#Version 2: typed contents

Version 2 allows up to 100 entries in contents. It needs at least one entry in contents, or in the older recipes list. A pack that adds no recipes, only capabilities, does not need a recipe at all.

type Required fields Purpose
recipe slug, version Pins one recipe. The optional visible flag says if people see it as a recipe.
ingredient One addressing form below Pins a published ingredient, or an ingredient id under a publisher.
operation_group ingredient_id, group_id Adds a declared group of operations from an ingredient.
channel_binding channel_name, capability, bound_to_catalog, conversation_policy Connects a channel to a catalog.
policy policy_id Adds a named policy.
composition composition Holds a whole composition, written out in full.

#Ingredient entries in version 2

An ingredient entry has exactly one of these two forms:

json
{ "type": "ingredient", "slug": "mail-reader", "version": 2, "role": "operation_wrapper" }
json
{ "type": "ingredient", "ingredient_id": "recued-core/mail", "ingredient_version": 2 }

On the slug form, you can skip the role. If you set it, it is entity_schema, operation_wrapper, or producer. Never mix the two forms in one entry.

#A recipe listed twice

A recipe may appear in both contents and the version-2 recipes list. Recued drops exact copies, where the slug and the version are both the same. The contents entry wins, so its visible setting is kept. Better: keep one list. Put new version-2 recipe pins in contents.

#By-value compositions

Most vendor packs carry one composition entry. A composition is written out in full, right inside the pack. It holds flat ingredients and operations tables. It can also hold recipe templates, default grants, work-entity Sources (synced lists of things like tasks or deals), and recipes. Recued checks it and breaks it down into the same ingredient and operation records that files you publish on their own would make.

Each operation says three things. How risky is it? When does it ask for approval? Is it safe to repeat? It also lists its arguments. Each argument says if it is required, and if it picks the target. And each operation has a binding that says how to run it. The binding's shape depends on the surface. It can be an HTTP method and path template. It can be a GraphQL document. Or it can be an argument list for a local command.

#Where to start with a composition

Start with the Pack editor. Point it at an API description or a command. It works out the bindings. It shows you the risk and data review. And it refuses mixes that would be rejected later. Most authors need nothing else.

Are you generating a pack instead of filling in a form? Maybe from an API description, a script, or your own tool. Then read Composition. It spells out the tables. It also says what publishing checks, and what it does not check.

The pack parser checks the composition marker. Then the authoring validator checks the composition itself. So a pack file that passes the outer check is not proof that its composition can be published. A composition is broken down into operation and catalog fields. See the ingredient manifest for those fields.

#Dependencies

Version 2 can name packs or ingredients that must be installed first. You can skip min_version. If you set it, it must be a whole number above zero.

json
"dependencies": [
  { "type": "pack", "slug": "email-outbox-pack", "min_version": 3 },
  { "type": "ingredient", "slug": "contact-search", "min_version": 2 },
  { "type": "ingredient", "ingredient_id": "recued-core/calendar" }
]

An ingredient entry here uses either slug or ingredient_id. Never both. The outer check only looks at this shape. At install time, Recued walks the list of packs, and their lists, and so on. A missing pack, a wrong version, or a loop fails the preflight check (the checks run before anything is installed). An ingredient entry here only says "this must be there first". It does not add the ingredient. Use contents or a composition for that.

#Install disclosure and authority

The pack file says what the install screen must show for review. It cannot skip that review.

  • requires must include install_bulk_pack. The needs of each recipe inside are added to the list. The pack cannot hide them.
  • Operation risk, approval, and editable arguments come from the ingredients or the composition the pack points at. The owner picks the access tier and the audience at install time.
  • webhook_requirements may ask for named webhook slots. Each slot must be backed by a webhook profile Recued knows. An author cannot put a verifier secret (the secret used to prove a webhook is real) or any incoming URL in this field.
  • mcp_body_visibility_grants is a closed list. It is for very private access to message bodies. An unknown value is refused.

#Fields kept for Recued itself

Some fields are for Recued's own release and set-up plumbing. A third-party pack cannot set pre_install: true. It cannot set a non-empty connection_requirements either. Those would let a pack install itself, or write a form that asks for a secret key. The fields launch_flag and post_substrate_canary are first-party rollout data. They are not feature flags for pack authors.

The transactional_offer field is special too. It can describe one paid workflow with six stages. It is allowed only on a version-2 app_pack with service_kind: "workflow". It is only data for the marketplace to show. The price, the proof of payment, customer access, and delivery live elsewhere. See Selling access.

#Validation checklist

Before you submit a pack, check all of these:

  1. Every slug is lowercase and safe for a web address. Every version is a whole number above zero.
  2. Every recipe and ingredient pin points at the publisher and version you meant.
  3. requires includes install_bulk_pack. The install preview names every extra permission.
  4. The description says what the pack does. It says which systems the pack touches. And it says if anything runs quietly in the background.
  5. A version-2 ingredient entry uses one form. An entry in dependencies uses one form.
  6. A composition written out in full passes both its authoring check and its break-down (decomposition) check.
  7. The install preview shows the connections, operations, approvals, body access, webhook slots, and audience choices you expect.
  8. Install and uninstall the pack on a clean server. Then look at recipes, grants, dependencies, and inventory. Nothing should be left behind or put off.

#What validation proves

The schema check is only the first gate. Publishing checks the outer part and every composition written out in full. It does not prove that each pinned recipe or ingredient can be fetched when someone installs the pack. The install finds the pinned recipes. Then it checks the packs it needs and its permissions before it starts. If a recipe write fails, all the recipe writes roll back together. Composition and inventory setup have their own results. So a pack file that parses is not proof of a complete install.

Recued Docs

Search documentation

Start typing to search the documentation.