五年前,David Crawshaw 曾问软件工程师:你写过什么只给自己使用的程序?得到的答案几乎都是“没有”。工程师每天使用别人提供的编辑器、构建系统和云服务,为别人开发软件,却很少为自己的具体工作流改造工具。
AI coding agent 正在改变这个局面。Crawshaw 作为开源 AI coding agent Shelley 的作者,提出了一个值得开发者工具团队认真对待的判断:当 agent 能阅读、理解并修改整个代码库时,源码本身就可能成为最强的扩展系统。由此推导出的结论是,开发者工具是否开源,不再只是采购、授权或社区建设问题,而会直接影响工具能否被 agent 深度改造。
传统扩展系统的边界由作者决定
插件 API、事件钩子和配置文件仍然有价值。它们提供稳定边界,限制扩展代码的权限,也让升级更可控。但传统扩展机制有一个天然限制:用户只能修改工具作者预先开放的部分。
假设一款代码审查工具只提供“提交评论”的 API,用户就很难改变它的 diff 分组方式、缓存策略或本地索引结构。即使需求只服务于一个团队,开发者也要等待上游增加扩展点,或者在工具之外再包一层脚本。
AI agent 面对开源项目时,路径不一样。它可以沿着调用链定位实现,修改内部数据结构,补充命令行参数,再运行测试验证结果。扩展不再局限于作者提前设计好的插槽,而是可以发生在源码中的任何合适位置。
这并不意味着插件系统会消失。更现实的分工是:
- 配置用于表达常见、低风险差异。
- 插件用于承载稳定且可复用的第三方能力。
- 源码修改用于解决尚未形成通用接口的团队特定需求。
- AI agent 降低理解代码、制作补丁和补测试的成本。
源码因此从“实现细节”变成了一种更通用但风险也更高的扩展接口。
开源带来的不是可见性,而是可修改性
如果工具只能公开阅读源码,却禁止修改、分发或部署,agent 的能力仍然受到法律和工程流程限制。因此,讨论“源码即扩展系统”时,需要区分真正的开源许可证与仅供查看的 source-available 模式。
对开发者而言,关键问题不是能不能让模型读到代码,而是能否完成一条合法、可维护的改造链路:
- 将仓库拉到本地并建立可复现环境。
- 让 agent 定位需求涉及的模块和测试。
- 生成范围有限、可以审查的补丁。
- 在 CI 中执行测试、静态检查和安全扫描。
- 将通用改动提交上游,或维护边界清晰的内部补丁。
闭源工具通常只能向 agent 暴露文档、API 和运行时行为。开源工具则能暴露实现、测试、提交历史和架构约束。后面这些信息会显著提升 agent 修改复杂系统时的成功率,也让人类审查者有机会判断它为什么这样改。
不过,开源并不会自动产生良好的可扩展性。缺少测试、构建不可复现、模块高度耦合的仓库,即使源码完全开放,也很难让 agent 稳定修改。对工具作者来说,测试套件、贡献指南和清晰的模块边界,正在成为面向 agent 的产品接口。
可以这样实践:让 agent 改造一个最小命令行工具
下面是一个概念性最小项目,用来展示“直接修改源码”的工作流,不代表 Shelley 的真实 API 或使用方式。示例只依赖 Python 3,可以直接运行。
先创建 notes.py:
#!/usr/bin/env python3
import argparse
from pathlib import Path
def read_notes(path: Path) -> list[str]:
if not path.exists():
return []
return [line.strip() for line in path.read_text().splitlines() if line.strip()]
def main() -> None:
parser = argparse.ArgumentParser(prog="notes")
parser.add_argument("file", type=Path)
subparsers = parser.add_subparsers(dest="command", required=True)
add_parser = subparsers.add_parser("add")
add_parser.add_argument("text")
subparsers.add_parser("list")
args = parser.parse_args()
if args.command == "add":
with args.file.open("a") as handle:
handle.write(args.text + "\n")
elif args.command == "list":
for index, note in enumerate(read_notes(args.file), start=1):
print(f"{index}. {note}")
if __name__ == "__main__":
main()
运行并建立基线:
mkdir agent-ext-demo
cd agent-ext-demo
# 将上面的代码保存为 notes.py
chmod +x notes.py
git init
git add notes.py
git commit -m "Add minimal notes CLI"
./notes.py data.txt add "review parser changes"
./notes.py data.txt add "run integration tests"
./notes.py data.txt list
现在可以把下面的任务交给能够在本地仓库中读写文件并执行测试的 coding agent:
你正在修改一个 Python 命令行工具。
目标:增加 `search QUERY` 子命令,按大小写不敏感方式搜索笔记。
约束:
- 不引入第三方依赖;
- 保持现有 add 和 list 行为不变;
- 搜索结果继续显示原始序号;
- 无匹配时退出码为 1;
- 使用 unittest 增加覆盖正常匹配、大小写和无匹配场景的测试。
请先阅读整个仓库并说明计划,再修改文件。完成后运行测试,展示命令、测试结果和 git diff。不要提交代码。
这个提示词把 agent 当成受约束的代码贡献者,而不是可以任意重写项目的自动化工具。验收时至少执行:
python -m unittest discover -v
git diff --check
git diff
./notes.py data.txt search TESTS
printf 'exit code: %s\n' "$?"
真实项目还应在隔离容器或权限受限的工作区中运行 agent,限制网络访问和密钥读取,并要求每个改动通过已有 CI。agent 能修改源码,不等于它应该拥有生产环境权限。
工具作者需要重新设计“可改造性”
如果越来越多用户通过 agent 定制工具,项目维护者需要优化的不只是 SDK。仓库本身会成为用户界面的一部分。
值得优先补齐的内容包括:
- 一条命令即可运行的开发环境和测试套件。
- 能说明模块职责、数据流和兼容边界的文档。
- 小而明确的模块,避免一个需求触发全仓库修改。
- 针对配置格式、数据库结构和命令行输出的兼容性测试。
- 清晰的许可证、贡献流程和安全报告渠道。
- 机器可读的格式化、静态检查和测试命令。
还要正视维护成本。团队内部 fork 可以迅速解决问题,但长期偏离上游后,升级和安全修复会越来越困难。比较稳妥的策略是让 agent 生成小补丁,把通用能力贡献上游,把真正私有的差异放在独立模块中,并持续自动重放这些补丁。
开源会成为开发者工具的能力边界
“开发者工具必须开源”不是说所有商业模式都要消失,也不是说源码开放可以替代稳定 API。它指出的是一个新的竞争维度:当 AI agent 能把需求直接转换为代码修改时,可合法修改、可测试、可重新部署的工具,会比只能调用固定接口的工具拥有更大的适应空间。
采用这条路线前,可以检查四件事:许可证是否允许目标用途,测试能否覆盖 agent 的改动,补丁能否持续跟随上游,以及执行环境是否隔离了密钥和生产资源。源码可以成为最灵活的扩展系统,但只有配合工程约束和人工审查,它才会成为可靠的扩展系统。