Deploying
The recipe does not change. Who supplies credentials and endpoints does.
An agent recipe carries no deployment descriptor, so nothing is rewritten when it moves. The host supplies what you set up by hand locally, and none of that local setup travels with the directory.
| Locally | On a host | |
|---|---|---|
| Model keys | Environment variables you export | A credential store the host passes in |
| MCP endpoints | .pi/mcp.local.json, uncommitted | Bindings the host synthesizes per run |
| MCP auth | You run the OAuth flow, once per machine | The host terminates it, once per connection |
| Child agents | In-process | Your own durable controller |
| Questions to a user | A terminal dialog | Your interrupt surface |
| What the agent sees | One headless mcp command | Identical |
Credentials
A host passes credentials to the constructor instead of leaving them to be read from the environment. Nothing in the recipe names a variable, so this needs no change to the package.
Construction fails closed. A provider with no resolvable credential raises RecipeCredentialError before the session exists, so a misconfigured deployment fails at startup rather than on a user's first message.
MCP endpoints
Two shapes, and the difference is where the upstream credential lives.
Bind per run
The host adapts its own connection registry into the same binding shape and passes it inline, so there is no file in the workspace at all.
Terminate auth at the edge
Or point the binding at your own gateway and let it hold the upstream credential. The session then carries a short-lived token for your gateway and never the provider's, and the OAuth dance a local user does by hand happens once at the platform edge instead of once per workspace. Use this for multi-tenant runtimes, where per-workspace browser flows are not available.
Either way the agent's instructions are unchanged, because the agent was never told how credentials arrive. It sees one rule in both worlds: MCP is headless, and a missing connection is authentication_required with an instruction to ask a human.
Agent runs
Child agents run in-process by default, which is right for a CLI and for tests. A long-lived host usually wants them durable instead: queued, observable, and able to outlive one process. Implement AgentRunController and pass it as runController, and no recipe changes. The SDK reference has the contract and its lifecycle.
Questions from a run
A recipe tool that asks the user something works in a terminal for free. In your runtime you implement the interrupt contract once, and every recipe you deploy gets a working question without knowing what your surface is. See Interactions.
What never travels
.pi/mcp.local.jsonand.pi/mcporter.json.- Environment variables you exported in your shell.
- Cached OAuth tokens from your local mcporter config.
- The workspace itself. A host provisions its own.
What Recipes owns, what the host owns
| Recipes | Host |
|---|---|
| Package and agent semantics | Credentials and transport |
| The immutable resolved graph | Sandbox and task lifecycle |
| Model, tool, skill, prompt, extension and MCP policy | Files and uploads |
| Pi session construction | Memory and workspace |
| The agent-run controller contract | Persistent run artifacts |
| Lightweight in-process agent runs | Scheduling and rehydration |
| Session-local cleanup | History, retries, interrupts and compaction policy |
| OTel provider, processors and exporters |