package.json manifest
Every recipe uses package.json as its manifest. Familiar package fields such
as name, description, version, and license describe the package. The
pi block tells Recipes where to find its agents and optional resources.
{
"name": "support-agent",
"version": "0.1.0",
"description": "Investigates support requests and drafts policy-grounded replies.",
"type": "module",
"pi": {
"agents": ["agents/*.yaml"],
"skills": ["skills/**/SKILL.md"],
"prompts": ["prompts/*.md"],
"extensions": ["extensions/*.ts"],
"mcp": {
"servers": [
// ... server policies
]
},
"runtime": {
// ... Python and system requirements
}
}
}The pi block can declare:
agents— one YAML file per agent; at least one is required;skills—SKILL.mdprocedures an agent may load;prompts— prompt templates, invoked as slash commands;extensions— TypeScript the package owns and every session loads;mcp— which MCP servers the package may use, and how much of each;runtime— locked Python and approved system capabilities the host must provide.
Resolution rules
- Omit
agents,skills, orpromptsto get the directory of that name by convention.extensionsandmcpare never found by convention, because executable code and capability are declared or absent. - A path can be a file, a directory, or a glob, and every one you write has to match something. Paths stay inside the package, including through symlinks.
- An explicit
[]resolves nothing of that kind. - A typo inside
piis an error, not a warning. Outside it, normal npm rules apply.
Node dependencies
Recipe extensions, scripts, and nested skill packages use normal npm metadata.
Put every module needed while the agent runs in dependencies:
{
"name": "spreadsheet-agent",
"type": "module",
"dependencies": {
"exceljs": "4.4.0",
"zod": "4.3.6"
},
"pi": {
"extensions": ["extensions/*.ts"]
}
}Install dependencies locally with your package manager and commit its lockfile.
Do not put runtime imports in devDependencies: managed runtimes install
production dependencies only. Pi packages supplied by the host are peers and
should not be duplicated in the recipe’s dependencies.
Python and system requirements
Use pi.runtime when recipe-owned code needs dependencies beyond the base
host. The declaration describes portable requirements; it does not contain
installation commands.
{
"name": "spreadsheet-agent",
"pi": {
"agents": ["agents/*.yaml"],
"runtime": {
"python": {
"project": "python",
"lockfile": "python/uv.lock",
"version": ">=3.12,<3.15",
"imports": ["pandas", "openpyxl"]
},
"system": {
"packages": [
{ "id": "document.pdf-tools", "version": "1" }
]
}
}
}
}For Python:
projectis a recipe-relative directory containingpyproject.toml;lockfileis the committeduv.lockinside that project;versionoptionally constrains the Python interpreter;importsoptionally names modules the runtime must import successfully before starting the agent.
The project and lockfile must exist and stay inside the recipe. The managed runtime uses frozen resolution and creates a recipe-local environment; it does not install into system Python or resolve an unlocked dependency graph.
System packages are versioned capability IDs provided by the runtime image.
They are not apt-get, Homebrew, or shell commands. A runtime that does not
provide every declared capability rejects the recipe before the first model
call.
Commit both pyproject.toml and uv.lock. When dependencies change,
regenerate and review the lockfile before committing the recipe.
The smallest recipe that runs is two files—a manifest with an empty pi block
and one agent:
{
"name": "my-agent",
"pi": {}
}name: agent # required
ai:
model: anthropic/claude-sonnet-4-6 # required; nothing else isAn empty pi block still finds agents/ by convention, so those two files
resolve. name and ai.model are the only required fields anywhere in the
format.
What package.json does not declare
package.json describes the portable recipe. Deployment configuration lives in
the separate runtime manifest,
.introspection/<runtime-slug>.yaml, which names
the runtime group, points at this recipe’s path, and declares
runtime.llm_mode, runtime.resources, and runtime.github — the workspace repositories the runtime’s tasks may check out
into workspace/repos/, plus the GitHub-Actions-style permissions ceiling on
the token minted for them. See
GitHub → Workspace repositories.
The conventional files/ directory and root .recipeignore control which
inputs accompany a managed task and which authoring-only paths stay out of the
deployed recipe. See Packaging a recipe.