pi-agent

claude_code 1 companion file
← Back

SKILL.md

---
name: pi-agent
description: >-
  Offload cheap, bulk, or parallelizable work from Claude Code to `pi` β€” a
  headless coding-agent CLI running on near-free Cloudflare Workers AI. Use when
  you (Claude Code) want to fan out mechanical edits, read-only recon,
  long-context digestion, or test/boilerplate generation onto cheap models
  instead of spending Opus tokens; or when the user says "use pi", "spawn pi",
  "offload to pi", "run this on the cheap models / Workers AI". Covers safe
  headless invocation, cost-verified model routing, output parsing, RPC
  steering, and parallel fan-out.
---

# pi-agent β€” offload work to pi on near-free Workers AI

`pi` (`@earendil-works/pi-coding-agent`, at `/root/.bun/bin/pi`) is a headless
coding-agent CLI with `read/bash/edit/write/grep/find/ls` tools. It is wired to
**Cloudflare Workers AI via an AI Gateway OpenAI-compatible endpoint**.
Cloudflare's catalog lists every model below as tool-capable, but the
pi→gateway→model *tool loop* does not always work in practice (see below).
Availability, context, ceilings, and price all change β€” confirm the current set
with `pi --list-models` (shows context Β· max-output Β· tool-calling Β· vision) and
read Cloudflare's Workers AI pricing page when a decision hinges on exact cost.

**Strategic frame:** Opus (Claude Code) is the scarce, high-IQ orchestrator; pi
is cheap muscle on capacity the user already pays for. Route token-wasteful,
parallelizable, or low-judgment work to pi. **The binding constraint is a small,
shared daily free-Neuron pool.** On Workers Paid, overage is a cheap soft cap
rather than a hard failure β€” but the pool is small, so favor the cheapest model
that clears the task's quality bar, reserve flagship models for escalation, and
keep every run bounded.

## ⚠️ Tested behavior (smoke tests, 2026-07-07) β€” read this first

Doc-level "function calling: Yes" is NOT the same as tool loops working through
the pi β†’ AI-Gateway β†’ model path. Actual results:

| Model | Pure text (no `-t`) | Tool loop (`-t read,…`) | Verdict |
|---|---|---|---|
| `gpt-oss-120b` | βœ… | βœ… executed first try | **reliable tool driver** |
| `gpt-oss-20b` | βœ… clean | ⚠️ prompt-sensitive: "Read X" leaked the call into its reasoning channel and did nothing; **"Use the read tool to open X" executed cleanly** | text-first; tools OK **with explicit tool phrasing** |
| `glm-4.7-flash` | untested | ❌ timed out at 100s, 0 tools | **don't use headless** until it passes a smoke test |

**Consequences for routing:**
- For work that needs pi to **use tools** (explore repo, edit files itself),
  default to **`gpt-oss-120b`**. If you use `gpt-oss-20b` to save cost, phrase
  the prompt with an explicit *"use the read/edit/grep tool"* instruction.
- The most robust and cheapest pattern is **text-in / text-out with NO tools**
  (`-nt`): pipe the file(s) in via `@file` or stdin, get the answer or the full
  new file content out, and let **Opus apply the change** with Write/Edit. This
  sidesteps gateway tool-calling entirely and lets you use the cheapest models.
  Prefer it for edits over pi's own `edit`/`write` tool.

## When to offload vs. keep

**Keep on Opus:** architecture, ambiguous debugging, API-contract design, D1/DO
schema migrations, anything irreversible or judgment-heavy.

**Offload to pi:** bulk mechanical edits (as text-out, Opus applies), read-only
recon, long-context digestion into a brief, test/boilerplate generation from a
spec Opus wrote, cheap second-opinion reviews, scratch exploration, drafting.

## Model routing (by role β€” confirm current models with `pi --list-models`)

Route on tool-loop *reliability* first (see the tested table above), then on
cost. Names below are today's picks, not permanent β€” prices and the catalog
change, so keep the cheap-vs-flagship split as the durable signal and verify the
specifics against `pi --list-models` and the pricing page.

| Task | Model | Why |
|---|---|---|
| **Pure text-in/out** β€” digest, summarize, draft, classify, review, generate file content | `@cf/openai/gpt-oss-20b` | Cheap and tested-clean on pure text; no tool loop means no gateway flakiness |
| Long-context digest / vision (text-out) | `@cf/google/gemma-4-26b-a4b-it` | Largest-context cheap model, and has vision |
| Recon-scale input (text-out, small scope) | `@cf/qwen/qwen3-30b-a3b-fp8` | Cheapest input; recon is input-heavy so it barely dents the pool |
| **Agentic / tool-using** β€” pi explores or edits files itself | `@cf/openai/gpt-oss-120b` | The one model with a tested-reliable gateway tool loop |
| Tool-using on the cheap | `@cf/openai/gpt-oss-20b` | Works **only with explicit "use the X tool" prompts** β€” cheaper but finicky |
| Coding-flavored alt | `@cf/zai-org/glm-4.7-flash` | ⚠️ timed out in testing β€” smoke-test before any headless use |
| Vision | `@cf/google/gemma-4-26b-a4b-it` / `@cf/moonshotai/kimi-k2.7-code` | Only these two confirm vision |
| **Escalation only** (never default) | `@cf/zai-org/glm-5.2`, `@cf/moonshotai/kimi-k2.7-code` | The flagship, most-expensive models β€” one fat run can eat a big slice of the daily pool |

Model IDs resolve under pi's default provider (`cloudflare-workers-ai`), so the
short `@cf/...` form works. Full form: `cloudflare-workers-ai/@cf/openai/gpt-oss-20b`.

## Core invocation patterns

**Sandbox tools with `-t` (or `-nt` for none), and use `--no-session` for
ephemeral offload.**

```bash
# BEST for edits: text-out, no tools, Opus applies the result.
# Pipe the current file in; get the full new file content back.
pi -p -nt --no-session --model @cf/openai/gpt-oss-20b \
   "Here is src/schemas/income.ts:\n$(cat src/schemas/income.ts)\n\nAdd an optional \`source\` field mirroring src/schemas/expense.ts. Output the COMPLETE new file, nothing else." \
   > /tmp/income.new.ts   # then Opus reviews + writes it

# Pure-text digest via stdin
cat taskNotes/accounts-balance-formula/*.md | \
   pi -p -nt --model @cf/google/gemma-4-26b-a4b-it \
   "Summarize the open decisions in <=300 words."

# Read-only recon β€” let pi use tools; use gpt-oss-120b for reliability,
# or gpt-oss-20b with EXPLICIT tool phrasing.
pi -p --no-session --model @cf/openai/gpt-oss-120b \
   -t read,grep,find,ls \
   "Use grep/find to list every file under src/routes that references org memberships. Return paths only."

# Structured output when you need to parse tool calls / final text
pi -p --mode json --no-session --model @cf/openai/gpt-oss-120b \
   -t read,edit,write "<task>" 2>/dev/null \
   | jq -rc 'select(.type=="message_end")'
```

- **Text mode (`pi -p`)** prints the final assistant text to stdout. If the model
  emits no final message (e.g. it "thought" a tool call but never issued one),
  stdout is **empty** β€” check `--mode json` for what happened. **JSON mode**
  streams LF-delimited events (`session`, `agent_start`, `message_*`,
  `tool_execution_*`, `agent_end{messages}`); a `tool_execution_start` count of
  0 on a tool task means the tool loop failed. Non-zero exit / exit 124
  (timeout) = failure; stderr carries diagnostics.
- Add `-a` / `--approve` to trust project-local `.pi/` extensions, skills, and
  agents for the run.
- Sandbox tighter with `--no-builtin-tools` (keep only custom/extension tools)
  or `--no-tools`/`-nt` (all off). Deny specific tools with `-xt bash`.

## Parallel fan-out (the flagship pattern)

Opus writes a precise per-file changeset, then dispatches one pi run **per file
in parallel** β€” each isolated in context and cost β€” then reviews and applies.
Prefer the **text-out variant** so cheap models work and Opus stays in control
of what lands on disk:

```bash
for f in src/routes/income.ts src/routes/expense.ts src/routes/reports.ts; do
  ( pi -p -nt --no-session --model @cf/openai/gpt-oss-20b \
      "File $f:\n$(cat $f)\n\n<scoped change>. Output the COMPLETE new file only." \
      > /tmp/pi.$(basename $f) ) &
done
wait
# Opus now diffs each /tmp/pi.* against the original, sanity-checks, and Writes it.
```

If you instead let pi edit files directly (`-t read,edit,write`), use
`gpt-oss-120b` for a reliable tool loop, and typecheck the aggregate diff.

## RPC mode β€” long-lived, steerable worker

When you want to steer or abort mid-run and watch spend, spawn a persistent
worker instead of one-shot print:

```bash
pi --mode rpc --no-session --model @cf/openai/gpt-oss-120b
```

Write JSON commands one-per-line to stdin (`prompt`, `steer`, `follow_up`,
`abort`, `set_model`, `get_session_stats` β†’ tokens+cost, `get_last_assistant_text`,
`fork`, `get_messages`); read the same streamed events back. **Framing is strict
LF-only JSONL** β€” split on `\n`, strip trailing `\r`, and do **not** use Node
`readline` (it breaks on U+2028/U+2029). `get_session_stats` lets Opus watch cost
and `abort` a runaway.

## Guardrails

- **Never default to a flagship / most-expensive model** (`glm-5.2`,
  `kimi-k2.7-code`) β€” a single fat run can burn a big slice of the daily pool.
  Escalate to them by hand only.
- **Tool loops are the flaky part, not the models.** Prefer text-out (`-nt`) and
  let Opus apply edits. When you do need tools, use `gpt-oss-120b`; only use
  `gpt-oss-20b` with explicit "use the X tool" phrasing; smoke-test any other
  model's 3-tool loop before trusting it headlessly (`glm-4.7-flash` timed out).
- **Always pass `-t` or `-nt`** to scope tools; never hand a broad task write
  access it doesn't need.
- **Keep every run bounded** β€” a looping or tool-failed run still spends input
  tokens against the shared pool. Fan out over many small, scoped runs rather
  than one open-ended one. If a gateway dynamic route is already configured,
  target it with `--model dynamic/<route>` to inherit its budget and rate limits.

## Quick reference

```
pi -p                      one-shot, prints final text, exits
--mode json|rpc            machine-readable events / bidirectional protocol
--model @cf/...            pick the model (short form uses default provider)
-t a,b   -xt a,b           allow / deny tools
-nt  -nbt                  no tools / no builtin tools  (prefer -nt for text-out)
--no-session               ephemeral (don't save)
-c  -r  --session <id>     continue / resume / target a session
--fork <id>                branch a session non-destructively
-a                         trust project-local .pi resources
--list-models [q]          list available models
@file...                   attach files as context
```

Companion Files

references/usecases.md
7 KB text/markdown

Danger Zone

Deleting this skill will remove all associated files. This action cannot be undone.

Owner
Prasham Trivedi
Created
7/9/2026, 6:35:50 PM
Last Updated
7/9/2026, 6:35:50 PM
πŸ†” Skill ID
119lnvd-atQvUdyVYo1WQ