开头部分我直接用从业者口吻切入说明“跑在 GitHub Actions 上的开源 AI Agent 框架”是什么用 GitHub Actions 的免费云环境来跑 AI Agent让 Agent 定期自动执行任务并把结果提交回仓库或者推送到自己的终端。说明适合谁想低成本搭建个人自动化、又不想维护服务器的人。然后展开。我要写大约6000字以上的内容。开始拟写留意自然、流畅、丰富。 最近我把一套开源 AI Agent 框架实际跑在了 GitHub Actions 上用免费的云环境定时执行任务agent 自己决策、自己调工具、自己把结果写回仓库。折腾了大半个月踩了不少坑也总结出一套真正能用的做法这里完整分享一下。先说这东西是什么所谓“跑在 GitHub Actions 上的开源 AI Agent 框架”本质就是借助 GitHub 提供的公有云 CI/CD 运行环境把 LLM 驱动的 Agent 程序打包成一个 workflow由 cron 定时触发、仓库事件触发或手动触发。GitHub 免费账号每月有 2000 分钟运行时长单次任务最长 6 小时对绝大多数个人自动化场景完全够用。这个方案适合不想维护服务器、又想搞定时型 AI Agent 的人比如自动收集行业信息、应急响应巡检、自动生成日报、监控开源项目动态等。先提醒一句这个思路不是把 Actions 当作无限算力的“免费白嫖机”而是借助它的托管环境加产物存储来做有状态任务。它解决的核心痛点是“Agent 需要一个稳定可靠的宿主”而 Actions 恰好提供了一整套现成的触发、隔离、日志、存储机制连运维都省了。1. 为什么把 AI Agent 放到 GitHub Actions 上跑1.1 这不是 CI/CD这是免费的消息驱动沙盒很多人对 GitHub Actions 的第一印象停留在“代码推送后自动跑测试、构建、部署”。但它本质上是一个事件驱动的分布式任务执行系统我把它当“云函数 定时任务 文件仓库”的组合拳用。一个 workflow 能收三类事件schedule定时、workflow_dispatch手动、push/pull_request代码事件。这就意味着只要把 Agent 代码写进 job 里它就能被 cron 在任意时间点唤醒。GitHub 官方仓库给的别名是“Actions 上的定时机器人”社区里也有不少把 Actions 当免费 cron 服务器用的例子但真正把 LLM Agent 跑进去的人还不多。举例我在一个公开仓库里放了每天凌晨 3 点自动运行的 Agent它负责扫描指定开源项目的 release 和 issue让大模型判断哪些变化值得关注然后整理成摘要提交回仓库并推送通知。整个过程不占用我本地任何资源也不需要在任何云厂商那里注册 cron 服务。1.2 这个思路真正能干什么定时型 Agent 是强需求但绝大多数人卡在“没有地方跑”。常见的替代方案是 PythonAnywhere、VPS、家里的树莓派它们要么收钱、要么要维护、要么断网失灵。GitHub Actions 把这三件事全包了它自带 Ubuntu 系统、公网 IP、包管理器、常用运行时跑完还能把产物直接推回 git 仓库天然保留历史记录。适合做这四类事情信息收集类定期抓取 RSS、GitHub 仓库动态、特定关键词搜索结果交给 Agent 聚合去重、生成摘要。决策辅助类每天定时分析行情/天气/指标让 Agent 结合上下文给出解读和建议。自动维护类对项目自动做依赖更新检查、issue 分类打标、Pull Request 审查。知识沉淀类定期把收集到的数据整理成 Markdown提交到仓库形成可检索的知识库。不适合做的事情也很明确实时性要求很高的任务不建议放 Actions因为 cron 任务误差可能到分钟级需要长连接或 WebSocket 的不适合因为每次运行都是全新环境重度依赖本地 IP 或内网服务的也不行Actions 和你本机不互通。1.3 Actions 与普通 VPS 的边界划分在实际选型时我习惯把任务分成两类一次性计算型和非交互长驻型。Actions 擅长前者VPS 擅长后者。Agent 如果只运行几分钟、输出结果后就退出Actions 几乎是零成本最优解但如果 Agent 需要保持状态、持续对话、监听回调还是得老老实实用服务器。还有一个容易被忽略的点Actions 的日志、环境变量加密、权限控制都是现成的不需要自己搭 prometheus 和 alert。每个 workflow 的每次运行都有完整日志失败时支持 webhook 通知和邮件通知对 Agent 这种“不可控输出”较多的程序来说可观测性非常重要。2. 开源 AI Agent 框架怎么选2.1 我比较过的三派方案目前主流的开源 AI Agent 框架大致分三个流派。第一派是 LangChain 系尤其是 LangGraph依赖生态最丰富什么工具都有但抽象层级极多学习成本高。第二派是 Anthropic 官方出的 Claude Agent SDK、OpenAI 出的 Agents SDK跟对应模型深度绑定好用但换模型麻烦。第三派是轻量级单文件 agent例如各路 Go 和 Python 社区自己写的 agent 包几百行代码就能跑灵活但工具生态靠手搓。我在 Actions 里没有一开始就用最重的框架而是先跑通了原生 API 直调。原生直调的 Agent 逻辑很简单大模型负责规划代码负责执行中间用 JSON 协议做函数调用。等到确实需要多步推理和复杂工具编排时才引入框架。这里给大家一个具体选择建议如果任务简单一次调用、一次工具结果拼接直接用原生 API 或者轻量 SDK如果要构建多步骤、有循环、需要记忆的任务选 LangGraph 最稳妥。Claude Agent SDK 也适合尤其当你的工具定义相对固定时它的 agent loop 和工具调用处理得很简洁。2.2 核心权衡工具调用与记忆管理Agent 框架的所谓“智能”其实集中在两块工具调用和记忆管理。工具调用就是让模型按照 JSON Schema 输出参数然后代码去执行对应函数返回结果。记忆管理则决定了大模型能否在多次推理之间保持上下文。GitHub Actions 有个天然优势——每次运行环境是全新的这反而逼着你把记忆外置化。我把对话记录和中间结果写入仓库中的 JSON 文件下一次运行时用actions/checkout把上一次的结果拉下来再放进本次 prompt 上下文。这样 Agent 的“记忆”就持久化了。推荐用文件做记忆而不是向量数据库。因为 Actions 环境下每次构建都要重新安装依赖如果引入 chromadb 或者 qdrant光是依赖安装就可能耗掉几分钟。对定时任务来说纯文件 结构化 JSON 足够支撑大多数场景而且 Git 本身就是一个版本化存储随时可以回溯 Agent 之前的状态。2.3 一个可复用的极简 Agent 骨架这里给出一段核心代码思路它足够支撑日常的信息收集类 Agentimport json from openai import OpenAI client OpenAI(api_keyos.environ[OPENAI_API_KEY]) tools [ { type: function, function: { name: fetch_webpage, description: 抓取网页并提取正文文本, parameters: { type: object, properties: {url: {type: string}}, required: [url], }, }, } ] messages [ {role: system, content: 你是一个信息收集助手只做有依据的判断。使用工具获取数据后再总结。}, {role: user, content: 请查看 https://example.com 上的内容总结最新动态}, ] for _ in range(5): resp client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, tool_choiceauto ) msg resp.choices[0].message if not msg.tool_calls: break messages.append(msg) for call in msg.tool_calls: result fetch_webpage(json.loads(call.function.arguments)[url]) messages.append({ role: tool, tool_call_id: call.id, content: result, }) final_answer messages[-1].content这段代码体现了 Agent 的核心循环模型输出工具调用请求程序执行真实函数结果回填到上下文模型再继续推理。在 Actions 里跑的时候只需要把fetch_webpage替换成任意代码能力读 API、查询数据库、操作文件Agent 就能处理不同类型的信息。3. 从零搭建一个跑在 Actions 上的 Agent实操记录3.1 仓库结构与 secrets 准备搭建的第一步是在 GitHub 建一个专用仓库目录结构尽量简单repo/ ├── .github/workflows/agent.yml ├── src/agent.py ├── src/tools.py ├── storage/ │ └── state.json └── output/storage目录保存 Agent 的持久化状态output目录保存每次运行结果。这两个目录建议直接提交进 git虽然会产生一点仓库体积但换来的是免费的对象存储和版本历史非常划算。然后是 secrets 设置。在仓库 Settings - Secrets and variables - Actions 中添加以下内容OPENAI_API_KEY或ANTHROPIC_API_KEY大模型服务的密钥。MY_API_TOKEN如果 Agent 要访问第三方 API单独放一个 token 方便审计。注意不要在代码里写死任何密钥GitHub 会自动对 Secrets 打码但历史提交里的明文密钥不会自动清除真泄露了必须立即吊销并清理提交历史。3.2 workflow 的写法与常见陷阱以下是完整的 workflow 配置文件已经过实际验证name: daily-agent on: schedule: - cron: 0 3 * * * workflow_dispatch: permissions: contents: write concurrency: group: daily-agent cancel-in-progress: false jobs: run-agent: runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Checkout repo uses: actions/checkoutv4 - name: Setup Python uses: actions/setup-pythonv5 with: python-version: 3.12 cache: pip - name: Install dependencies run: | pip install --upgrade pip pip install -r requirements.txt - name: Run agent env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} MY_API_TOKEN: ${{ secrets.MY_API_TOKEN }} run: | python src/agent.py - name: Push output run: | git config user.name agent-bot git config user.email agent-botusers.noreply.github.com git add storage/ output/ git diff --cached --quiet || git commit -m Update agent output $(date -u) git push几个容易踩的坑schedule事件用的是 UTC 时间。很多人在中国时区设置cron: 0 3 * * *以为凌晨三点跑实际是北京时间上午十一点跑。要按北京时间配置的话记得换算成 UTC。比如北京时间早上八点对应 UTC 就是“0 0 * * *”。实际执行会有监控机制虽然大多数时候能够准点触发极端情况下也可能延迟几分钟。job 的并发控制。cron 和手动触发可能在同一天内重叠如果没有concurrency字段两个任务会并行跑同时写同一个 storage 文件导致冲突。加上concurrency就是为了避免这种情况。默认分支和保护规则。如果仓库默认分支是main且有推送保护bot 直接 push 会被拦截要么去掉保护要么给操作加上BYPass条件。个人仓库一般没这个问题团队仓库需要注意。timeout-minutes一定要设。LLM 调用一旦出现网络超时重试工作流可能拖很久免费额度会被白白消耗。个人经验是常规任务给 20 分钟足够。Actions 支持cache: pip它会缓存 pip 依赖。在 Ubuntu 环境下开缓存后第二次运行安装依赖的时间从三分钟降到二十秒效果明显。3.3 把状态持久化到 Git 仓库Agent 在云端跑完经常会带着新的信息状态比如上次扫描到了哪个时间点、上一次输出摘要的哈希、某个资源是否已经被处理过。这些状态如果存在本地第二次运行就又丢了存在第三方对象存储还要配密钥最省事的就是写回仓库。具体做法是每次运行开始时先 checkout 仓库读取storage/state.json运行过程中更新内存中的 state 对象运行结束写入文件后再 git push。这样状态、结果、运行日志全部以 git commit 的方式沉淀下来。import json import os STATE_FILE storage/state.json def load_state(): if not os.path.exists(STATE_FILE): return {} with open(STATE_FILE, r) as f: return json.load(f) def save_state(state): with open(STATE_FILE, w) as f: json.dump(state, f, ensure_asciiFalse, indent2)3.4 调试技巧与手动触发在把 Agent 交给 cron 前一定先手动触发。方法是进入仓库的 Actions 页面选中 workflow点击 Run workflow 按钮。这样能观察到真实的运行环境、环境变量和网络状况。我在调试阶段几乎每一步都通过 workflow_dispatch 触发因为在本地写好的代码放到 Ubuntu 容器里经常有细微差异。日志查看也很重要。Actions 页面会输出步骤级日志Python 的 print 输出直接可见。建议在 agent.py 里加上日志模块打印每次模型调用消耗的 token 数和工具执行耗时。这样你能看清楚一次任务到底把时间花在了哪里是网络请求慢还是依赖安装慢还是模型输出太长导致超时。4. 常见问题与排查技巧实录4.1 任务明明触发了却什么都没有输出这是最常见的状况。排查方法从 Actions 页面查看对应 job 的日志先看Run agent这一步的完整输出确认 Python 是否报错、API 是否返回 401、网络是否被限制。我遇到过一次报错原因是requirements.txt里有个包在新版 Ubuntu 上编译失败属于系统依赖缺失。那种情况需要在 workflow 中先执行sudo apt-get update sudo apt-get install -y ...。还有一个极易忽略的问题GitHub 对 workflow 第一次运行有白名单机制如果仓库是私有仓库并且用户信息没配置git push 阶段会报Please make sure you have the correct access rights。这个不是开发者的代码问题而是 bot 使用的 token 权限不对。解决办法是要么开permissions: contents: write要么用GITHUB_TOKEN的默认权限把写权限打开。如果是用个人访问令牌PAT方式要给 repo 权限且把仓库 owner 加进去。4.2 模型调用频繁失败或超时在 Actions 环境里访问 OpenAI 或 Claude 等外部模型服务网络一般没问题但确实会碰到限流和时区相关触发。尤其多个 workflow 同时运行时容易出现 429。我的处理方式是给所有外部调用加退避重试import time, random def call_with_retry(func, max_retries4): for attempt in range(max_retries): try: return func() except Exception as e: if attempt max_retries - 1: raise wait (2 ** attempt) random.uniform(0, 1) time.sleep(wait)除此之外几个细节要注意用gpt-4o-mini或claude-sonnet这类便宜模型跑掉很多初始分类任务只在需要真正推理时用贵模型。在 prompt 里限制输出长度防止模型生成超大响应占满上下文。监控每个模型调用耗时如果某步持续超过 30 秒优先怀疑网络和限流。4.3 并行与串行的取舍大多数 Agent 技能循环是顺序执行读数据、调用模型、执行工具、再调用模型。这个顺序在 Actions 上可以做但不是最高效的。如果你的 Agent 要处理多个独立数据源建议用 Python 的concurrent.futures做并行请求能显著缩短运行时间。我用过的一个模式把待处理的 URL 列表拆成 4 个并发桶每个桶由一个 worker 依次调用模型。之后的合并阶段再让主进程汇总。这样做的好处是总耗时大约从 9 分钟降到 5 分钟以内坏处是并发大时容易触发限流所以并发数不宜过高我一般控制在 4~6 个。4.4 失败重试的工程写法Agent 程序不像传统脚本它可能因为模型输出 JSON 不合法、工具返回空值、第三方 API 临时挂掉而失败。如果只靠 Actions 原生失败重试那会浪费大量时间。我给 workflow 设计的失败重试策略有三层第一层代码内 try/except 捕获外部调用异常进入重试队列。第二层模型输出 JSON 解析失败时让模型重新生成一次并在系统提示里说清楚上一轮解析的报错信息。第三层workflow 失败后Actions 支持retry策略但我一般不开因为如果每轮都领取新任务可以但如果是幂等性不强的任务可能重复产生脏数据。真正靠谱的兜底是把“已经处理过的 key”记录到 storage 的 state.json 中。下一次 Agent 启动时读一下已经在处理列表中并且成功结束的直接跳过。这就实现了“断点续跑”的效果。5. 进阶用法让这个框架变成个人的自动化基础设施5.1 用 Actions 做定时数据采集与 AI 摘要我实际跑得最久的一个 Agent 是“每天定时采集开源项目动态”。它每 12 小时拉取特定 GitHub 仓库的 Issues 和 Releases利用大模型判断哪些内容变化值得纳入简报再把筛选结果汇总成 Markdown提交到仓库并推送到 Telegram。这里有一个很关键的经验一定要给任务限数量否则 Agent 会抓取太多数据导致 token 消耗爆炸。我用 state.json 记录每个项目的“上次活跃时间”每次只抓取后这条时间的更新内容这样日积月累下来token 消耗只跟增量数据有关不会无限膨胀。5.2 把 Agent 结果推送到自己的消息终端GitHub Actions 跑出来的结果不在本地如果开发者没有打开 GitHub 页面习惯很容易错过。这里可以把 Agent 的 output 写入 repo 后通过 Telegram Bot 或 Discord webhook 主动推送到手机上。5.3 多 Agent 的分工与调度GitHub Actions 允许在同一个仓库里放多个 workflow 文件一个文件就是一个独立 Agent。比如 12:00 跑新闻摘要 Agent16:00 跑代码依赖检查 Agent每天 9:00 跑日报汇总 Agent。这些 Agent 之间千万不要通过写同一个文件来共享数据容易出现竞态。更好的做法是让每个 Agent 有自己的存储目录然后在最终汇总时用另一个“编排 Agent”去读取所有目录。这种“小 Agent 独立执行 总 Agent 汇总”的模式比单纯一个大 Agent 做所有事情稳定得多也更省 token。我现在的架构就是这样一个分布式多 Agent 结构每个 agent 的职责边界非常清晰。6. 最后再分享几个经验我个人在实际操作中的体会是这个模式最打动我的不是免费额度而是“把模型能力变成可追溯、可回滚、可分享的自动化流程”。Actions 上跑 Agent每一次执行都会留下永久日志和 Git 提交出错时可以回滚到任意历史状态这种透明性是我之前用 VPS 和 crontab 完全做不到的。一个小技巧收尾给 Agent 的输出文件写入时间戳和 commit hash比如report-YYYYMMDD.md。如果 Git 仓库公开的话你会得到一份能被索引、能被链接、能被人引用的时序化数据集这比“在服务器上的某个隐藏目录里存文件”有价值得多。按照这个思路你可以把个人的监控、摘要、数据采集需求都逐步迁移到 Actions 上来形成一套完全托管、近乎免费、可随时徒手 cp 重来的公共基础设施。