Skip to Content
Platform
Agent Recipespackage.json manifest

package.json manifest

The manifest identifies the recipe and declares the portable resources it owns.

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;
  • skillsSKILL.md procedures 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, or prompts to get the directory of that name by convention. extensions and mcp are 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 pi is 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:

package.json
{ "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.

package.json
{ "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:

  • project is a recipe-relative directory containing pyproject.toml;
  • lockfile is the committed uv.lock inside that project;
  • version optionally constrains the Python interpreter;
  • imports optionally 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:

package.json
{ "name": "my-agent", "pi": {} }
agents/agent.yaml
name: agent # required ai: model: anthropic/claude-sonnet-4-6 # required; nothing else is

An 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.

Last updated on