☰
用 Go 实现 Ralph Loop:基于 GitHub Copilot SDK 的自主 AI 任务循环
2026/10/10 5:26:12 网站建设 项目流程
  • 文档
  • 知识库
  • AI 技能/插件

【免费下载链接】awesome-copilot

Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.

项目地址:https://gitcode.com/GitHub_Trending/aw/awesome-copilot
点击查看免费下载

导读

Ralph Loop 是一种"状态存磁盘、上下文不累积"的自主开发工作流:AI Agent 在每次迭代都使用全新的上下文窗口,从磁盘读取任务与计划、实现一个任务、通过测试与构建的"背压"校验、提交并退出,然后开启下一轮。本文基于 awesome-copilot 仓库中 cookbook/copilot-sdk/go/ralph-loop.md 的完整方案,讲解如何用 Go 语言与 GitHub Copilot SDK 从零构建这套循环:你将掌握最小可运行的简单版、带 PLANNING/BUILDING 双模式的理想版、配套的项目文件规范(PROMPT_plan.md、PROMPT_build.md、AGENTS.md、IMPLEMENTATION_PLAN.md),以及 10 条防止 Agent 跑偏的工程最佳实践。文末还提供可直接运行的 recipe/ralph-loop.go 完整源码路径。

Ralph Loop 是什么

Ralph Loop 得名于其作者提出的"循环"开发模式,本质是一段无人值守的自动化脚本:AI Agent 在彼此隔离的上下文窗口中反复执行"读状态 → 干活 → 写回状态 → 退出"的闭环。核心洞察只有一句话:

状态存在磁盘上,而不是存在模型的上下文里。

每一次迭代都从一张"白纸"开始:会话读取当前状态(任务计划、规格说明、代码),只完成一个任务,把结果写回磁盘,然后退出。下一轮迭代又开启一个全新的会话,继续读取磁盘上最新的状态。这样模型永远工作在上下文窗口的"聪明区"(smart zone),不会因为对话越来越长而出现注意力分散、指令遗忘等问题。

循环流程示意

┌─────────────────────────────────────────────────┐ │ loop.sh │ │ while true: │ │ ┌─────────────────────────────────────────┐ │ │ │ Fresh session (isolated context) │ │ │ │ │ │ │ │ 1. Read PROMPT.md + AGENTS.md │ │ │ │ 2. Study specs/* and code │ │ │ │ 3. Pick next task from plan │ │ │ │ 4. Implement + run tests │ │ │ │ 5. Update plan, commit, exit │ │ │ └─────────────────────────────────────────┘ │ │ ↻ next iteration (fresh context) │ └─────────────────────────────────────────────────┘

四条核心原则

  1. 每次迭代都是全新上下文(Fresh context per iteration):循环的每一轮都创建新的会话,不累积任何历史上下文,Agent 永远处于"聪明区"。
  2. 磁盘即共享状态(Disk as shared state):IMPLEMENTATION_PLAN.md在多次迭代之间持久存在,是各隔离会话之间唯一的协调机制。
  3. 背压驱动质量(Backpressure steers quality):测试、构建、Lint 会拒绝糟糕的工作——Agent 必须先把问题修好才能提交,质量由硬性校验把关而非靠提示词自觉。
  4. 两种运行模式(Two modes):PLANNING(差距分析 → 生成计划)与BUILDING(依据计划实现任务)。

在 awesome-copilot 仓库中,这一配方被收录于 cookbook/copilot-sdk/go/ralph-loop.md,并提供了可直接运行的 recipe/ralph-loop.go 示例;同一配方在 .NET、Node.js、Python、Java 四个语言目录下也有对应实现,详见 cookbook/copilot-sdk/README.md。

简单版本:最小编码循环

最小化的 Ralph Loop 是 SDK 版的一条等价命令:

while :; do cat PROMPT.md | copilot ; done

即:反复把同一个提示词文件喂给 Copilot CLI,让 Agent 读项目文件、干活、提交、退出,然后以干净状态重新开始。用 Go SDK 表达这段逻辑只有约 90 行:

package main import ( "context" "fmt" "log" "os" copilot "github.com/github/copilot-sdk/go" ) func ralphLoop(ctx context.Context, promptFile string, maxIterations int) error { client := copilot.NewClient(nil) if err := client.Start(ctx); err != nil { return err } defer client.Stop() prompt, err := os.ReadFile(promptFile) if err != nil { return err } for i := 1; i <= maxIterations; i++ { fmt.Printf("\n=== Iteration %d/%d ===\n", i, maxIterations) // Fresh session each iteration — context isolation is the point session, err := client.CreateSession(ctx, &copilot.SessionConfig{ OnPermissionRequest: copilot.PermissionHandler.ApproveAll, Model: "gpt-5.3-codex", }) if err != nil { return err } _, err = session.SendAndWait(ctx, copilot.MessageOptions{ Prompt: string(prompt), }) session.Disconnect() if err != nil { return err } fmt.Printf("Iteration %d complete.\n", i) } return nil } func main() { if err := ralphLoop(context.Background(), "PROMPT.md", 20); err != nil { log.Fatal(err) } }

逐段拆解这段代码的工作方式:

  • copilot.NewClient(nil)创建 SDK 客户端,client.Start(ctx)启动底层 Copilot 运行时,defer client.Stop()保证程序退出时资源被回收——这与仓库内 error-handling.md 强调的"始终用 defer 确保Stop()被调用"的清理规范一致。
  • 提示词文件(PROMPT.md)在循环外只读一次,作为每轮迭代的固定指令。
  • for i := 1; i <= maxIterations; i++控制迭代次数上限,防止无人值守时无限运行。
  • 关键点:每一轮迭代都调用client.CreateSession创建全新会话,上下文隔离正是 Ralph Loop 的意义所在;session.Disconnect()在每轮末尾显式断开,避免残留连接。
  • copilot.PermissionHandler.ApproveAll自动批准工具调用权限,让 Agent 可以自主执行文件读写、命令运行等操作而不中断循环。

这段代码就够起步了:提示词文件告诉 Agent 做什么,Agent 读取项目文件、完成工作、提交、退出,循环以全新状态重新开始。

理想版本:PLANNING 与 BUILDING 双模式

完整版的 Ralph 模式引入规划与构建两种模式,对应 Ralph Playbook 的架构。它比简单版多出三样东西:模式选择(决定读取哪个提示词文件)、固定工作目录(WorkingDirectory,保证工具调用路径解析正确)、工具调用可视化日志(通过session.On监听事件)。

package main import ( "context" "fmt" "log" "os" "strconv" "strings" copilot "github.com/github/copilot-sdk/go" ) func ralphLoop(ctx context.Context, mode string, maxIterations int) error { promptFile := "PROMPT_build.md" if mode == "plan" { promptFile = "PROMPT_plan.md" } client := copilot.NewClient(nil) if err := client.Start(ctx); err != nil { return err } defer client.Stop() cwd, _ := os.Getwd() fmt.Println(strings.Repeat("━", 40)) fmt.Printf("Mode: %s\n", mode) fmt.Printf("Prompt: %s\n", promptFile) fmt.Printf("Max: %d iterations\n", maxIterations) fmt.Println(strings.Repeat("━", 40)) prompt, err := os.ReadFile(promptFile) if err != nil { return err } for i := 1; i <= maxIterations; i++ { fmt.Printf("\n=== Iteration %d/%d ===\n", i, maxIterations) session, err := client.CreateSession(ctx, &copilot.SessionConfig{ Model: "gpt-5.3-codex", WorkingDirectory: cwd, OnPermissionRequest: func(_ copilot.PermissionRequest, _ copilot.PermissionInvocation) (copilot.PermissionRequestResult, error) { return copilot.PermissionRequestResult{Kind: "approved"}, nil }, }) if err != nil { return err } // Log tool usage for visibility session.On(func(event copilot.SessionEvent) { if d, ok := event.Data.(*copilot.ToolExecutionStartData); ok { fmt.Printf(" ⚙ %s\n", d.ToolName) } }) _, err = session.SendAndWait(ctx, copilot.MessageOptions{ Prompt: string(prompt), }) session.Disconnect() if err != nil { return err } fmt.Printf("\nIteration %d complete.\n", i) } fmt.Printf("\nReached max iterations: %d\n", maxIterations) return nil } func main() { mode := "build" maxIterations := 50 for _, arg := range os.Args[1:] { if arg == "plan" { mode = "plan" } else if n, err := strconv.Atoi(arg); err == nil { maxIterations = n } } if err := ralphLoop(context.Background(), mode, maxIterations); err != nil { log.Fatal(err) } }

命令行参数

main函数解析os.Args决定运行模式与迭代次数,仓库内 recipe/ralph-loop.go 的注释给出了四种用法:

命令行为
go run ralph-loop.go默认 BUILDING 模式,最多 50 次迭代
go run ralph-loop.go planPLANNING 模式,生成/更新IMPLEMENTATION_PLAN.md
go run ralph-loop.go 20BUILDING 模式,限制为 20 次迭代
go run ralph-loop.go plan 5PLANNING 模式,限制为 5 次迭代

解析逻辑:参数等于plan则切到规划模式;参数可被strconv.Atoi解析为整数则当作迭代次数上限。运行时输出一段分隔线与模式摘要,便于在无人值守时快速确认本次运行配置。

与简单版的三处关键差异

  • WorkingDirectory: cwd:把会话的工作目录固定到项目根目录(os.Getwd()获取),Agent 执行文件操作与命令时路径解析始终正确。这也是最佳实践第 9 条"Pin the session to your project root"的代码级落实。
  • 手动批准回调:用内联函数替代PermissionHandler.ApproveAll,返回copilot.PermissionRequestResult{Kind: "approved"}实现同样的自动批准,但保留了对权限请求的完全控制权。
  • 工具使用日志:session.On订阅会话事件,一旦收到*copilot.ToolExecutionStartData就打印工具名(⚙ <ToolName>)。这让运维人员能实时观察 Agent 每一步在调用什么工具,是排查循环卡死或行为异常的"仪表盘"。

理想版依赖的项目文件结构

理想版假设项目根目录存在以下文件结构:

project-root/ ├── PROMPT_plan.md # Planning mode instructions ├── PROMPT_build.md # Building mode instructions ├── AGENTS.md # Operational guide (build/test commands) ├── IMPLEMENTATION_PLAN.md # Task list (generated by planning mode) ├── specs/ # Requirement specs (one per topic) │ ├── auth.md │ └──>0a. Study `specs/*` to learn the application specifications. 0b. Study IMPLEMENTATION_PLAN.md (if present) to understand the plan so far. 0c. Study `src/` to understand existing code and shared utilities. 1. Compare specs against code (gap analysis). Create or update IMPLEMENTATION_PLAN.md as a prioritized bullet-point list of tasks yet to be implemented. Do NOT implement anything. IMPORTANT: Do NOT assume functionality is missing — search the codebase first to confirm. Prefer updating existing utilities over creating ad-hoc copies.

要点拆解:

  • 0a/0b/0c三步是"先读后写":先读规格、读现有计划、读源码,形成全局认知。
  • 第 1 步明确要求只做差距分析并输出带优先级的任务清单,明令"不要实现任何东西"——规划模式与构建模式职责严格分离。
  • 末尾的 IMPORTANT 是防幻觉护栏:禁止凭空假设功能缺失,必须先搜索代码库确认;优先扩展现有工具函数而不是临时复制一份。这条护栏直接呼应了最佳实践中"Observe and tune,按 Agent 的具体失败方式给提示词加护栏"的理念。

PROMPT_build.md:构建模式提示词

0a. Study `specs/*` to learn the application specifications. 0b. Study IMPLEMENTATION_PLAN.md. 0c. Study `src/` for reference. 1. Choose the most important item from IMPLEMENTATION_PLAN.md. Before making changes, search the codebase (don't assume not implemented). 2. After implementing, run the tests. If functionality is missing, add it. 3. When you discover issues, update IMPLEMENTATION_PLAN.md immediately. 4. When tests pass, update IMPLEMENTATION_PLAN.md, then `git add -A` then `git commit` with a descriptive message. 5. When authoring documentation, capture the why. 6. Implement completely. No placeholders or stubs. 7. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it.

要点拆解:

  • 第 1 步:从计划中挑选最重要的一项,改动前先搜索代码库,再次强调"不要假设未实现"。
  • 第 2 步:实现后必须运行测试,功能缺失就补上——这是背压机制在提示词层的体现。
  • 第 3~4 步:发现问题时立即更新计划;测试通过后先更新IMPLEMENTATION_PLAN.md,再git add -A并提交。提交放在最后,保证磁盘上的计划永远是最新状态。
  • 第 5~7 步是质量约束:文档要记录"为什么"、实现必须完整无占位符、计划必须保持最新(后续迭代依赖它)。

AGENTS.md:操作指南(保持精简)

AGENTS.md每次迭代都会被加载,因此冗余内容只会浪费上下文。保持约 60 行,只放运营信息:

## Build & Run go build ./... ## Validation - Tests: `go test ./...` - Vet: `go vet ./...`

它不记录进度、不做笔记,只提供 Agent 每轮迭代执行验证所需的命令入口——测试与构建命令正是"背压"的具体承载。

最佳实践清单

理想版的鲁棒性不只来自代码,更来自以下 10 条工程纪律:

  1. 每次迭代全新上下文(Fresh context per iteration):绝不跨迭代累积上下文——这正是 Ralph Loop 的全部意义。
  2. 磁盘就是数据库(Disk is your database):IMPLEMENTATION_PLAN.md是隔离会话之间唯一的共享状态。
  3. 背压不可或缺(Backpressure is essential):测试、构建、Lint 都要写进AGENTS.md,Agent 必须全部通过才能提交。
  4. 先进入 PLANNING 模式(Start with PLANNING mode):先生成计划,再切换到 BUILDING。
  5. 观察并调优(Observe and tune):盯住前几轮迭代,当 Agent 以特定方式失败时,给提示词补护栏。理想版中的工具使用日志(session.On监听ToolExecutionStartData)正是服务于这条实践的观测手段。
  6. 计划是可丢弃的(The plan is disposable):Agent 跑偏时,直接删除IMPLEMENTATION_PLAN.md重新规划。
  7. 保持AGENTS.md精简(Keep AGENTS.md brief):它每轮都加载,只放运营信息,不放进度笔记。
  8. 使用沙箱(Use a sandbox):Agent 以全工具权限自主运行,必须隔离执行环境。
  9. 设置WorkingDirectory(Set WorkingDirectory):把会话固定到项目根目录,工具操作的路径解析才不会出错。
  10. 自动批准权限(Auto-approve permissions):用OnPermissionRequest允许工具调用,避免每轮迭代被打断。

第 9、10 条对应理想版代码中的WorkingDirectory: cwd与内联OnPermissionRequest回调;第 5 条对应session.On事件订阅。可以看到,这份清单并非空泛建议,而是与代码一一对应的可操作规范。

何时适合用 Ralph Loop

适合的场景

  • 依据规格实现功能,且能用测试驱动验证。
  • 大型重构拆解成大量小任务后逐个击破。
  • 无人值守的长时开发,需求清晰明确。
  • 任何背压机制(测试/构建)能验证正确性的工作。

不适合的场景

  • 中途需要人类判断的任务——循环无人值守,无法在迭代中途介入决策。
  • 一次性操作——不迭代就没有意义。
  • 需求模糊、缺乏可测试验收标准的工作——背压无从施加。
  • 方向不明的探索性原型开发——连计划都无法生成。

判断标准可以归结为一句话:当正确性可以用测试与构建自动验证时,Ralph Loop 才有发挥空间;当每一步都需要人做价值判断时,它反而会加速错误。

运行与验证

仓库内已提供完整的可运行实现。运行前置条件与命令如下:

# 依赖:Go 1.21+ 与 GitHub Copilot SDK for Go go get github.com/github/copilot-sdk/go # 进入 Go 配方目录运行示例(默认构建模式) cd go go run recipe/ralph-loop.go # 带参数运行:规划模式 / 限制迭代次数 go run recipe/ralph-loop.go plan go run recipe/ralph-loop.go 20

更多配方(错误处理、多会话、本地文件管理、PR 可视化、会话持久化)的说明见 cookbook/copilot-sdk/go/README.md,其可运行示例集中在 cookbook/copilot-sdk/go/recipe/ 目录下,每个.go文件都是完整的独立程序。

工程化增强建议

对照仓库内其他配方,可进一步强化 Ralph Loop 的健壮性:

  • 错误处理:参考 error-handling.md——为长时运行会话设置context.WithTimeout超时、用errors.As/errors.Is区分"CLI 未安装"与"连接超时"、用fmt.Errorf("%w")保留错误链。仓库源码 recipe/ralph-loop.go 已把文档版代码的错误处理升级为fmt.Errorf("failed to start client: %w", err)的包裹式写法,并记录了Disconnect失败日志——这是比文档版更完善的工程化范本,值得直接采用。
  • 会话恢复:参考 persisting-sessions.md——若某轮迭代中途崩溃,可用自定义SessionID+client.ResumeSession恢复上下文,避免整轮重跑。
  • 并行会话:参考 multiple-sessions.md——规划与构建、或多个模块的构建任务,可在不同会话中并行推进。

小结

Ralph Loop 用"磁盘状态 + 每次全新上下文 + 背压校验"三件套,把 AI 编码从一次性对话升级为可持续迭代的自动化流水线。Go 版实现仅需一个 SDK 客户端、一个循环、两套提示词文件,配合IMPLEMENTATION_PLAN.md作为跨会话的协调枢纽,即可在无人值守下完成"规划 → 实现 → 测试 → 提交"的闭环。当 Agent 行为偏离预期时,删除计划文件重新规划即可重置方向——这套可恢复、可观测、可调优的设计,正是它适合长时自主开发任务的原因。

  • 文档
  • 知识库
  • AI 技能/插件

【免费下载链接】awesome-copilot

Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.

项目地址:https://gitcode.com/GitHub_Trending/aw/awesome-copilot
点击查看免费下载

相关推荐

上一篇:深度诊断5大系统故障:AtlasOS进阶修复实战指南
下一篇:3行代码实现REST API可视化:PySimpleGUI网络请求实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询