Skip to content

Epic: Pluggable model-agnostic agent runners (anthropic | pi) #520

@gewenyu99

Description

@gewenyu99

Epic: pi agent runner — pi.dev coding agent behind the wizard-runner flag

Summary

Add a second agent backend, pi, built on pi.dev
(@earendil-works/pi-coding-agent) — a Claude-Code-style coding agent —
selectable at runtime via a multivariate wizard-runner flag (anthropic | pi,
default anthropic). This de-risks the wizard's dependency on a single agent loop
(@anthropic-ai/claude-agent-sdk): an interchangeable coding-agent backend runs
against the same PostHog LLM gateway, the same skills, and the same TUI, so the two
can be A/B'd in production.

Why Pi

  • It's a coding agent — it owns the tool-calling loop and ships its own
    Read/Write/Edit/Bash tools, so we wrap it rather than rebuild a loop.
  • Native file-based skillsSKILL.md + frontmatter, progressive disclosure,
    discovered from scanned skill directories. This is the context-mill skill model,
    so a framework skill loads by placing it in a directory Pi scans.
  • Speaks our gateway directlyregisterProvider({ baseUrl, apiKey, api: 'anthropic-messages', headers }) matches the PostHog gateway transport (Anthropic
    Messages protocol, bearer auth, Bedrock-fallback + metadata/flag headers).
  • In-process SDKcreateAgentSessionsession.prompt(text)
    session.subscribe(event); custom tools via defineTool.

Architecture

Two orthogonal axes:

Axis Flag Forks
Mode wizard-orchestrator linear vs orchestrator
Backend wizard-runner anthropic vs pi

Backend selection lives inside the linear mode. A backend is a drop-in for
runLinearProgramAgentBackend.run(session, config: ProgramRun, programConfig, boot: BootstrapResult) — and selectBackend(flags) resolves wizard-runner to one
(unknown/missing → anthropic). anthropic is the control (the claude-agent-sdk
path).

The pi backend:

  • Registers the PostHog gateway as an anthropic-messages provider (baseUrl from
    getLlmGatewayUrlFromHost(host), apiKey = posthog token, headers =
    Bedrock-fallback + wizard metadata/flags). Model id matches the anthropic
    backend for a clean A/B.
  • System prompt = wizard commandments (DefaultResourceLoader system-prompt
    override).
  • Skills: installs the resolved framework skill into a Pi-scanned skill dir so Pi
    discovers it.
  • Wizard capabilities (env-file ops, wizard_ask, PostHog data ops) as Pi tools.
  • Streams session.subscribe events onto the shared stream→TUI bridge; maps errors
    to AgentErrorType.
  • Fail-closed security (canUseTool allowlist + YARA) on tool execution, matching the
    anthropic path.

Sub-issues

Open questions (resolve in early sub-issues)

  • Does Pi mount MCP servers, or are PostHog data ops better expressed as custom
    tools?
  • Does Pi's provider append /v1/messages to baseUrl, or is the full path needed?
  • How does Pi resolve a custom-provider model without interactive auth in
    headless/CI runs?
  • How is per-tool gating exposed for the security layer (canUseTool + YARA)?

Local testing (mprocs)

Running a non-anthropic backend locally has three requirements the harness must
satisfy:

  • Build channel. Flag overrides and the active runner are only meaningful in a
    non-production build, but local runs need real prod-cloud OAuth/hosts. The CI
    build channel (WIZARD_BUILD_NODE_ENV=ci) satisfies both — it keeps
    WIZARD_CI_FLAG_OVERRIDES live and targets prod cloud. A wizard-build-ci mproc
    builds it.
  • Backend selection. Select the backend with
    WIZARD_CI_FLAG_OVERRIDES='{"wizard-runner":"pi"}' (or anthropic) in the
    workbench .env — a flag, not a code change — so both backends run from one build.
  • Dependencies & observability. The local MCP (localhost:8787) must be running
    for the full PostHog toolset; the backend degrades when it isn't. Runner
    diagnostics go to the log file (the TUI owns the console), and each run dumps its
    context (system prompt, tools, skills, model) for side-by-side comparison.

Canonical flow:

# wizard-workbench/.env
WIZARD_PATH=/path/to/wizard
WIZARD_CI_FLAG_OVERRIDES={"wizard-runner":"pi"}
# mprocs: wizard-build-ci → mcp (localhost:8787) → wizard-run

Acceptance

  • pi runs a real integration end-to-end through the gateway, behind
    wizard-runner=pi, default-off; anthropic unchanged.
  • Skills load via Pi's native discovery (same framework skill as anthropic).
  • Security parity (canUseTool + YARA) before any non-zero ramp.
  • A documented, repeatable mprocs test flow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions