# pigo 协作 —— 调用文档 > 在 Docker 容器内运行一个 pigo agent(单 agent)完成 /blackboard/task.md 中的任务,工作区为 /blackboard/workspace,完成时通过 blackboard 工具创建 DONE;supervisor 把结果以结构化 JSON(result.json)落盘,供外部调度方直接解析。 --- ## 1. 原理与架构 ``` +------------------ docker 容器 pigo-coop ----------------+ | | TASK/MODEL/ | +---------- supervisor.sh(单 agent 编排)-------+ | API_KEY ──────┼─▶ | 每轮运行一个 pigo 进程: | | | | └─ agent ──▶ cwd = /blackboard/workspace | | | | (--resume 会话 · 角色 prompt agent.md) | | | +──────┬────────────────────────────────----------+ | | ▼ | | /blackboard(任务黑板:task.md + workspace + DONE) | +-----------------------------------------------------------+ ``` - **单 agent**:每轮一个 pigo 进程串行推进,无评审者;工作区 `/blackboard/workspace` 是普通文件工具(read/write/bash)的根目录。 - **原子完成标记**:`DONE` 只能通过 `blackboard` 工具 `done`(`O_CREATE|O_EXCL`)创建,supervisor 检测到 `DONE` 即收尾。 - **连续上下文**:headless 运行自动持久化会话,supervisor 从 stream-json 首事件提取 `sessionId`,下一轮用 `--resume` 恢复,agent 跨轮记住自己的思考。 - **协议注入**:任务协议(AGENTS.md)副本放入工作区,pigo 自动注入系统提示;角色 prompt 通过 `--append-system-prompt` 注入。 - **结构化结果**:任务结束(成功/未解出/超时/失败)统一写 `$BB/result.json`,字段:`status`、`exit_code`、`summary`、`flag`、`artifacts`。 --- ## 2. 前置条件 | 依赖 | 说明 | | --- | --- | | Go 工具链 | 版本与 `go.mod` 一致(当前 `go 1.27rc1`),用于交叉编译 pigo 二进制 | | Docker | 本机已有基础镜像 `pigo-worker:latest`(Alpine,含 bash/git/wget/flock/timeout/CA 证书) | | 模型后端 | 任意 OpenAI 兼容 API(如 DeepSeek、Ollama、OpenRouter),需可访问的 base-url 与 API key | --- ## 3. 构建 ### 3.1 交叉编译 pigo(含 blackboard 工具) Windows PowerShell: ```powershell $env:GOOS="linux"; $env:CGO_ENABLED="0" go build -trimpath -ldflags="-s -w" -o coop/tmp/pigo-linux-amd64 ./cmd/pigo ``` Linux/macOS: ```bash GOOS=linux CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o coop/tmp/pigo-linux-amd64 ./cmd/pigo ``` 产物 `coop/tmp/pigo-linux-amd64` 是纯静态 Linux 二进制(约 30MB)。 ### 3.2 构建镜像 ```bash docker build -f coop/Dockerfile -t pigo-coop . ``` > 镜像直接 `FROM pigo-worker:latest`(复用本机已有镜像,不拉取 golang/alpine),只覆盖 pigo 二进制并加入 supervisor 与协作 prompt,构建通常秒级完成。 --- ## 4. 环境变量(运行参数) | 变量 | 必填 | 默认值 | 说明 | | --- | --- | --- | --- | | `MODEL` | ✅ | — | 模型名,如 `deepseek-chat` | | `BASE_URL` | ✅ | — | OpenAI 兼容 API base-url | | `API_KEY` | ✅ | — | API key | | `PROTOCOL` | 否 | 按 model 推断 | 协议 `openai` / `anthropic` | | `TASK` | 二选一 | — | 任务描述;不填则需挂载 `$BB/task.md` | | `BLACKBOARD` | 否 | `/blackboard` | 黑板根目录(即 `BB`) | | `PROMPTS` | 否 | `/prompts` | 协作 prompt 目录(镜像内固定,一般不用改) | | `ROUND_MAX` | 否 | `10` | 最大轮次 | | `TIMEOUT` | 否 | `600` | 单轮超时秒数,`0`=不超时 | | `FAIL_MODE` | 否 | `stop` | agent 失败时:`stop`=立即退出(默认)\| `continue`=继续下一轮 | --- ## 5. 运行示例 ### 5.1 最小运行(真实模型) ```bash docker run --rm \ -e MODEL=deepseek-chat \ -e BASE_URL=https://api.deepseek.com \ -e API_KEY= \ -e TASK="请为 XX 编写设计文档并实现原型" \ -e ROUND_MAX=6 \ pigo-coop ``` ### 5.2 保留黑板产物与连续会话(推荐) ```bash mkdir -p blackboard docker run --rm \ -v $PWD/blackboard:/blackboard \ # 黑板产物落盘 -v $HOME/.pigo:/root/.pigo \ # 保留 agent 会话(--resume 依赖) -e MODEL=deepseek-chat \ -e BASE_URL=https://api.deepseek.com \ -e API_KEY= \ -e TASK="..." \ pigo-coop ``` > 会话持久化在 `~/.pigo/sessions`(容器内为 `/root/.pigo`)。**不挂载 `$HOME` 时,会话只存在于容器生命周期内**——跨 `docker run` 不保留;每次 `run` 内部跨轮仍有效。 ### 5.3 结果与退出码 - 任务完成(检测到 `DONE`):退出码 `0`,`result.json` 的 `status=solved`。 - 达到 `ROUND_MAX` 仍未完成:退出码 `1`,`status=unsolved`,检查黑板与日志。 - 单轮超时被强杀:`status=timeout`(退出码 124)。 - 参数缺失 / 非法:退出码 `2`。 --- ## 6. 黑板目录结构 ``` /blackboard/ ├── task.md # 任务描述(勿修改) ├── AGENTS.md # 任务协议(工作区有副本) ├── workspace/ # agent 工作区 = 其 cwd(产物全部在这里) ├── DONE # 完成标记(只用 blackboard done 创建) ├── result.json # 结构化结果(supervisor 结束时生成) ├── sessions/ # agent 的 session id(supervisor 内部维护,供 --resume) └── logs/ # 每轮运行日志:round-N.log ``` --- ## 7. blackboard 工具(agent 侧 API) pigo 在 `BB` 环境变量存在时自动注册 `blackboard` 工具;普通运行不受影响。agent 通过该工具原子读写黑板: | 操作 | 参数 | 行为 | | --- | --- | --- | | `read` | (可选 `path`) | 无 `path`:返回黑板全局快照(task.md、workspace 清单、DONE 状态、环境);有 `path`:返回黑板内单文件内容(如 `workspace/exploit.py`) | | `post` | `file`、`content` | 原子追加消息到 `messages/`;`file` 必须是裸 `*.md` 名(防目录穿越),内容 ≤ 32 KiB | | `done` | `summary` | 原子创建 `DONE`(`O_CREATE|O_EXCL`);已存在则报错且不覆盖。仅交付完整时调用 | 环境变量 `BB` / `ROUND` / `NAME` 由 supervisor 注入。 --- ## 8. 验证与调试 ### 8.1 无模型端到端验证(mock) `coop/tmp/mock_openai.py` 是一个 OpenAI 兼容 mock server,驱动 agent 依次调用 `blackboard done`,用于验证单 agent 编排与 DONE 原子性: ```bash # 终端 1:启动 mock(本机) python coop/tmp/mock_openai.py 8899 # 终端 2:运行容器,base-url 指向 mock(按环境替换宿主地址) docker run --rm \ -v $PWD/blackboard:/blackboard \ -e MODEL=mock -e BASE_URL=http://:8899 -e API_KEY=test \ -e TASK="验证任务" -e ROUND_MAX=3 -e TIMEOUT=120 \ pigo-coop ``` 预期:agent 完成并创建 `DONE`,容器退出 0,`blackboard/result.json` 中 `status=solved`。 ### 8.2 查看日志 ```bash # 黑板挂载后: cat blackboard/logs/round-1.log # 第 1 轮的 stream-json 事件 cat blackboard/sessions/agent.session # 下一轮 --resume 用的 session id ``` ### 8.3 常见问题 | 现象 | 原因 / 处理 | | --- | --- | | 退出码 `2` 且提示缺 MODEL/BASE_URL/API_KEY | 未传必填环境变量 | | 容器内报 `DONE already exists` | 正常:DONE 幂等,上一次运行已留标记 | | 跨 run 后 agent 不记得之前轮次 | 未挂载 `$HOME/.pigo`;会话在容器内 `~/.pigo/sessions`,`--rm` 后丢失 | | `docker build` 报找不到 `pigo-worker:latest` | 先 `docker pull` 或在目标机导入该基础镜像 | | 构建期 `chmod` 被拒 | 已用 `COPY --chmod=755` 规避(NTFS 挂载构建上下文会丢可执行位) | --- ## 9. 任务协议要点(详见 `/blackboard/AGENTS.md`) 每轮:**读取 task.md → 检查已有产物 → 推进任务 → 完成后用 blackboard done 创建 DONE**。红线:不直接写 DONE;不伪造命令/提交结果;不修改 task.md 与 AGENTS.md。