← 回首页

接入文档

五分钟接进来

这一页不需要登录就能读完。你在付钱之前最想确认的应该是「接入麻不麻烦」,把它藏在登录后面是自断转化。

最后更新
2026-08-14

快速开始

注册账号之后跑一行脚本,它会把接口地址和密钥写进 `~/.config/agiplan/env`,并告诉你怎么让它生效。然后打开你原来用的编程工具,照常用就行。

# 交互式(会提示你粘贴密钥)
curl -fsSL https://agiplan.dev/setup -o setup.sh && sh setup.sh

# 或者一行搞定
AGIPLAN_API_KEY=ap_live_xxx sh -c "$(curl -fsSL https://agiplan.dev/setup)"

. ~/.config/agiplan/env   # 让它在当前 shell 生效

不想跑脚本也完全可以。 手动配两个环境变量效果一样,只是多套配置切换时麻烦一点。

export API_BASE_URL="https://agiplan.dev/v1"
export API_KEY="ap_live_••••••••••••••••"

脚本到底做了什么

`curl | sh` 是个需要你信任我们的动作,所以我们把它做了什么逐条写出来。脚本本身以纯文本返回,浏览器直接打开 https://agiplan.dev/setup 就能读全文——你正要跑的和你看到的是同一份。

  • 把接口地址和密钥写进 `~/.config/agiplan/env`,目录 700、文件 600,写之前先收紧 umask——否则密钥会在默认权限下短暂可读。不碰系统目录,不要 sudo。
  • 同一个文件里还会导出 `OPENAI_BASE_URL` / `OPENAI_API_KEY`。多数工具认这两个名字,所以加载之后它们会走我们这里——这是有意的,但你应该知道。
  • 不改你的 `.bashrc` / `.zshrc`——要不要开机加载由你决定,那是你的文件。
  • 不装任何二进制。 命令行工具还没发布,脚本不假装装了什么——一个假装成功的安装脚本,比一个说清现状的危险得多。
  • 不探测你装了什么工具,不改任何别的配置文件,不上传任何本机信息。
  • 密钥不以 `ap_live_` 开头就直接退出,一个文件都不写。

脚本不改你的 shell 配置,只写 `~/.config/agiplan/env` 这一个文件——所以也没有什么「备份」需要还原。`agiplan uninstall` 就是删掉那一个文件,而且默认只列出要删什么,加 `--yes` 才真删。

认证

三套协议都用 Bearer token。密钥在控制台创建,明文只显示一次——我们只存哈希,找回不了,只能轮换。

Authorization: Bearer ap_live_xxxxxxxxxxxx

密钥可以设作用域、绑定到自定义模型、限制 IP、设过期时间。轮换比吊销更顺手是有意的设计:让正确的操作成为最省事的操作。旧密钥可以设宽限期,不会一刀切断。

兼容哪几套协议

同一个 base URL 下同时提供三套主流协议的兼容端点。用哪套取决于你的 SDK,不需要告诉我们。

端点对应协议说明
/v1/chat/completionsOpenAI 风格含 stream、tools、response_format
/v1/messagesAnthropic 风格含 stream、tools、system
/v1/responsesOpenAI Responses含 stream、tools;`previous_response_id` 可以不重传上下文
/v1/models三者通用返回你当前可用的模型与自定义模型
/v1/quota三者通用不发起调用就能读三个窗口的剩余比例,需要 usage:read

凡是允许改接口地址的工具都能直接用,不用装插件,不用改业务代码。各套协议的请求体差异我们在网关内部消化,你按自己熟悉的那套写就行。

`/v1/responses` 是三者里唯一有状态的:用 `previous_response_id` 续接时,那轮对话的消息内容会存在我们这边,最长 5 小时,之后由定时任务删除。不用这个参数就不产生这项存储。状态放在我们自己这边而不是上游,是为了让灾备切换对你透明——代价就是这 5 小时,隐私政策里也写着同一句。

还有几个端点没列在上面:`/v1/device/code`、`/v1/device/token`、`/v1/keys/current` 是命令行工具的传输层(`agiplan login` / `agiplan use` 用),不是给你直接调的。`/v1/traces/{追踪号}` 见下面的溯源一节。

发图片只支持内嵌的 `data:` URL(base64),远程 `http(s)` 图片链接还没有做。 标了「视觉」的模型确实能看图,但那张图得由你在请求体里带上;给一个 URL 的话,网关需要替你下载再转 base64,还要防住内网地址(SSRF),这件事我们没做完,所以现在会把它降级成一句文本占位。降级时响应头里会有 `x-agiplan-dropped-params: content[].image_url`——我们不想让你以为模型看过了那张图。音频和文件类型同理,当前直接丢弃并在同一个头里列出。

指定模型,或交给 Prism

同一个 `model` 字段两种用法:填具体模型就固定用它;填 `auto` 或你自己的自定义模型名就交给 Prism 按任务难度动态调度。

"model": "frontier-a"       // 固定用这一个,Prism 不介入
"model": "auto"            // 交给 Prism 自动挑
"model": "my-coding-model" // 你自己建的自定义模型

想在单次请求里覆盖难度判断,加一个请求头即可:`X-AGIPlan-Difficulty: 0.9`。全部模型与系数见 /models 页。

流式

三套协议的流式都按各自的原生格式返回 SSE,行为与你熟悉的一致。需要注意的只有一点:计费在流结束时结算。

请求进来时我们先按最坏情况预扣一笔额度——输出按你声明的 `max_tokens` 算,输入按请求里已经能数出来的 token 算。流正常结束、客户端中断、上游报错都走同一个收尾逻辑,用真实用量回填、多退少补。所以中途断开不会被按最坏情况扣钱。

配额响应怎么读

每个响应都带三个窗口的剩余比例和重置时间。给比例不给数量是刻意的:足够你决定要不要退避,而不用把套餐的绝对额度写进每一个响应头。要逐笔核对用了多少,看控制台的用量明细或月度对账单——那边是绝对值。触发限流时返回 429,并明确告诉你是哪个窗口满了、什么时候恢复——429 上同样带这三个头,那正是你最需要它们的时候。密钥无效(401)时没有这几个头:那时我们还不知道该报谁的额度。

X-AGIPlan-Quota-Session: remaining=68%; resets=2026-08-15T09:00:00.000Z
X-AGIPlan-Quota-Week:    remaining=34%; resets=2026-08-18T00:00:00.000Z
X-AGIPlan-Quota-Month:   remaining=81%; resets=2026-09-05T00:00:00.000Z
Retry-After: 1740        // 秒,仅在 429 时出现

错误码与重试

状态码错误码含义该怎么做
401invalid_api_key密钥无效或已吊销换一个密钥,不要重试
404model_not_found生图端点:没有这个生图模型看 /v1/models 里 kind 为 image 的那些
503size_unavailable生图端点:此刻没有线路支持这个尺寸换个尺寸,或稍后重试。失败的调用不计费
401key_rotation_required这把密钥超过了组织设定的轮换周期在控制台轮换一把新的
400capability_unavailable请求声明的能力(视觉、工具…)当前没有任何模型支持**重试不会改变结果。** 去掉这项要求,或等我们接上支持它的上游
400context_too_small你按真名点名的那个模型,上下文窗口小于这次请求要求的 `min_context_k`**重试不会改变结果。** 缩短上下文,或换一个窗口更大的模型——/models 上每个模型都标了窗口
400upstream_rejected_request上游拒绝了请求本身(参数或内容不被接受)**换模型也一样。** 检查请求;确认合法的话把追踪号发给我们
400request_exceeds_mix_cap按最坏情况估算超过了你的自定义模型里设的 `max_cu_per_request`**是你自己设的上限。** 调小 max_tokens、缩短上下文,或改高那个值
403insufficient_scope这把密钥没有对应作用域换一把有权限的密钥
403no_subscription这个账号没有生效中的订阅去控制台订阅或续费
429quota_exceeded某个窗口的额度用尽按 Retry-After 等待,或换到消耗更低的能力组
429concurrency_exceeded同时进行的请求达到档位上限等一个跑完再发。**升档能解决,充值不能**——它和额度用尽是两回事
451region_not_available该能力组没有向你所在地提供的模型**重试不会改变结果。** 换一个能力组,或见 /models 的地域列
503no_supply_configured这个能力组当前没有接入任何上游**重试不会改变结果。** 换一个能力组,或者用 auto——/models 页上标着每一组此刻有几条线在跑
503policy_unavailable你调用的自定义模型现在编译不过——多半是它钉死的某个模型下架了错误信息里写着是哪个池、哪个模型。去控制台「自定义模型」里把那个池改成别的模型或一个档位,保存后立刻生效
503model_unavailable你按真名点名的那个模型当前没有可用线路**我们不会替你换一个模型**——你写死了真名,换一个回去等于骗你。稍后重试,或改用能力组的名字(例如 `domestic-a`),那样网关会在同能力的线之间自动切换
503all_upstreams_failed该能力组的模型都试过了,均不可用响应体里带完整尝试记录,可直接报障。失败的尝试不计费
流式中upstream_interrupted已经开始输出之后上游断了。此时状态码早已是 200,只能在流里发一个错误事件,**不会再有正常的结束标记****已经输出的部分按实际 token 计费。** 这时换模型会让回答前后不一致,所以网关不做灾备;请重新发起请求

5xx 不需要你自己重试。 灾备已经在网关内部做完了——你看到 503 说明同能力组的模型都试过了。客户端再重试一遍只会加重上游压力。

这张表列的是网关真的会返回的码。 额度用尽仍然是 429,开了按量续用的话请求会改从余额扣、不会被拒;余额也不够时还是 429,错误信息里会说清是哪一样没过(没开、到上限、余额不够)。有测试钉着这张表和代码里的错误码一致。

请按 `code` 判分支,不要按 `message`。 `code` 是稳定契约,改动会走公告;`message` 是给人读的一句话,措辞会变。还有一件该说清楚的:`message` 目前只有中文——站点、文档、控制台、通知邮件都已经是双语的,唯独这一句还没有。`code` 和 HTTP 状态码不受影响,所以按它判分支的代码不会因为语言而出问题。

追踪号与溯源

成功的响应都带追踪号和实际调用的模型标识。发生过灾备切换时会额外标记出来。被拒的响应没有追踪号——那次调用没有落成一条用量记录,给一个查不到的号比不给更糟。503 的时候链路直接放在响应体的 `attempts` 里,报障时把它一起发来就行。

X-AGIPlan-Trace: tr_01J8FQ3M7X
X-AGIPlan-Model-Actual: frontier-b
X-AGIPlan-Failover: true

用你自己的密钥就能拉完整链路:`GET /v1/traces/{id}`,返回结构化 JSON,保留 30 天。报障时把追踪号发给我们,客服能一键定位,不用你复述发生了什么。

命令行工具

先说一件更要紧的事:命令行工具目前还没有发布渠道。 不在 npm 上,没有下载地址,接入脚本也明说了「不装任何二进制」。所以下表标的是实现状态——哪几条写完了、哪条决定不做——不是「你现在敲下去能不能跑」。今天敲 `agiplan` 得到的是 command not found,而那不是你的配置问题。

「没做」「坏了」「做了但你拿不到」是三件不同的事,混在一起最费时间。没做的命令敲下去会明说「还没有实现」;而整个工具还没发布这件事,只能写在这里。发布方式(npm、单文件二进制、还是跟着 setup 脚本装)定下来之后,这一段会换成安装说明。

命令作用状态
agiplan login设备码授权:浏览器里确认,密钥直接送回终端可用
agiplan status三个窗口的剩余比例、档位与重置时间可用
agiplan models可用模型与能力组可用
agiplan use <名字>给当前密钥绑定自定义模型,--none 解绑可用
agiplan env输出可 eval 的环境变量可用
agiplan keys rotate <配置>轮换密钥不做,见下
agiplan uninstall删掉 setup 写的配置文件(--yes 才真删)可用

`keys rotate` 我们决定不做,理由是安全不是工作量。 一把能给自己签发后继者的密钥会熬过吊销:密钥泄露之后攻击者先轮换一次,你在控制台吊销的是旧的那把,新的那把还活着,而你根本不知道它存在。轮换只走浏览器确认过的路径——控制台里点轮换,或者重新跑一遍 `agiplan login`。

支持项目级配置文件 `.agiplan`,里面只存配置名不存密钥,所以进 git 也安全。

从别处迁过来

如果你已经在用官方 SDK 或别的聚合服务,需要改的只有两处:接口地址和密钥。模型名如果不一致,用自定义模型名做一层映射就行,业务代码不用动。

有一处行为和官方不一样,值得单独说:不传 `max_tokens` 时我们会补一个 4096,并且真的发给上游。 官方那边不传意味着「用模型的上限」,所以同一段代码打过来,长回答会在 4096 处截断、带着 `finish_reason: "length"` 回来——看起来像模型自己停的。这么做是因为这个数同时决定预扣多少额度:不设上限就没法在调用前判断你的额度够不够。补了的时候响应头里有 `x-agiplan-max-tokens-default: 4096`,自己传一个就按你传的走。

还有一处会影响账单,写在这里而不是留给你自己去发现:请求需要某项能力、而你指定的能力组给不了时,我们会把它抬到能给的那一组,并按抬到的那一组计费。 最常见的是发图:自定义模型里选了「快速响应组」,而那一组没有视觉模型,于是这次调用落到国产旗舰组——输出系数从 0.06 变成 0.18,同样的 token 数三倍的 CU。往上抬是因为另一条路是直接失败,而失败对你更没用;只往上不往下,降级永远不会静默发生。每次响应都带 `x-agiplan-billed-group`,写的就是实际计费的那一组,和用量明细里的记录一致。不想被抬走就别在该自定义模型里发它给不了的东西,或者直接选一个本来就支持的组。

  • 先建一个自定义模型,把你原来用的模型名当它的名字,路由到对应的能力组。
  • 改 base URL 和 key,跑一遍你的测试。
  • 对照 /models 页确认系数,用控制台的用量明细核对第一天的账。

第三步别跳过。 第一天就把账对上,比事后发现对不上再来查要省事得多——我们也希望你养成这个习惯。

文档还在持续补充。缺什么、哪里写得不清楚,发一封邮件到 support@agiplan.dev,我们会改并记在更新日志里。