Pi カスタムプロバイダ設定:コスト $0 表示と 500 エラーの直し方

Pi はカスタムプロバイダだと毎セッション $0 と表示し、Anthropic 系のモデルは推論を有効にすると 500 を返す。どちらもバグではなく設定。pi 0.84.1 で実測。

Pi カスタムプロバイダ設定:コスト $0 表示と 500 エラーの直し方

Pi には 36 の API キープロバイダと 6 つのサブスクリプションログインが最初から配線済みで、それでもあなたが使いたい先はそこに入っていない可能性が十分にあります。 別の場所に向けるのは JSON ファイル 1 つと 5 分ほどの作業で、そこは簡単なほうです。面白いのはそのあとに起きる 3 つの問題で、どれも自分から「これは設定の問題です」とは名乗りません。

以下はすべて 2026-08-18 に macOS 上の pi 0.84.1 で、OpenAI 互換エンドポイント経由で 131 モデルを提供するゲートウェイに対して実行した結果です。

設定ファイル:      ~/.pi/agent/models.json
プロバイダの項目:  baseUrl、api、apiKey、models[]
プロトコル:        openai-completions、openai-responses、
                    anthropic-messages、google-generative-ai
環境変数からキー:  "$OFOX_API_KEY"
キーチェーンから:  "!security find-generic-password -ws ofox"
未登録のモデル:    警告付きで動く、コンテキストは 128K
コスト計算:        cost ブロックを足すまで $0.00
推論 + Claude:     supportsDeveloperRole: false を足すまで 500
組み込みの上書き:  baseUrl のみ、/v1 の手前で止める
再読み込み:        自動、/model を開くたび

この設定で何ができて、何ができないのか?

ゲートウェイが扱うすべてのモデルを、Pi 自身のループの中で、1 本のキーに課金しながら使えます。 手に入らないのは、ゲートウェイから取得したモデル一覧、機能するコスト表示、そしてモデルが本来の 8 分の 1 のコンテキストで静かに動いているときの警告です。

すぐ動くもの:

  • OpenAI chat completions、OpenAI Responses、Anthropic Messages、Google Generative AI のいずれかを話すエンドポイント。
  • /model によるセッション途中のモデル切り替え。ピッカーを開くたびにファイルを読み直すので、プロバイダをまたいでも切り替わります。
  • 環境変数やシェルコマンドから取り出すキー。おかげで秘密情報を JSON に置く必要がありません。
  • 思考レベル、画像入力、ツール呼び出し。ただしモデルごとに宣言することが前提です。

すぐには動かないもの:

  • カタログの取得はしない。 すべてのリクエストを記録するローカルサーバーに向けたところ、Pi は 1 回の実行につき /v1/chat/completions へ POST を 4 回送り、/v1/models への GET は 1 回もありませんでした。あなたが打ち込んだものが、Pi の知るすべてです。
  • コストの数字は出ない。 トークン数は正確で、金額はゼロです。単価を自分で書くまでは変わりません。
  • プロトコルの推測はしない。 組み込みプロバイダを誤ったベースパスで上書きすると、返ってくるエラーはプロトコルではなく認証について語ります。

Pi をゲートウェイに向けるべきか、組み込みプロバイダで済ませるべきか?

すでに Anthropic、OpenAI、Google に直接支払っているなら組み込みを使ってください。使いたいモデルがその中にないとき、あるいはベンダーごとのダッシュボードよりも全ツールを 1 本のキーで通すことのほうが重要なときに、カスタムプロバイダを足します。

カスタムプロバイダが元を取る場面:

  • どの一次プロバイダも扱っていないモデルを動かす場合。実務上はほとんどの中国製オープンウェイト旗艦モデルと、公式ではなくホスティング経由のモデルが該当します。
  • すでに Claude Code や Codex CLI をゲートウェイ経由にしていて、4 本ではなく 1 本のキーと 1 通の請求にまとめたい場合。
  • 安価な既定モデルと高価なエスカレーション用モデルを A/B したいが、後者のために 2 つ目のアカウントを開きたくない場合。

ファイルを書くまでもない場面:

  • ベンダーもプランも 1 つだけ。/login は ChatGPT Plus と Pro、Claude Pro と Max、GitHub Copilot、xAI、OpenRouter を含む 6 種類のサブスクリプションを直接カバーします。ここまでの作業は一切不要です。
  • ローカルランタイムを使っている。Ollama、vLLM、llama.cpp はドキュメントに載っているケースで、baseUrl とモデル ID があれば足り、本記事の残りは要りません。
  • 組み込みプロバイダのキーを変えたかっただけ。それは 1 行の上書きで、記事の終盤で扱います。

打ち切り条件: pi --list-models にすでに動かしたいモデルが出ているなら、このタブは閉じて構いません。ここにあるのはすべて、Pi が知らないモデルを足すための手順です。

始める前に何が必要か?

Node 22 以降、キー、そして一度は curl で叩いたことのあるベース URL です。

必要なもの今回使ったもの備考
Node.js24.14.1パッケージの宣言は engines: node >=22.19.0
Pi0.84.1(最新は 0.84.2)@earendil-works/pi-coding-agent、MIT
エンドポイントhttps://api.ofox.ai/v1/models だけでなく /chat/completions に応答すること
キーゲートウェイのキー 1 本$OFOX_API_KEY に保持し、直書きしない
モデル ID正確な文字列ベンダーの ID ではなくゲートウェイの ID

まだ入れていない場合:

npm install -g @earendil-works/pi-coding-agent
pi --version

ファイルを書く前に決めておく価値があることが 1 つあります。選んだプロバイダ名は、以後すべての --provider フラグとすべてのセッション記録に残ります。 あとで改名すると、古いセッションはもう存在しないプロバイダを指すことになります。

Pi にカスタムプロバイダを追加するには?

1 つのファイルに 4 つの項目、そして動作を証明するコマンド 1 本です。

ステップ 1:プロバイダブロックを書く

~/.pi/agent/models.json にすべてが入ります。最小構成のエントリはこれです:

{
  "providers": {
    "ofox": {
      "baseUrl": "https://api.ofox.ai/v1",
      "api": "openai-completions",
      "apiKey": "$OFOX_API_KEY",
      "models": [
        { "id": "deepseek/deepseek-v4-flash", "contextWindow": 1000000, "maxTokens": 384000 }
      ]
    }
  }
}

まず手を伸ばすべきは openai-completions です。もっとも広く実装されている形式で、今回のゲートウェイでは同じモデルに対して openai-responses も動きましたが、これは他所で当然に成り立つ話ではありません。

ステップ 2:キーはファイルではなく環境に置く

export OFOX_API_KEY=sk-...

apiKey の解決方法は 3 つあります。リテラル文字列、$VAR または ${VAR} の展開、そして !command(シェルコマンドを実行して標準出力を使う)です。共有マシンで使うべきは 3 つ目です:

"apiKey": "!security find-generic-password -ws ofox"

ステップ 3:Pi がモデルを認識しているか確認する

pi --list-models ofox
provider  model                       context  max-out  thinking  images
ofox      deepseek/deepseek-v4-flash  1M       384K     no        no
ofox      moonshotai/kimi-k3          1M       1M       no        no
ofox      z-ai/glm-5.2                1M       128K     yes       no

これらの列はゲートウェイではなくあなたのファイル由来です。エントリから contextWindowmaxTokens を消せば、同じコマンドが 128K16.4K を表示します。これが Pi のドキュメントにある既定値です。推論するモデルの thinking が no になっているなら、それは宣言の漏れであって、エンドポイントが拒んでいるわけではありません。

ステップ 4:ディスクに触る処理を走らせる

print モードがもっとも速い証明になります。補完エンドポイントだけでなくツールループを動かすからです:

pi --provider ofox --model deepseek/deepseek-v4-flash -p \
  "Read buggy.py, run it, and state the one-line bug. Do not edit files."

add 関数に return a - b と書かれた 2 行のファイルを置いた作業用ディレクトリで、DeepSeek V4 Flash はファイルを読み、bash ツールでインタプリタを実行し、一発で正解しました。統合テストとしてはこれで十分です。ファイル読み取り、シェル実行、回答の 3 点が通っています。

openai-responses でも動くのか?

今回のゲートウェイでは、同じモデルについて、プロトコル名だけを変えて動きました。 "api": "openai-completions""api": "openai-responses" に差し替えて同じプロンプトを流すと、同じ答えが返ってきます。

ただし一般化はしないでください。Responses に対応するかどうかはゲートウェイ単位ではなくホスティング側がモデル単位で決めるので、あるモデルには /v1/responses を返すエンドポイントが、次のモデルには Responses のルートをまったく持たないということが起こります。openai-completions がもっとも広くカバーされる形式で、特定のモデルが要求しない限り他を選ぶ利点はありません。この問いを突きつけてくるのは Codex CLI です。Responses しか話さないからです。

使えないキーなのに pi auth check が ready と言うのはなぜか?

キーが存在するかを見ているだけで、有効かどうかは見ていないからです。 わざと無効なキーをプロバイダに設定して尋ねました:

pi auth check --provider ofox
# ready

同じ設定で、次のリクエスト:

401: {"message":"Invalid or expired API key","type":"invalid_api_key","code":401}

ready の意味は、Pi が apiKey の枠に何かを解決できたということだけです。環境変数のスペルチェック程度に扱ってください。本当の準備確認はステップ 4 です。

Pi がどのセッションでも $0 と報告するのはなぜか?

カスタムプロバイダには価格表がなく、Pi はそれを創作しないからです。 トークンの記録は正確です。最初の実行の 2 ターン分について Pi が書いた使用量の記録を、~/.pi/agent/sessions/ 配下のセッションファイルからそのまま引きます:

ターンinputoutputcacheReadreasoningtotalcost
12,8401220122,962$0.00
252562,94403,052$0.00

この表では 2 つを切り分ける必要があります。cacheRead の値は本物です。2 回目の呼び出しでゲートウェイが prompt_tokens_details.cached_tokens を返し、Pi がそれを記録しました。cost の列は本物ではなく、そもそも存在しません。モデルのエントリが単価を宣言していないので、cost 配下のすべての項目がゼロのままなのです。

追記すれば計算が動き出します:

{
  "id": "anthropic/claude-sonnet-5",
  "contextWindow": 1000000,
  "maxTokens": 128000,
  "cost": { "input": 2, "output": 10, "cacheRead": 0.2, "cacheWrite": 2.5 }
}

単価は 100 万トークンあたりで、モデル提供元ではなく実際に接続している事業者の価格ページから取ります。次の Claude Sonnet 5 の実行では入力 4,111、出力 4 トークンが記録され、$0.008222$0.00004 の合計 $0.008262 と算出されました。これはそれぞれのトークン数に 100 万あたり $2 と $10 を掛けた値です。この計算は Pi がローカルで行うので、数字の正直さは入力した単価の正直さまでです。モデルメーカーではなくゲートウェイの単価を入れ、ページが変わったら見直してください。

contextWindow も同じです。Sonnet 5 はこのゲートウェイでは 1M コンテキストのモデルなので、エントリにそう書く必要があります。書かなければ 128K の既定値が静かに引き継がれます。

モデルが「unsupported message role: developer」で失敗するのはなぜか?

reasoning: true によって Pi がシステムプロンプトを developer ロールのメッセージとして送るからで、そのロールをすべての上流が受け付けるわけではないからです。 失敗の出方は派手で、サーバー障害のように見えます:

500: {"code":null,"message":"Request error: failed to convert messages:
unsupported message role: developer","param":null,"type":"api_error"}

この文字列のどこにもあなたの設定を指すものはありません。だからこそ、きちんと切り分ける価値があります。同じゲートウェイ、同じモデルで、1 項目ずつ変えて 3 回実行しました:

モデルのエントリ結果
reasoning: true500、unsupported message role: developer
reasoning: truecompat: { supportsDeveloperRole: false } を追加動く
reasoning: false動く

つまり引き金は developer ロールで、2 つの修正はコストが異なります。同じ 3 つの設定を、リクエストボディを記録するローカルサーバーに向けると、何が変わるのかがはっきりします:

モデルのエントリmessages[].role送信された reasoning_effort
reasoning: true["developer", "user"]"medium"
supportsDeveloperRole: false を追加["system", "user"]"medium"
reasoning: false["system", "user"]なし

compat のスイッチはシステムプロンプトを system メッセージに戻しつつ reasoning_effort を残すので、思考は生き延びます。reasoning: false でもエラーは消えますが、それは reasoning_effort をリクエストから丸ごと落とすからで、たいていは割に合わない取引です。

同じキャプチャは maxTokensField についてよく聞かれる疑問にも答えます。openai-completions では Pi は max_tokens ではなく max_completion_tokens を送ります。エンドポイントが古い項目しか理解しないなら、切り替えるべきはこのスイッチです。

このロールが拒まれるのはカタログの一部だけです。同じゲートウェイ、同じ reasoning: true、3 つのモデルファミリー:

モデルreasoning: true の結果
DeepSeek V4 Flash動く
GLM 5.2動く
Claude Sonnet 5supportsDeveloperRole: false を入れるまで 500

パターンを決めているのは上流の形式であって、ゲートウェイの方針ではありません。Anthropic の API に developer ロールは存在しないので、OpenAI 形式のリクエストを Messages に変換するゲートウェイには対応づける先がありません。OpenAI 形式の上流はそのまま受け取って進みます。これは Codex CLI が空のツール説明を送り、検証する上流と無視する上流に分かれるのと同じ種類の問題で、9 つの harness を 1 つのゲートウェイで試したときにも遭遇しました。教訓は毎回同じです。クライアントとエンドポイントの言い分が食い違ったら、設定を変える前にボディを読むことです。

Pi のドキュメントには同じ系統のスイッチがあと 2 つ挙がっています。推論パラメータを拒むサーバー向けの supportsReasoningEffort と、max_tokens ではなく max_completion_tokens を求めるサーバー向けの maxTokensField です。思考を有効にした瞬間にモデルが 400 を返すなら、次に試すのはこの 2 つです。

すべてのモデルを列挙する必要はあるか?

ありません。131 個あるゲートウェイでは、やろうとすべきでもありません。 Pi が見たことのない ID でも動きます:

pi --provider ofox --model z-ai/glm-5.2 -p "say ok"
# Warning: Model "z-ai/glm-5.2" not found for provider "ofox". Using custom model id.
# ok

このフォールバックが、5 行の設定と 500 行の設定を分けます。同時に、隠れたコストもあります。未登録のモデルは Pi の既定値、ドキュメント上は 128,000 コンテキストと 16,384 最大出力を引き継ぎ、pi --list-models はこれらを省略したエントリに対してまさにその 2 つの数字を表示します。自動圧縮は contextTokens > contextWindow - reserveTokens で発火し、reserveTokens の既定は 16,384 なので、1M コンテキストのモデルは 100 万近くではなく 111,600 トークンあたりで自分を要約し始めます。その理由は出力のどこにも書かれません。プロジェクトのコミュニティでは圧縮が想定より早く来るという報告が実際にあり、少なくともこれはその現象を生む 1 つの仕組みで、モデルのせいにする前に潰しておくコストは低いはずです。

実務的な線引きはこうです。探索の段階は未登録の ID に任せ、毎日動かす 2 つか 3 つのモデルには contextWindowmaxTokensreasoninginputcost を埋めた本格的なエントリを書く。画像を受け付けるかどうかも含め、Pi がモデルについて表示するすべてはエンドポイントではなくこのエントリ由来です。

Pi の組み込み anthropic プロバイダをゲートウェイに向けられるか?

向けられますし、OpenAI ではなく Anthropic のベースパスを渡す限り、Claude モデルにはこちらのほうが良い経路です。 上書きは 1 行で、自分でモデル一覧を書く必要もありません:

{ "providers": { "anthropic": { "baseUrl": "https://api.ofox.ai/anthropic", "apiKey": "$OFOX_API_KEY" } } }
pi --provider anthropic --model claude-sonnet-5 -p "Reply with exactly: ok"
# ok

Pi は組み込みの Claude カタログ全体を、正しいウィンドウのまま保持します。Claude Fable 5 は 1M、Opus と Haiku のエントリは 200K です。宣言するものも同期し続けるものもなく、developer ロールも登場しません。この経路では Messages がネイティブな形式だからです。ベンダーの ID はそのまま使え、ゲートウェイの接頭辞も不要です。

ベース URL を間違えると、どちらも別の問題を説明するエラーが 2 種類出ます。OpenAI のパスに向けた場合:

401 {"error":{"message":"You didn't provide an API key. You need to provide your API key
in an Authorization header using Bearer auth ...","type":"invalid_request_error","code":401}}

ここに認証のバグはありません。Pi は Messages を話しているので x-api-key を送りますが、OpenAI のパスは Authorization: Bearer しか受け付けません。プロバイダの headers 項目で Bearer ヘッダーを足すと、正直な答えが出てきます。404 Unsupported OpenAI API endpoint です。あの 401 は認証の衣をまとったプロトコル不一致でした。

もう 1 つの間違え方はバージョンセグメントの重複です:

404 {"error":{"message":"Unsupported Anthropic API endpoint. ...","code":404}}

これは設定が .../anthropic/v1 になっている場合です。Pi 自身が /v1/messages を付け足すので、ベース URL は /anthropic で止めます。

baseUrl結果
https://api.ofox.ai/anthropic動く、組み込みの Claude カタログがすべて使える
https://api.ofox.ai/anthropic/v1404、Unsupported Anthropic API endpoint
https://api.ofox.ai/v1401、実体は別プロトコルに対する 404

つまり同じキーで Claude に至る経路は 2 つあります。上記の組み込み上書きか、ゲートウェイ自身の ID を使ったカスタムの openai-completions エントリ(コストの例で使ったほう)です。上書きは記述量が少なく、developer ロールを完全に回避できます。カスタムエントリは、Pi がまだ知らないモデルごとの costcontextWindow を持たせたいときに使うものです。

そもそも Pi で Claude モデルを動かすべきか?

動きますし、そのうえで Pi の作者自身が最新モデルにおけるスキーマの問題を記録しています。 2026-07-04 の記事で Armin Ronacher は、「新しめの Claude モデルは、入れ子になった edits[] 配列に余計な、でっち上げの項目を付けて Pi の edit ツールを呼ぶことがある」と報告し、その結果「モデルが存在しないキーを創作し、Pi はツール呼び出しを拒否して再試行を求める」と述べています。傾向についての彼のまとめが居心地の悪い部分です。「これは新しい Anthropic モデルほど悪化していて、Opus 4.8 と Sonnet 5 の両方で見られるが、それより古いモデルでは 1 つも起きない。」

これは学習とツールのミスマッチであってベース URL で直せるものではなく、発生のたびに再試行 1 回分のコストがかかります。Claude が Pi で使い物にならないという話ではありません。ただし、edit ツールを自前で持つ harness の既定モデルを選ぶなら、最新の Claude が自動的にもっとも安全な選択肢になるわけではないということです。同じ編集に対するツール呼び出しが繰り返されていないか、セッションログを見ておく価値があります。

Pi が実際に何を送っているかを見るには?

同じ呼び出しを curl で再現し、Pi が記録した内容と突き合わせます。 必要なことの大半はファイル 2 つとコマンド 1 本で片づき、プロキシは要りません。

まずセッションログです。実行のたびに ~/.pi/agent/sessions/<project>/ の下に JSON Lines ファイルが書かれ、1 イベント 1 行で記録されます。その中には Pi が解決したプロバイダとモデル ID を示す model_change 行と、usage ブロックを持つアシスタントメッセージがあります。そのファイル内のモデル ID が意図したものと違うなら、問題はフラグかフォールバックにあり、プロバイダをいくら調整しても直りません。

次にエンドポイントです。同じ形のリクエストを自分で送ります:

curl -s https://api.ofox.ai/v1/chat/completions \
  -H "Authorization: Bearer $OFOX_API_KEY" -H 'Content-Type: application/json' \
  -d '{"model":"deepseek/deepseek-v4-flash","messages":[{"role":"user","content":"hi"}],"max_tokens":8}' \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["usage"])'

usage の中で注意深く読むべき箇所が 2 つあります。prompt_tokens_details.cached_tokens は Pi が cacheRead の列に対応づけているもので、このキーが返ってこないなら、プレフィックスがどれだけ安定していてもセッションログのキャッシュ値はゼロのままです。そして completion_tokens_details.reasoning_tokens は思考が実際に走っているかを教えてくれます。出力を読んで推測するよりずっと速い確認方法です。

設定をいじる前にこれをやること。これが、私たちが書いてきたすべての harness 接続記事に共通する結論です。エラー文字列はそれを投げた側が書いたものであり、投げた側が壊れている側とは限りません。

設定中に何が壊れ、どう直すか?

6 つの失敗のうち、5 つは 0.84.1 で実際のエンドポイントに対して再現し、1 つは Pi 自身のモデル表で示しました。

症状原因対処
401: {"message":"Invalid or expired API key"...}キーは解決されたが誤っている、またはこのシェルで変数が空ファイルを疑う前に echo $OFOX_API_KEYpi auth check ではこれを捕まえられない
404 404 page not foundbaseUrl にバージョンセグメントがないhttps://host ではなく https://host/v1 を使う
500 ... unsupported message role: developer上流に developer ロールがないモデルで reasoning: truecompat: { supportsDeveloperRole: false } を足す
anthropic プロバイダで 401 ... provide your API key ... using Bearer auth組み込みの上書きが OpenAI のパスを向いており、Bearer しか受け付けない先に Pi が x-api-key を送っている/anthropic で終わるゲートウェイの Anthropic ベースパスを使う
404: {"message":"Model 'openai/gpt-5.6' not found","type":"model_not_found"}ID の形式は正しいが、このゲートウェイのカタログにないゲートウェイ自身のモデルページから ID を読み取る。ベンダーが発表したからといって、あらゆるカタログに載るわけではない
モデル本来のウィンドウよりはるかに早くセッションが圧縮される未登録のモデルが 128K の既定値に落ちたそのモデルに contextWindowmaxTokens を宣言する

4 行目と 5 行目がもっとも時間を食います。どちらのエラーメッセージも、実際の問題とは別のことを説明しているからです。

チームで Pi のプロバイダ設定をどう共有するか?

ファイルは共有し、キーは絶対に共有しない。 すべての apiKey$VAR!command であれば models.json に秘密は含まれないので、dotfiles リポジトリやブートストラップスクリプトに安心してコミットできます。

複数人の開発に耐える分け方はこうです:

  • コミットするもの:プロバイダブロック。ベース URL、プロトコル、そして contextWindowmaxTokensreasoningcost を備えた完全なモデルエントリ。これらはエンドポイントについての事実で全員に共通しており、間違えると静かな早期圧縮と偽の $0 請求が生まれます。
  • 絶対にコミットしないもの:キー。共有ファイルには "apiKey": "$OFOX_API_KEY" と書き、実際の値は各自のシェル設定かキーチェーンに置きます。
  • 検証したバージョンを固定する。 Pi はおよそ週次で出ており、1 か月足らずで 0.82.1 から 0.84.2 まで進みました。設定を検証したバージョンを記録しておきましょう。
  • 全員に同じベース URL を配る。 エンドポイントが 1 つなら、モデルカタログも 1 つ、レート制限のプールも 1 つ、支出を見る場所も 1 つになります。開発者ごとの推測が入り込みません。

最後の点はチームが飛ばしがちで、そしてこれこそが「今どのモデルを使ってる?」を質問から参照作業に変えるものです。

すべての harness を同じキーに向けるには?

harness はそれぞれ独自の方言でモデルへのアクセスを保持します。Claude Code は ANTHROPIC_BASE_URLANTHROPIC_AUTH_TOKEN を読みます。Codex CLI は config.tomlmodel_providers ブロックを求め、Responses API 以外を受け付けません。Cline には設定画面があります。DeepSeek Harness はカスタムプロバイダのフォームか DEEPSEEK_BASE_URL を求めます。Pi は上記の JSON ファイルを求めます。5 つのツール、キーを回す場所が 5 か所、そして少しずつずれていくモデル一覧が 5 つです。

どれも OpenAI 互換か Anthropic 互換のエンドポイントに対して HTTP を話しているので、対処はどこでも同じです。ベース URL 1 つ、キー 1 本、そして変わるのはモデル文字列だけ。これらのツールのカスタムプロバイダのフォームが揃って同じ 4 項目である理由も、まさにそこにあります。

ofox ではそのエンドポイントが https://api.ofox.ai/v1 で、openai-completions を使い、2026-08-18 時点でキー 1 本から 131 モデルに届きました。上で使った DeepSeek、GLM、Claude のエントリに加えて Kimi K3MiniMax M3 も含まれます。他のツールでの同等の設定は、Codex CLI カスタムプロバイダガイドOpenCode 設定の手順Cursor / Claude Code / Cline の設定 にあります。

すでに使っている harness と比べて Pi はどうか?

仕事は同じ、表面積はずっと小さく、設定ファイルは自分がいかに何も仮定していないかについて正直です。 Pi はモデルに 4 つのツールと拡張 API を渡し、Claude Code は hooks、subagent、skills、MCP サーバーを最初から渡します。抽象的にどちらが優れているという話ではありません。問題は、組み立て済みが欲しいのか、組み立てが必要なほうが良いのかです。

カスタムプロバイダの経路が示すのは、そのミニマリズムがどこで代償を伴うかです。カタログ取得なし、価格表なし、プロトコルの推測なし。本記事の 3 つの問題はいずれも、Pi があなたの代わりに推測することを拒んだ結果であり、どの対処も、事実を一度書き留めるという作業です。

Pi がこの分野のどこに位置するか、各 harness の中で人々が実際にどのモデルを動かしているかという OpenRouter の利用データも含めては、9 つの harness の横断比較を参照してください。ターミナル系エージェントに絞るなら、Claude Code と Codex CLI と Cursor の比較がより踏み込んで扱っています。

References

よくある質問

Pi coding agent とは何ですか?
Armin Ronacher と Mario Zechner による MIT ライセンスのターミナル型 coding agent で、現在は Earendil のもとで github.com/earendil-works/pi で開発されています。モデルに渡すのは組み込みの 4 ツール(read、write、edit、bash)だけで、hooks や subagent、skills の代わりに拡張 API を公開しています。2026-08-18 時点でリポジトリは 92,619 スター、npm パッケージは週 137 万ダウンロードです。
Pi をインストールする npm パッケージはどれですか?
@earendil-works/pi-coding-agent で、現在は 0.84.2、engines は node >=22.19.0 です。古い @mariozechner/pi は 0.70.6 で止まっており週数百ダウンロードにとどまります。こちらは買収前の配布チャネルで、入れると Earendil 移行前のバージョンが手に入ってしまいます。
Pi はサードパーティの API エンドポイントに対応していますか?
対応しています。~/.pi/agent/models.json を使います。プロバイダのエントリは baseUrl、api、apiKey と models 配列を取り、api は openai-completions、openai-responses、anthropic-messages、google-generative-ai のいずれかです。コード変更もフォークも不要で、このファイルは /model ピッカーを開くたびに読み直されます。
Pi は環境変数から API キーを読めますか?
読めます。apiKey は $VAR と ${VAR} の展開に対応し、さらに !command も受け付けます。これはシェルコマンドを実行して標準出力をキーとして使う書き方で、JSON に秘密を残さずシステムのキーチェーンから読むための手段です。ドル記号そのものを書きたいときは $$ を使います。
models.json にすべてのモデルを列挙する必要はありますか?
ありません。一覧にない ID を渡すと Warning: Model not found for provider と表示されたうえで、カスタムモデル ID として実行されます。ただし未登録のモデルは既定値、つまり 128,000 コンテキストと 16,384 最大出力を引き継ぐため、1M コンテキストのモデルが必要よりはるかに早く圧縮を始めます。
Pi がどのリクエストでも $0 と表示するのはなぜですか?
カスタムプロバイダには価格のメタデータが一切ないからです。トークン数はセッションファイルに正しく記録されますが、モデルのエントリに cost ブロックを足して input、output、cacheRead、cacheWrite の 100 万トークンあたり単価を書くまで、cost 配下のすべての項目はゼロのままです。
Pi の組み込み anthropic プロバイダをゲートウェイに向けられますか?
向けられます。ただし OpenAI 側ではなく、ゲートウェイの Anthropic Messages のベースパスを渡す必要があります。組み込みの anthropic プロバイダの baseUrl を上書きすれば、Pi の Claude カタログ全体が正しいコンテキスト長のまま残り、models 配列も不要です。Pi 自身が /v1/messages を付け足すので URL はバージョンの手前で止めます。OpenAI のパスに向けると、実体はプロトコル不一致である 401 が返ります。
Pi の unsupported message role: developer とはどういう意味ですか?
そのモデルのエントリで reasoning が true になっているため、Pi がシステムプロンプトを developer ロールのメッセージとして送り、上流がそのロールを拒否しているという意味です。compat の supportsDeveloperRole を false にすれば思考を保ったまま解消でき、reasoning を false にしても消えますが思考は失われます。OpenAI 形式のゲートウェイでは、この現象は Anthropic 系のモデルにだけ現れます。