Skip to content

Instantly share code, notes, and snippets.

@ckcr4lyf
Last active August 24, 2026 10:55
Show Gist options
  • Select an option

  • Save ckcr4lyf/8c69872c70da78eb6b929b10607598ca to your computer and use it in GitHub Desktop.

Select an option

Save ckcr4lyf/8c69872c70da78eb6b929b10607598ca to your computer and use it in GitHub Desktop.
How to use Chaozhiyuan AI Pool with pi.dev

Overview

Chaozhiyuan AI Pool provides cheap access to Anthropic / OpenAI models (supposedly).

API Key Groups

Typically when you create an API key you need to link it to a group. From some testing it seems like:

  • Claude/Kiro API keys can use Anthropic models, but not OpenAI
  • GPT API keys can use OpenAI models, and also Anthropic models! (But if you hit /v1/models you'll only see OpenAI models
image

pi.dev configuration

Based on the response from /v1/models , you can add custom providers into ~/.pi/agent/models/json , something like

{
  "providers": {
    "chaozhiyuanai": {
      "name": "Chaozhiyuan AI Pool",
      "baseUrl": "https://pool.chaozhiyuanai.com/v1",
      "apiKey": "REDACTED",
      "api": "openai-completions",
      "compat": {
        "supportsStore": false,
        "supportsDeveloperRole": true,
        "supportsReasoningEffort": true,
        "maxTokensField": "max_tokens"
      },
      "models": [
        {
          "id": "codex-auto-review",
          "name": "codex-auto-review",
          "reasoning": true,
          "input": ["text", "image"],
          "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
          "contextWindow": 272000,
          "maxTokens": 128000,
          "thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
        }
        ...

You may want to name the provider based on the API Key group to make it convenient.

Also note that the base URL is different when configuring pi.dev for OpenAI vs. Anthropic, so they need separate "Providers" even if its the same API key!

API Key / Model / Time matrix as of 2026-08-24:

image
#!/usr/bin/env node
/**
* Probe the Chaozhiyuan OpenAI-compatible gateway across multiple API keys.
*
* Node 18+; no external dependencies.
* Keep API_KEYS below, or replace the values with your own keys.
*/
import { performance } from "node:perf_hooks";
import { writeFile } from "node:fs/promises";
import process from "node:process";
const BASE_URL = "https://pool.chaozhiyuanai.com/v1";
// key type -> API key. Do not commit real credentials to source control.
const API_KEYS = {
GPT_PRO: "sk-",
KIRO: "sk-",
CLAUDE_KIRO: "sk-",
};
const DEFAULTS = {
concurrency: 3,
timeoutMs: 60_000,
retries: 0,
prompt: "Reply with exactly PONG.",
};
function usage() {
console.log(`Usage: node chaozhiyuan-model-probe.mjs [options]
Options:
--concurrency N Maximum simultaneous requests (default: ${DEFAULTS.concurrency})
--timeout-ms N Per-request timeout (default: ${DEFAULTS.timeoutMs})
--retries N Retries after a failed request (default: ${DEFAULTS.retries})
--key NAME[,NAME...] Probe only these key names
--model MODEL[,MODEL] Probe only these model IDs after discovery
--discover-only Fetch /models but do not run the cross-product probes
--json Print the complete report as JSON instead of a table
--out FILE Also write the complete report as JSON to FILE
--help Show this help
The default probe matrix is every configured key x the union of models returned
by /models for all configured keys. Model API selection is automatic: IDs whose
name starts with "claude" use Anthropic Messages; all others use OpenAI Chat
Completions.`);
}
function parseArgs(argv) {
const options = { ...DEFAULTS, json: false, discoverOnly: false, out: undefined };
for (let i = 0; i < argv.length; i += 1) {
const arg = argv[i];
const value = () => {
const next = argv[++i];
if (next === undefined) throw new Error(`Missing value for ${arg}`);
return next;
};
if (arg === "--help" || arg === "-h") {
usage();
process.exit(0);
} else if (arg === "--concurrency") {
options.concurrency = positiveInt(value(), arg);
} else if (arg === "--timeout-ms") {
options.timeoutMs = positiveInt(value(), arg);
} else if (arg === "--retries") {
options.retries = nonNegativeInt(value(), arg);
} else if (arg === "--key") {
options.keys = splitList(value());
} else if (arg === "--model") {
options.models = splitList(value());
} else if (arg === "--discover-only") {
options.discoverOnly = true;
} else if (arg === "--json") {
options.json = true;
} else if (arg === "--out") {
options.out = value();
} else {
throw new Error(`Unknown option: ${arg}`);
}
}
return options;
}
function positiveInt(value, flag) {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed < 1) throw new Error(`${flag} requires a positive integer`);
return parsed;
}
function nonNegativeInt(value, flag) {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed < 0) throw new Error(`${flag} requires a non-negative integer`);
return parsed;
}
function splitList(value) {
return value.split(",").map((item) => item.trim()).filter(Boolean);
}
function apiForModel(model) {
return /^claude(?:[-/]|$)/i.test(model) ? "anthropic-messages" : "openai-completions";
}
function endpointFor(api) {
return api === "anthropic-messages" ? `${BASE_URL}/messages` : `${BASE_URL}/chat/completions`;
}
function headersFor(api, apiKey) {
if (api === "anthropic-messages") {
return {
"content-type": "application/json",
"x-api-key": apiKey,
"anthropic-version": "2023-06-01",
};
}
return {
"content-type": "application/json",
authorization: `Bearer ${apiKey}`,
};
}
function requestBody(api, model, prompt) {
if (api === "anthropic-messages") {
return {
model,
max_tokens: 32,
temperature: 0,
messages: [{ role: "user", content: prompt }],
};
}
return {
model,
max_tokens: 32,
temperature: 0,
messages: [{ role: "user", content: prompt }],
};
}
async function fetchJson(url, init, timeoutMs) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, { ...init, signal: controller.signal });
const text = await response.text();
let body;
try {
body = text ? JSON.parse(text) : null;
} catch {
body = { raw: text };
}
return { response, body, rawText: text };
} finally {
clearTimeout(timer);
}
}
function errorMessage(body, rawText, fallback) {
const error = body?.error;
if (typeof error === "string") return error;
if (error?.message) return error.message;
if (body?.message) return body.message;
if (rawText) return rawText.slice(0, 500);
return fallback;
}
function textFromContent(content) {
if (typeof content === "string") return content;
if (!Array.isArray(content)) return "";
return content.map((part) => {
if (typeof part === "string") return part;
return part?.text ?? part?.content ?? "";
}).join("");
}
function extractReply(api, body) {
if (api === "anthropic-messages") {
return textFromContent(body?.content);
}
return textFromContent(body?.choices?.[0]?.message?.content);
}
function modelIdsFromResponse(body) {
if (!Array.isArray(body?.data)) return [];
return body.data
.map((model) => typeof model === "string" ? model : model?.id)
.filter((id) => typeof id === "string" && id.length > 0);
}
async function discoverModels(keyName, apiKey, timeoutMs) {
const started = performance.now();
try {
const { response, body, rawText } = await fetchJson(
`${BASE_URL}/models`,
{ headers: { authorization: `Bearer ${apiKey}` } },
timeoutMs,
);
const models = modelIdsFromResponse(body);
return {
key: keyName,
status: response.status,
ok: response.ok,
elapsedMs: elapsed(started),
models,
error: response.ok ? undefined : errorMessage(body, rawText, `HTTP ${response.status}`),
};
} catch (error) {
return {
key: keyName,
status: undefined,
ok: false,
elapsedMs: elapsed(started),
models: [],
error: error instanceof Error && error.name === "AbortError" ? `timeout after ${timeoutMs}ms` : String(error),
};
}
}
async function probe(keyName, apiKey, model, options) {
const api = apiForModel(model);
const endpoint = endpointFor(api);
const started = performance.now();
let lastFailure;
for (let attempt = 0; attempt <= options.retries; attempt += 1) {
try {
const { response, body, rawText } = await fetchJson(
endpoint,
{
method: "POST",
headers: headersFor(api, apiKey),
body: JSON.stringify(requestBody(api, model, options.prompt)),
},
options.timeoutMs,
);
const reply = extractReply(api, body);
const passed = response.ok && reply.trim() === "PONG";
if (passed || attempt === options.retries) {
return {
key: keyName,
model,
api,
endpoint,
status: response.status,
ok: response.ok,
passed,
elapsedMs: elapsed(started),
reply: reply || undefined,
finishReason: api === "anthropic-messages"
? body?.stop_reason
: body?.choices?.[0]?.finish_reason,
usage: body?.usage,
error: response.ok && !passed
? `unexpected reply: ${JSON.stringify(reply).slice(0, 500)}`
: response.ok ? undefined : errorMessage(body, rawText, `HTTP ${response.status}`),
attempts: attempt + 1,
};
}
lastFailure = errorMessage(body, rawText, `HTTP ${response.status}`);
} catch (error) {
lastFailure = error instanceof Error && error.name === "AbortError"
? `timeout after ${options.timeoutMs}ms`
: String(error);
if (attempt === options.retries) {
return {
key: keyName,
model,
api,
endpoint,
status: undefined,
ok: false,
passed: false,
elapsedMs: elapsed(started),
error: lastFailure,
attempts: attempt + 1,
};
}
}
}
throw new Error(`Probe fell through unexpectedly: ${keyName}/${model}: ${lastFailure}`);
}
function elapsed(started) {
return Math.round((performance.now() - started) * 100) / 100;
}
async function mapConcurrent(items, concurrency, worker) {
const results = new Array(items.length);
let next = 0;
async function consume() {
while (true) {
const index = next++;
if (index >= items.length) return;
results[index] = await worker(items[index], index);
}
}
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, consume));
return results;
}
function sortedUnique(values) {
return [...new Set(values)].sort((a, b) => a.localeCompare(b));
}
function buildSummary(discovery, probes) {
const byKey = Object.fromEntries(discovery.map((item) => [item.key, {
status: item.status,
ok: item.ok,
elapsedMs: item.elapsedMs,
models: item.models,
error: item.error,
}]));
const byModel = {};
for (const model of sortedUnique(probes.map((probe) => probe.model))) {
const rows = probes.filter((probe) => probe.model === model);
byModel[model] = {
api: apiForModel(model),
discoveredBy: discovery.filter((item) => item.models.includes(model)).map((item) => item.key),
passedBy: rows.filter((row) => row.passed).map((row) => row.key),
failedBy: rows.filter((row) => !row.passed).map((row) => row.key),
};
}
return { byKey, byModel };
}
function printTable(report) {
console.log("\nModel discovery:");
for (const item of report.discovery) {
console.log(` ${item.key.padEnd(14)} ${String(item.status ?? "ERR").padEnd(5)} ${String(item.models.length).padStart(3)} models ${item.elapsedMs}ms${item.error ? ` ${item.error}` : ""}`);
}
console.log("\nProbe matrix (✓ means HTTP success and exact PONG):");
const keys = Object.keys(API_KEYS).filter((key) => report.selectedKeys.includes(key));
const models = sortedUnique(report.probes.map((probe) => probe.model));
console.log(` ${"model".padEnd(40)} ${keys.map((key) => key.padEnd(16)).join("")}`);
for (const model of models) {
const cells = keys.map((key) => {
const row = report.probes.find((probe) => probe.model === model && probe.key === key);
if (!row) return "".padEnd(16);
const mark = row.passed ? "✓" : "✗";
return `${mark} ${row.status ?? "ERR"} ${row.elapsedMs}ms`.padEnd(16);
});
console.log(` ${model.padEnd(40)} ${cells.join("")}`);
}
console.log("\nPer-model analysis:");
for (const [model, summary] of Object.entries(report.summary.byModel)) {
console.log(` ${model} [${summary.api}]`);
console.log(` discovered by: ${summary.discoveredBy.join(", ") || "none"}`);
console.log(` passed by: ${summary.passedBy.join(", ") || "none"}`);
console.log(` failed by: ${summary.failedBy.join(", ") || "none"}`);
}
}
async function main() {
const options = parseArgs(process.argv.slice(2));
const selectedKeys = options.keys ?? Object.keys(API_KEYS);
const unknownKeys = selectedKeys.filter((key) => !(key in API_KEYS));
if (unknownKeys.length > 0) throw new Error(`Unknown key name(s): ${unknownKeys.join(", ")}`);
const discovery = await mapConcurrent(selectedKeys, options.concurrency, (key) =>
discoverModels(key, API_KEYS[key], options.timeoutMs));
const union = sortedUnique(discovery.flatMap((item) => item.models));
const models = options.models ? union.filter((model) => options.models.includes(model)) : union;
const missingRequestedModels = (options.models ?? []).filter((model) => !union.includes(model));
const combos = options.discoverOnly ? [] : selectedKeys.flatMap((key) => models.map((model) => ({ key, model })));
const probes = await mapConcurrent(combos, options.concurrency, ({ key, model }) =>
probe(key, API_KEYS[key], model, options));
const report = {
generatedAt: new Date().toISOString(),
baseUrl: BASE_URL,
selectedKeys,
options: {
concurrency: options.concurrency,
timeoutMs: options.timeoutMs,
retries: options.retries,
prompt: options.prompt,
},
discovery,
unionModels: union,
selectedModels: models,
missingRequestedModels,
probes,
summary: buildSummary(discovery, probes),
};
if (options.out) {
await writeFile(options.out, `${JSON.stringify(report, null, 2)}\n`, { mode: 0o600 });
if (!options.json) console.log(`\nWrote report: ${options.out}`);
}
if (options.json) console.log(JSON.stringify(report, null, 2));
else printTable(report);
}
main().catch((error) => {
console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
process.exitCode = 1;
});
{
"providers": {
"chaozhiyuanai": {
"name": "Chaozhiyuan - OpenAI (GPT PRO)",
"baseUrl": "https://pool.chaozhiyuanai.com/v1",
"apiKey": "REDACTED",
"api": "openai-completions",
"compat": {
"supportsStore": false,
"supportsDeveloperRole": true,
"supportsReasoningEffort": true,
"supportsUsageInStreaming": true,
"supportsFinishReason": true,
"maxTokensField": "max_tokens",
"requiresToolResultName": false,
"requiresAssistantAfterToolResult": false,
"requiresThinkingAsText": false,
"requiresReasoningContentOnAssistantMessages": false,
"thinkingFormat": "openai",
"supportsStrictMode": true,
"supportsOpenAIGrammarTools": false,
"sendSessionAffinityHeaders": false,
"supportsLongCacheRetention": true
},
"models": [
{
"id": "codex-auto-review",
"name": "codex-auto-review",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.3-codex-spark",
"name": "gpt-5.3-codex-spark",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 128000,
"maxTokens": 32000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.4",
"name": "gpt-5.4",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.4-mini",
"name": "gpt-5.4-mini",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 400000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.5",
"name": "gpt-5.5",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.6",
"name": "gpt-5.6",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.6-luna",
"name": "gpt-5.6-luna",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.6-sol",
"name": "gpt-5.6-sol",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
},
{
"id": "gpt-5.6-terra",
"name": "gpt-5.6-terra",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 272000,
"maxTokens": 128000,
"thinkingLevelMap": { "off": null, "minimal": "minimal", "low": "low", "medium": "medium", "high": "high", "xhigh": null, "max": null }
}
]
},
"chaozhiyuanai-anthropic": {
"name": "Chaozhiyuan - Anthropic (GPT PRO)",
"baseUrl": "https://pool.chaozhiyuanai.com/",
"apiKey": "REDACTED",
"api": "anthropic-messages",
"compat": {
"supportsEagerToolInputStreaming": true,
"supportsLongCacheRetention": true,
"supportsCacheControlOnTools": true,
"supportsStrictTools": false
},
"models": [
{
"id": "claude-haiku-4-5-20251001",
"name": "Claude Haiku 4.5",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 1, "output": 5, "cacheRead": 0.1, "cacheWrite": 1.25 },
"contextWindow": 200000,
"maxTokens": 64000
},
{
"id": "claude-opus-4-5-20251101",
"name": "Claude Opus 4.5",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 5, "output": 25, "cacheRead": 0.5, "cacheWrite": 6.25 },
"contextWindow": 200000,
"maxTokens": 64000
},
{
"id": "claude-opus-4-6",
"name": "Claude Opus 4.6",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 5, "output": 25, "cacheRead": 0.5, "cacheWrite": 6.25 },
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": { "forceAdaptiveThinking": true }
},
{
"id": "claude-opus-4-7",
"name": "Claude Opus 4.7",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 5, "output": 25, "cacheRead": 0.5, "cacheWrite": 6.25 },
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": { "forceAdaptiveThinking": true }
},
{
"id": "claude-opus-4-8",
"name": "Claude Opus 4.8",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 5, "output": 25, "cacheRead": 0.5, "cacheWrite": 6.25 },
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": { "forceAdaptiveThinking": true }
},
{
"id": "claude-opus-5",
"name": "Claude Opus 5",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 5, "output": 25, "cacheRead": 0.5, "cacheWrite": 6.25 },
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": { "forceAdaptiveThinking": true }
},
{
"id": "claude-sonnet-4-5-20250929",
"name": "Claude Sonnet 4.5",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 3, "output": 15, "cacheRead": 0.3, "cacheWrite": 3.75 },
"contextWindow": 1000000,
"maxTokens": 64000
},
{
"id": "claude-sonnet-4-6",
"name": "Claude Sonnet 4.6",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 3, "output": 15, "cacheRead": 0.3, "cacheWrite": 3.75 },
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": { "forceAdaptiveThinking": true }
},
{
"id": "claude-sonnet-5",
"name": "Claude Sonnet 5",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 2, "output": 10, "cacheRead": 0.2, "cacheWrite": 2.5 },
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": { "forceAdaptiveThinking": true }
}
]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment