ADR 0258: Trusted extensions may provide custom agents
- Status: Accepted for implementation
- Date: 2026-09-15
- Decision: D426
- Related: ADR 0214, ADR 0215,
07-plugins/16-trusted-extensions.md, Issue #401
Context
Trusted extensions run beside the Agent runtime and are the appropriate surface for providers that cannot be represented by a built-in pi-ai adapter. Issue #401 asks for model selection and custom agent/provider registration so a plugin can integrate services such as Command Code with its own endpoint and authentication flow.
The pinned pi-coding-agent API has registerProvider, but no registerAgent, and its provider registry assumes coding-agent-owned credentials and model persistence. Passing that registry through would bypass PI-Desktop's session binding and secret ownership boundaries.
Decision
- Add a PI-Desktop
registerAgentExtensionAPI member. A trusted extension registers an id, bounded model metadata, and either astreamorcompleteimplementation. The plugin owns endpoint, authentication, request serialization, and response conversion. - Keep the registration in the Agent sidecar. The host receives only the selected opaque provider id/model id and persists the session binding through the existing
session.configureflow. - Use namespaced
extension-agent:<encoded-agent-key>provider ids. On later turns the Electron launcher passes the binding as a placeholder provider; the sidecar reloads the trusted extension and reactivates the matching implementation. - Expose a read-only model registry projection to the extension context. It may list models and auth availability, but never returns host API keys, secret refs, OAuth tokens, arbitrary provider headers, or host provider internals.
registerProvideraccepts the same plugin-owned streaming shape as a compatibility alias. Literal provider credentials are not consumed by the host and no provider registration is written to the Host database or global defaults.- Registration is session-scoped and is removed with the runtime. Custom agents are available only to trusted extensions holding the existing high-risk
agent.extensiongrant.
Consequences
- Command Code and similar integrations can implement their own auth and wire protocol without an app release or a new Rust transport.
- Session model selection remains host-owned and observable through the existing
session:modelChangedevent. - Custom agent definitions are not visible in the ordinary provider Settings picker; a plugin may expose its own command or UI to select them.
- Trusted extension code has sidecar-level authority by design. Marketplace distribution remains subject to the existing signing/trust policy.
- The public ExtensionAPI contract is PI-Desktop-specific for
registerAgent; upstream pi API upgrades must preserve the adapter contract or add a compatibility translation.
Alternatives considered
Expose pi-coding-agent ModelRegistry directly
Rejected: it exposes credential resolution and assumes pi's persistence model.
Add every custom provider to Rust/SQLite
Rejected: the plugin owns the implementation and credentials, while Host storage must not persist opaque plugin transport code or secrets.
Register an executable subagent instead
Deferred to a separate API. This decision covers custom LLM/Agent transport, not a new autonomous worker or tool-permission profile.