Skip to content

Add pi provider backend for extended provider coverage #78

Description

@jrswab

Summary

Pi (@mariozechner/pi-coding-agent) supports 30+ LLM providers with maintained model lists, auth handling, streaming, and retries. Axe currently maintains ~6 providers manually. We should add an optional "pi backend" provider that shells out to pi --mode rpc, giving axe users access to pi's entire provider ecosystem without sacrificing axe's architecture.

Motivation

  • Provider maintenance is a significant ongoing burden
  • Users want providers axe doesn't support (DeepSeek, Groq, Cerebras, Mistral, etc.)
  • Pi keeps model lists updated with every release
  • Pi handles auth, OAuth, and base URL resolution for 30+ providers
  • This would be optional — native providers remain the default

Proposed Design

How It Works

  1. User configures a pi-backed agent with a special provider prefix:

    model = "pi/anthropic/claude-sonnet-4"
    # or
    model = "pi/openai/gpt-4o"
    # or
    model = "pi/groq/llama-3.3-70b"
  2. Axe detects the pi/ prefix and delegates to the pi RPC backend

  3. Axe spawns pi --mode rpc --no-session --provider <provider> --model <model>

  4. Communicates via pi's JSONL RPC protocol over stdin/stdout

  5. Translates pi events into axe's Provider interface

Pi RPC Protocol (Brief)

  • Commands sent as JSON objects to stdin, one per line
  • Events streamed as JSON lines to stdout
  • Key commands: prompt, steer, abort
  • Key events: message_update, tool_execution_start/end, turn_start/end

See: https://github.com/badlogic/pi-mono/blob/main/docs/rpc.md

Provider Interface Mapping

Axe Interface Pi RPC Equivalent
Send(ctx, *Request) {"type":"prompt","message":...}
SendStream(ctx, *Request) Same + stream message_update events
Tool definitions Passed via --tools flag or set_tools command
ToolResult Returned in tool_execution_end events
Token counts May not be available for all pi providers

Configuration

Add to global config (config.toml):

[providers.pi]
# Optional: path to pi binary (default: pi in $PATH)
binary = "/usr/local/bin/pi"
# Optional: additional flags passed to pi
args = ["--thinking", "medium"]

Or via environment:

AXE_PI_BINARY=/path/to/pi

Requirements

  • Pi must be installed (npm install -g @mariozechner/pi-coding-agent)
  • User must configure API keys via pi's auth system or env vars
  • Pi handles provider auth, so axe does not need to know provider-specific keys

Fallback Behavior

  • If pi binary is not found, return a clear error suggesting npm install -g @mariozechner/pi-coding-agent
  • If pi exits unexpectedly, return the stderr output in the error
  • If pi returns an unsupported provider error, surface it clearly

Acceptance Criteria

  • New pi provider type in axe's provider registry
  • RPC client that speaks pi's JSONL protocol
  • Supports both streaming and non-streaming modes
  • Tool definitions forwarded to pi correctly
  • Tool results returned to axe correctly
  • Sub-agent delegation still works (pi backend agents can call sub-agents)
  • Budget tracking works (best-effort token counting)
  • Tests with mocked pi RPC process
  • Documentation: setup, configuration, supported providers

Open Questions

  1. Should we require a specific minimum pi version?
  2. How do we handle pi's extension loading in RPC mode? (extensions may add tools/commands)
  3. Should the pi backend support pi skills/prompts, or keep axe's system prompt pure?
  4. Token counting: pi may not expose token counts for all providers. Should axe estimate, or treat budget as best-effort?

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions