Files
bot-bottle/docs/prds/0058-pi-agent-provider.md
T
didericis 504144eb9c
lint / lint (push) Failing after 1m58s
test / unit (push) Successful in 41s
test / integration (push) Successful in 24s
Update Quality Badges / update-badges (push) Successful in 1m27s
fix(pi): prepare runtime state and agent workdir
2026-06-10 00:02:28 -04:00

4.9 KiB

PRD 0058: Add built-in Pi agent provider

  • Status: Active
  • Author: codex
  • Created: 2026-06-09
  • Issue: #221

Summary

Add pi as a built-in agent_provider.template. The provider runs the Pi coding-agent CLI, provisions its agent config under ~/.pi/agent, and writes a provider settings file that targets an unauthenticated Ollama-compatible server.

The default settings assume an Ollama server at http://ollama:11434/v1, using the openai-completions API with a dummy API key because Ollama ignores it. Users can override the provider id, base URL, model list, API key, API-key env reference, API type, and compatibility flags through a new agent_provider.settings object.

Problem

bot-bottle currently ships Claude and Codex as built-in agent providers. Pi is a useful third harness, but using it today requires a custom provider plugin and a custom image. That repeats boilerplate for prompt copying, skill copying, provider config, and runtime registration.

Pi's local-model path is also easy to misconfigure: its custom-model docs require ~/.pi/agent/models.json, an API entry, at least one model id, and a dummy apiKey for Ollama even though the server does not authenticate. bot-bottle should generate that shape consistently.

Goals / Success Criteria

  • agent_provider.template: pi is accepted as a built-in provider.
  • bot_bottle/contrib/pi/ provides a Pi image and PiAgentProvider.
  • Pi receives the bot-bottle prompt at ~/.bot-bottle-prompt.txt and starts in print-mode prompt delivery like Codex.
  • Pi skills are copied into ~/.pi/agent/skills/<name>/.
  • Pi provider settings are configurable from the bottle manifest via agent_provider.settings.
  • The default Pi provider settings configure an unauthenticated Ollama-compatible server.
  • Unit tests cover manifest parsing, runtime selection, plan generation, prompt, skills, and provider provisioning.

Non-goals

  • Managing or launching an Ollama server.
  • Authenticating to Ollama or any remote Pi provider.
  • Forwarding host Pi credentials.
  • Implementing Pi extensions or MCP registration.
  • Changing Claude or Codex provider behavior.

Design

Manifest

Extend agent_provider with an optional settings object. It is currently only supported for built-in pi.

Supported keys:

  • base_url: string, defaults to http://ollama:11434/v1
  • provider: string, defaults to ollama
  • api: string, defaults to openai-completions
  • api_key: string, defaults to ollama
  • api_key_env: string, optional host env var name for egress auth injection
  • models: non-empty array of strings, defaults to ["qwen2.5-coder:7b"]
  • context_window: positive integer, defaults to 4096; this is the Ollama runtime context, and bot-bottle subtracts max_tokens before writing Pi's contextWindow so output space is reserved
  • max_tokens: positive integer, defaults to 1024
  • max_tokens_field: max_tokens or max_completion_tokens, defaults to max_tokens
  • supports_developer_role: boolean, defaults to false
  • supports_reasoning_effort: boolean, defaults to false

The snake-case manifest keys are converted into Pi's JSON field names: baseUrl, apiKey, contextWindow, maxTokens, supportsDeveloperRole, and supportsReasoningEffort. context_window describes the server's total context; Pi's contextWindow receives context_window - max_tokens because Pi uses it as an input compaction target.

api_key and api_key_env are mutually exclusive. When targeting a hosted provider through bot-bottle's egress sidecar, omit api_key and set api_key_env to the host env var that holds the API key. The generated models.json receives only an egress-placeholder API key, and the egress route injects the real Authorization header from the sidecar env. For example, OpenRouter can use provider id openrouter with api_key_env: OPENROUTER_API_KEY, keeping the key out of the agent env and models.json.

Provider

PiAgentProvider.provision_plan writes models.json into the per-launch state directory and returns an AgentProvisionPlan that copies it to ~/.pi/agent/models.json. The provider also declares an unauthenticated egress route for the configured base URL host so the egress layer can allow the Ollama endpoint.

The Pi runtime uses:

  • command="pi"
  • prompt_mode="append_system_prompt"
  • image="bot-bottle-pi:latest"
  • bypass_args=()
  • resume_args=()
  • remote_control_args=()

The Dockerfile installs @earendil-works/pi-coding-agent globally from npm and keeps the same Debian/node base shape as the existing provider images.

Supervise MCP

Pi does not have built-in MCP support in the current public docs, so provision_supervise_mcp is a no-op. This keeps Pi bottles launchable with supervise: true while preserving the explicit non-goal of implementing Pi extensions.

Merge rule(s)

This PR can merge when the focused unit tests pass and the PRD status is flipped from Draft to Active in the final implementation commit.