CNB NPC 万界 API 集成工作流
概述
本 Skill 指导如何在 CNB(Cloud Native Build)平台上创建自定义 NPC,使用万界 API(OpenAI 兼容接口)替代 CNB 内置 AI 模型,从而彻底脱离 CNB Credit 计费。
适用场景
- 你想用自己已有的万界/其他 OpenAI 兼容 API Key
- 你需要在 CNB NPC 中使用特定模型(如 GLM-5.1、DeepSeek 系列)
- 你希望控制成本(万界 API 按量计费,不用 CNB Credit)
- 你需要自定义 NPC 行为(白名单、角色定制)
架构概览
用户 @NPC 评论 → CNB NPC 事件触发
↓
自定义 Docker 容器启动
↓
npc-agent.js 读取 CNB_NPC_* 环境变量
↓
调用万界 API (OpenAI 兼容格式)
↓
回复 Issue/PR 评论2. 快速开始(5 分钟)
前提
- 一个 CNB 组织(如
cnbnpc) WANJIE_API_KEY(万界平台获取的完整 JWT Key)- Docker 环境(本地或 CNB 流水线均可)
步骤
2.1 创建 NPC 仓库
bash
# 在 cnbnpc 组织下创建仓库,或 fork 现有模板
# 推荐点此 fork: https://cnb.cool/cnbnpc/CodeBuddy2.2 创建 Dockerfile
dockerfile
FROM docker.cnb.cool/cnb/npc-js-runtime:latest
WORKDIR /app
COPY . .
# 注意:API Key 通过 ARG 构建时注入,不在代码中硬编码!
ARG WANJIE_API_KEY
ENV WANJIE_API_KEY=$WANJIE_API_KEY
ENV AI_BASE_URL=https://maas-openapi.wanjiedata.com/api/v1
CMD ["node", "npc-agent.js"]2.3 创建 .cnb/npc-agent.js
javascript
const API_KEY = process.env.WANJIE_API_KEY || process.env.PLUGIN_WANJIE_API_KEY || process.env.CNB_SECRET_WANJIE_API_KEY;
const BASE_URL = process.env.AI_BASE_URL || 'https://maas-openapi.wanjiedata.com/api/v1';
const content = process.env.CNB_NPC_TRIGGER_CONTENT;
const prompt = process.env.CNB_NPC_PROMPT;
const model = process.env.CNB_NPC_NAME || 'glm-5.1';
const replyUrl = process.env.CNB_NPC_TRIGGER_URL;
const user = process.env.CNB_NPC_TRIGGER_USER;
if (!API_KEY) { console.error('❌ API Key 未配置'); process.exit(1); }
async function main() {
const resp = await fetch(`${BASE_URL}/chat/completions`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
model,
messages: [
{ role: 'system', content: prompt },
{ role: 'user', content }
]
})
});
const data = await resp.json();
const reply = data.choices?.[0]?.message?.content || '❌ 无响应';
// 回复 Issue/PR
await fetch(replyUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: reply })
});
}
main().catch(console.error);2.4 配置 .cnb.yml
yaml
main:
push:
- services:
- docker
stages:
- name: docker build & push
script: |
docker build \
--build-arg WANJIE_API_KEY=${WANJIE_API_KEY:-${PLUGIN_WANJIE_API_KEY:-}} \
-t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest .
docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
npc:
roles:
- name: MyNPC
avatar: 🤖
model: npc_agent
work_mode: true
system_prompt: |
你是 MyNPC,一个使用万界 API 的 AI 助手。
用中文回答,简洁专业。
trigger:
service:
pipeline: image
image: ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest2.5 设置 settings(API Key 安全注入)
在 .cnb.yml 顶层添加:
yaml
settings:
WANJIE_API_KEY: "{{ secrets.WANJIE_API_KEY }}"或者在 CNB 组织 → 设置 → 密钥 中创建 WANJIE_API_KEY 环境变量。
2.6 构建 & 推送
bash
# 本地构建
docker build --build-arg WANJIE_API_KEY=你的Key -t docker.cnb.cool/cnbnpc/你的仓库:latest .
# 登录并推送
docker login -u cnb -p $CNB_TOKEN docker.cnb.cool
docker push docker.cnb.cool/cnbnpc/你的仓库:latest
# 或直接推代码,CNB 流水线自动构建
git push origin main2.7 测试 NPC
在仓库 Issue 中评论:
@cnbnpc/MyNPC(glm-5.1) 你好,测试一下3. 完整工作流
阶段 1:设计 & 准备
- 确定 NPC 用途、角色名、模型
- 获取万界 API Key
- 创建 CNB 组织(或使用现有组织)
阶段 2:仓库搭建
- 创建/fork NPC 仓库
- 配置 Dockerfile
- 编写 npc-agent.js
- 配置 .cnb.yml(构建流水线 + NPC 事件 + settings)
阶段 3:构建 & 部署
- 注入 API Key 构建 Docker 镜像
- 推送到 CNB Docker Registry
- 验证 NPC 事件触发正常
阶段 4:安全加固
- 添加白名单访问控制
- 迁移 API Key 到 CNB Secrets
- 清理 git history 中的明文 Key
阶段 5:优化 & 监控
- 流水线 lint 非阻塞
- 添加 token 消耗记录
- 添加错误处理 & 重试
4. 配置详解
4.1 Dockerfile 配置
dockerfile
FROM docker.cnb.cool/cnb/npc-js-runtime:latest
LABEL maintainer="your-org"
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
# ⚠️ API Key 通过构建时 ARG 注入
# 不要在代码中写死!
ARG WANJIE_API_KEY
ENV WANJIE_API_KEY=$WANJIE_API_KEY
# 万界 API 端点(也可通过 settings 注入)
ENV AI_BASE_URL=https://maas-openapi.wanjiedata.com/api/v1
CMD ["node", "npc-agent.js"]4.2 .cnb.yml 完整模板
yaml
# ============================================
# CNB NPC 万界 API 集成 — .cnb.yml 完整模板
# ============================================
settings:
# API Key(从 CNB 组织密钥读取)
# 需在 cnbnpc → 设置 → 密钥 创建 WANJIE_API_KEY
WANJIE_API_KEY: "{{ secrets.WANJIE_API_KEY }}"
# ----- 构建流水线 -----
main:
push:
- services:
- docker
stages:
- name: docker build & push
image: docker:24-cli
volumes:
- /var/run/docker.sock:/var/run/docker.sock
script: |
# 构建时注入 API Key
docker build \
--build-arg WANJIE_API_KEY=${WANJIE_API_KEY} \
-t ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest .
docker push ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest
- name: lint & format check (non-blocking)
image: node:22-slim
script: |
npm ci 2>/dev/null
npm run format:check 2>/dev/null || true
npm run lint 2>/dev/null || true
# ----- NPC 角色定义 -----
npc:
roles:
- name: MyNPC
avatar: 🤖
model: npc_agent
work_mode: true
system_prompt: |
你是一个使用万界 API 的 AI 助手。
你是代码审查和问题诊断专家。
用中文回答,简洁专业。
trigger:
service:
pipeline: image
image: ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest4.3 npc-agent.js 完整脚本
见
references/npc-agent.js示例文件
4.4 白名单控制
在 src/index.ts 或 npc-agent.js 中添加:
javascript
// 白名单:仅允许这些用户触发
const ALLOWED_USERS = ['hejianhong', 'cnbnn', 'nawaer'];
const currentUser = process.env.CNB_NPC_TRIGGER_USER;
if (!ALLOWED_USERS.includes(currentUser)) {
console.warn(`⛔ 未授权用户: ${currentUser}`);
// 回复拒绝消息
await fetch(replyUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: `⚠️ 此 NPC 仅限授权成员使用` })
});
process.exit(0);
}5. API Key 安全指南
5.1 安全优先级(从最安全到最不安全)
| 方案 | 安全等级 | 说明 |
|---|---|---|
| CNB 组织 Secrets | ⭐⭐⭐ | 最佳:Key 不出现在任何文件中 |
| Dockerfile ARG+ENV | ⭐⭐ | 次优:Key 在镜像层中 |
.cnb.yml settings | ⭐⭐ | 同 Dockerfile ARG |
| 代码硬编码 | ❌ | 极度危险,git history 抹不掉 |
5.2 Key 注入链路
┌─ CNB Secrets ──────────────────────┐
│ cnbnpc → 设置 → 密钥 → WANJIE_API_KEY │
└───────────┬─────────────────────────┘
│ {{ secrets.WANJIE_API_KEY }}
▼
┌─ .cnb.yml settings ────────────────┐
│ WANJIE_API_KEY: "{{ secrets.... }}" │
│ 自动转为 → PLUGIN_WANJIE_API_KEY │
└───────────┬─────────────────────────┘
│ 环境变量 image: 容器中生效
▼
┌─ Docker 容器 ──────────────────────┐
│ npc-agent.js 读取优先顺序: │
│ 1. WANJIE_API_KEY (直接 ENV) │
│ 2. PLUGIN_WANJIE_API_KEY (settings)│
│ 3. CNB_SECRET_WANJIE_API_KEY │
└────────────────────────────────────┘5.3 Key 泄露处理
如果 Key 已暴露(如在公开仓库历史中):
- 立即去万界控制台轮换 Key
- 更新 CNB Secrets 中的值
- 重建 Docker 镜像
- 清理或归档旧仓库
6. 踩坑记录
| # | 问题 | 原因 | 解决方案 |
|---|---|---|---|
| 1 | env: 块的 Key 不传到 image: 容器 | CNB pipeline 设计如此 | 改用 Dockerfile ARG+ENV 或 settings |
| 2 | Fork 仓库不能改私有 | CNB 策略 | 改用 CNB Secrets + 不暴露明文 |
| 3 | settings.AI_BASE_URL 为 null | CNB 不支持此 key | 代码硬编码 endpoint |
| 4 | YAML 锚点解析失败 | CNB YAML 解析器限制 | 手写完整值,不用锚点 |
| 5 | build 跑完但镜像没更新 | lint 失败阻塞了 build | 调整阶段顺序:build 先 run |
| 6 | 白名单写了不生效 | 镜像没重建 | 手动触发构建或改代码文件 push |
| 7 | workspace SSH 连不上 | 网络超时或断开 | 重试或换用户后缀 |
| 8 | Node.js 报 Invalid character in header | Key 被微信截断为 Unicode | 用环境变量传递,不经聊天 |
7. 自修复工作流
本 Skill 支持 NPC 自修复——让 NPC 自己分析并修复自身代码问题。
流程
- 创建 Issue 描述问题
- 在 Issue 中 @NPC 并设置
work_mode: true - NPC 分析代码 → 修改 → commit → push
- 验证修复
触发模板
@cnbnpc/MyNPC(glm-5.1) work_mode: true
请分析 Issue 中的问题并修复:
1. <问题1>
2. <问题2>
提交修改并 push。8. 多角色配置
一个仓库可配置多个 NPC 角色,每个角色用不同模型:
yaml
npc:
roles:
- name: CodeBuddy
avatar: 🤖
model: npc_agent
system_prompt: 你是一个严谨的代码审查专家...
trigger:
service:
pipeline: image
image: ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest
- name: CodeWhale
avatar: 🐳
model: npc_agent
system_prompt: 你是一个全栈开发专家,可以修改代码并提交...
work_mode: true
trigger:
service:
pipeline: image
image: ${CNB_DOCKER_REGISTRY}/${CNB_NPC_SLUG_LOWERCASE}:latest9. 故障排除
9.1 NPC 不响应
- 检查
.cnb.yml的 NPC 事件配置是否正确 - 检查 Docker 镜像是否已推送
- 检查流水线日志是否有错误
9.2 镜像未更新
- 确认
ifModify或changes条件匹配了本次修改的文件 - 检查 lint 阶段是否阻塞了 build 阶段
- 手动在 workspace 中执行
docker build && docker push
9.3 API Key 相关问题
- 万界 API 对 CNB 流水线 IP 有效,对其他 IP 可能返回
apiKey not found - 验证 Key:
curl -s -H "Authorization: Bearer $KEY" https://maas-openapi.wanjiedata.com/api/v1/chat/completions
9.4 白名单不生效
- 确认镜像已重建(跑的是否是旧镜像)
- 确认
CNB_NPC_TRIGGER_USER环境变量正确 - 检查用户名的精确拼写
10. 参考
- 万界 API 文档: https://docs.wjark.com/maas/Interface.html
- CNB NPC 文档: https://docs.cnb.cool/zh/build/npc.html
- CNB OpenAPI 文档: https://api.cnb.cool/#/
- 示例仓库: