Skip to main content

Package Recipe Reference

Package recipes live in a package repository under:

packages/<package_id>.yaml

A recipe describes which authored-surface files to install into runtime Agent Cores. It owns package identity, install-time options, component selection, target paths, pipeline placement, conditions, and config overlays.

Component source directories own runtime files such as slot.yaml, tool.yaml, config.yaml, Python modules, skills, libraries, child cores, MCP manifests, and schedule manifests.

For a task-oriented writing guide, see Write a Package Recipe.

Complete Shape

schema_version: 1
id: reply_style
name: Reply Style
summary: Add a reply style input module.
tags:
- input
- style
manual_dependencies: []
options:
- id: tone
type: choice
prompt: Tone
description: Choose the reply tone.
default: direct
required: false
choices:
- value: direct
description: Prefer direct answers.
- value: detailed
description: Prefer detailed answers.
capabilities: []
components:
- id: reply_style_input
kind: input
source: reply_style
target: agent/input/reply_style
pipeline:
group: serial
append: true
config:
tone: ${options.tone}

Only schema_version, id, and components are required at the top level.

Top-Level Fields

FieldRequiredTypeDefaultMeaning
schema_versionYesintegerNoneMust be 1.
idYesstringNonePackage id, unique within the repository.
nameNostringidDisplay name in package lists and interactive flows.
summaryNostringempty stringShort package summary.
tagsNolist of strings[]Filter and browse tags such as memory, stt, or provider:openai.
manual_dependenciesNolist of strings[]Human-review warnings for dependencies Demiurge will not install.
optionsNolist of option objects[]Install-time values that users can provide.
capabilitiesNolist of strings[]Package-level capability summary for review.
componentsYeslist of component objectsNoneComponents to install.

Removed v1 fields are rejected:

slots
tools
files
config_defaults
metadata

Component-level metadata and phase are also rejected.

Option Fields

Options are resolved once during install or preview. Unknown script-supplied options are rejected.

FieldRequiredTypeDefaultMeaning
idYesstringNoneOption id used by ${options.<id>} references. Must be unique in the recipe.
typeNostringstringOne of string, bool, choice, path, or secret.
promptNostringidLabel shown by the interactive package manager.
descriptionNostringempty stringHelp text shown in interactive flows and docs.
defaultNoany scalarnull when absentValue used when the user does not provide an answer.
requiredNobooleanfalseReject missing or empty values after defaults are applied.
choicesFor choicelist[]Allowed values for a choice option.
secretNobooleantrue for type: secretRedact this option in installed packages.yaml.

Supported option types:

TypeAccepted install valueNotes
stringscalar valueStored as text. Lists and maps are rejected.
boolboolean or common true/false stringsAccepted strings include true, yes, y, 1, on, false, no, n, 0, and off.
choicestring from choiceschoices are required; a non-empty default must be one of them.
pathscalar valueStored as text. Validation is package-owned.
secretscalar valueStored as text in installed config when used, but redacted in packages.yaml.

choices entries can be strings:

choices:
- direct
- summary

They can also be objects with descriptions:

choices:
- value: direct
description: Generate speech from the assistant reply as-is.
- value: summary
description: Summarize the assistant reply before generating speech.

Option References

config and config_when.config can reference options:

config:
api_key: ${options.api_key}
notice: ${options.notice}

An exact string reference preserves the resolved value type:

notice: ${options.notice}

If notice is a bool, the rendered config value is a boolean.

An option reference embedded in a longer string renders as text:

label: "voice-${options.voice}"

If an option resolves to null, an exact reference renders null; an embedded reference renders an empty string.

Component Kinds

kindSource pathDefault targetRequired source filesWhat it installs
bootstrapbootstrap/<source>/agent/bootstrap/<source-name>slot.yamlA bootstrap slot and pipeline entry.
inputinput/<source>/agent/input/<source-name>slot.yamlAn input slot and pipeline entry.
outputoutput/<source>/agent/output/<source-name>slot.yamlAn output slot and pipeline entry.
tooltool/<source>/agent/tools/<source-name>tool.yamlAn authored tool directory.
skillskill/<source>/agent/skills/<source-name>None enforcedA skill directory.
liblib/<source>/agent/lib/<source-name>None enforcedPackage-owned helper code or config.
corecore/<source>/runtime core named by target_core_id or component idagent.yaml expected at install timeA package-owned runtime child core.
mcpmcp/<source>target core MCP declaration root plus source filenameYAML fileOne MCP server declaration.
scheduleschedule/<source>target core schedule declaration root plus source filenameYAML fileOne schedule declaration.

Components are installed in this stable kind order:

lib, bootstrap, input, output, tool, skill, core, mcp, schedule

This order lets slots and tools import package-owned lib files when the runtime loads the installed core.

Component Fields

FieldRequiredApplies toTypeDefaultMeaning
idYesall componentsstringNoneComponent id, unique within the recipe.
kindYesall componentsstringNoneOne of the supported component kinds.
sourceYesall componentsstringNoneSource name under the matching repository root. Must stay inside the repository.
targetNoall except corestringkind-specific defaultRuntime-core-relative target path.
target_core_idNocorestringcomponent idRuntime core id to create or update.
pipelineYes for bootstrap, input, output; invalid for othersslot componentsmappingNonePipeline group and placement.
configNoall except coremappingNoneConfig overlay rendered with options.
whenNoall componentsmapping{}Option condition that includes or skips the component.
config_whenNoall except corelist[]Conditional config overlay list.

source cannot be absolute, cannot contain .., cannot be a symlink, and cannot contain symlinks.

Pipeline Placement

Only bootstrap, input, and output components can edit agent/pipelines.yaml.

Every slot component must declare one pipeline group and exactly one placement:

pipeline:
group: serial
append: true
pipeline:
group: serial
before: base_input
pipeline:
group: parallel
after: artifact_writer

Supported groups:

Component kindGroups
bootstrapserial
inputserial, parallel
outputserial, parallel

Rules:

  • A pipeline mapping can contain only group, append, before, and after.
  • Exactly one of append, before, or after must be active.
  • before and after targets must already exist in the target pipeline.
  • Install fails if the target pipeline already contains the slot id.
  • Uninstall removes package-owned pipeline entries.

The installed slot id is the installed target directory name.

Config Overlays

For directory components, config is a deep-merge overlay on the source component's config.yaml.

If a directory component declares config or config_when, its source directory must contain config.yaml.

components:
- id: stt_lib
kind: lib
source: stt_openai
target: agent/lib/stt_openai
config:
api_key: ${options.api_key}
language: ${options.language}

Merge behavior:

  • Mapping values merge recursively.
  • Scalars, lists, and null replace the source value.
  • The rendered effective config is written back to the installed component's config.yaml.
  • The install record stores a config hash, not the full effective config.

For mcp and schedule, config is applied directly as a manifest overlay before schema validation and normalization.

core components cannot declare config or config_when.

Conditions

Use when to include or skip a whole component:

components:
- id: tts_tool
kind: tool
source: text_to_speech_minimax
target: agent/tools/text_to_speech
when:
enable_tool: true

Use config_when to apply extra config only when a condition matches:

components:
- id: tts_output
kind: output
source: tts_minimax
target: agent/output/tts_minimax
pipeline:
group: parallel
append: true
config_when:
- when:
mode: summary
config:
summarizer_core: tts_summarizer

Condition rules:

  • Conditions are mappings from option id to expected value.
  • Every referenced option id must exist in options.
  • Matching is exact after option values are resolved and normalized.
  • Empty or missing when means the component or config overlay always applies.

Manifest File Components

mcp and schedule components use one YAML source file and install one rendered YAML file into the target core's declaration root.

Default roots come from the target core's agent.yaml:

KindSlot nameFallback root
mcpslots.mcpagent/mcp
scheduleslots.schedulesagent/schedules

Rules:

  • Source files live under mcp/ or schedule/.
  • Source files must use .yaml or .yml.
  • Targets must be YAML files.
  • Targets must be directly inside the declaration root.
  • A sibling file with the same manifest id and a different YAML suffix is a conflict.
  • Installed files are normalized through the MCP or schedule manifest schema.

Example:

components:
- id: docs_mcp
kind: mcp
source: docs.yaml
config:
url: ${options.url}
- id: weekday_summary
kind: schedule
source: weekday_summary.yaml
config:
prompt: ${options.prompt}

MCP and schedule packages install declarations. The host still owns MCP transport, server lifecycle, schedule claims, approvals, and execution.

Component Source Manifests

Recipe YAML does not replace component manifests.

Slot component source directories must include slot.yaml. Allowed keys are:

entrypoint
description
input_schema
capabilities
timeout_seconds
failure_policy
default_placement
history_policy

Tool component source directories must include tool.yaml. Allowed keys are:

entrypoint
description
input_schema
risk
capability
approval_policy
display_policy
model_output_policy
capabilities

Unknown keys in slot.yaml or tool.yaml are rejected when the repository is loaded.

Reuse and Conflicts

Install rejects unmanaged target conflicts.

Multiple packages can reuse the same component target only when an installed package already owns the same repository alias, source, target, and effective config hash.

Install also rejects:

  • Duplicate package ids in one repository.
  • Duplicate component ids in one recipe.
  • Duplicate targets in one install plan.
  • Duplicate MCP or schedule manifest ids in one declaration root.
  • Shared component config conflicts.

Uninstall removes package-owned targets and package-owned pipeline entries. It does not remove data written outside package-owned targets.

Validation Rules

  • repository.yaml and recipe schema_version must be 1.
  • tags, manual_dependencies, and capabilities must be lists of strings.
  • components must be a list of mappings.
  • Component kind must be supported.
  • Component id, kind, and source are required.
  • pipeline is required for bootstrap, input, and output.
  • pipeline is invalid for all other component kinds.
  • config must be a mapping when present.
  • config_when must be a list of objects with config mappings.
  • core components cannot use config or config_when.
  • when and config_when.when must reference declared options.
  • Component sources must stay inside the package repository.
  • Component sources cannot be symlinks and cannot contain symlinks.
  • Package recipes do not install Python dependencies.
  • Package recipes do not edit host dependency files.