1.1 环境与仓库骨架
从本节开始,我们要从零手写一个 Agent 运行时库 minagent。它不是把某个框架的 API 抄一遍,而是让你亲手把「消息怎么表示、模型怎么调用、循环怎么转、工具怎么执行」这些环节逐一实现出来。第 1 章的目标很克制:搭好环境、定下核心类型、跑通第一轮假模型。但正因克制,后面 17 章才能在同一套类型上稳步叠加。
本节把 minagent 推进到「仓库立起来」:建好 Python 与 Node 双栈环境,生成
minagent/包骨架与tests/目录,完成git init与首个提交。到本节结束,你手上有一个能装包、能跑脚本、能被版本管理的空壳项目。
1.1.1 为什么是双栈
这套书稿的主线是 Python 3.14,对照线是 TypeScript(Node 26)。为什么不一门语言走到黑?
| 维度 | Python 主线 | TypeScript 对照线 |
|---|---|---|
| 角色 | minagent 引擎全部实现 | 协议客户端与类型对照 |
| 理由 | 标准库即可写完整 Agent,零第三方依赖 | 前端/Node 生态里调用 Agent 服务的真实场景 |
| 出现章节 | 第 1–16 章几乎全部 | 第 17 章「TS 落点」集中出现 |
关键取舍是:卷一的核心引擎只用 Python 标准库。dataclasses / typing / json / asyncio / sqlite3 / math / re / hashlib 这八个模块,足以支撑到第 16 章的评测。第三方库(pydantic / FastAPI / httpx / anthropic)只在明确标注「可选」「工程化」的地方出现。这样做的直接好处是:你 clone 下来就能跑,不会被依赖地狱卡住。
Node 侧则负责「另一门语言怎么消费同一套协议」。TypeScript 的静态类型能在编译期把消息结构的形状固定下来,与 Python 的 dataclass 形成有趣的对照。到第 17 章我们会用一个真实可运行的 TS 客户端收尾。
1.1.2 建立 Python 虚拟环境
先把 Python 虚拟环境建起来。本机实测版本是 Python 3.14.6:
python3 -m venv /tmp/agentbook/venv
这一步会在 /tmp/agentbook/venv/ 下生成 bin/、lib/、pyvenv.cfg。激活它:
source /tmp/agentbook/venv/bin/activate
激活后 python 就指向这个环境。本书后续所有 Python 命令都写作 /tmp/agentbook/venv/bin/python,这样即使忘了激活也不会误用到系统解释器。
验证解释器版本——这是你每次开新终端都该跑的一行:
/tmp/agentbook/venv/bin/python -c "import sys; print(sys.version)"
本机实测输出:
3.14.6 (main, Jun 10 2026, 10:03:53) [Clang 21.0.0 (clang-2100.0.123.102)]
三部分分别是版本号、构建时间、编译器。看到 3.14.6 就说明环境对了。注意 Python 3.14 起 sys.version 的编译器信息更完整,这在排查「为什么 A 机器能跑 B 机器不能」时很有用。
1.1.3 pip 源:必须用中科大
本机实测下来,PyPI 官方源与清华源在 pip 下都不稳定,而阿里云源不完整(装 pydantic 时 wheel 元数据 404)。可靠的选择是中科大源:
python -m pip install --index-url https://mirrors.ustc.edu.cn/pypi/simple <包名>
把它写成默认配置,省得每次敲:
python -m pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/simple
确认 pip 本身可用:
/tmp/agentbook/venv/bin/python -m pip --version
pip 26.1.2 from /private/tmp/agentbook/venv/lib/python3.14/site-packages/pip (python 3.14)
卷一的大部分章节你根本不需要装包——标准库已经够用。只有第 17 章打包成 API 服务时才会真正引入 fastapi / uvicorn,到那时再按上面的口径安装。
1.1.4 Node 26 对照线
TypeScript 侧本机实测 Node 26.5.0:
node --version
v26.5.0
Node 26 有一个必须提前记住的约束:它只支持「类型擦除」(type stripping),不支持 --experimental-transform-types(会直接报 bad option)。这意味着所有 TS 示例必须只用「可擦除语法」:
- 不用构造函数的参数属性(
constructor(private x: number)) - 不用
enum - 不用
namespace
构造函数里的参数,在函数体内赋值即可。这样 node file.ts 就能零构建直接执行,不需要 ts-node、不需要打包器。类型检查另走 npx tsc --noEmit,并在 tsconfig.json 里打开 "erasableSyntaxOnly": true 让编译器帮你把关。
1.1.5 仓库骨架
现在建目录。minagent 采用「包与仓库同名」的布局,minagent/ 仓库根下再放一个 minagent/ 包:
mkdir -p minagent/minagent minagent/tests
cd minagent
touch minagent/__init__.py
第 1 章结束时,目录会长成这样:
minagent/
├── README.md
├── .gitignore
├── minagent/
│ ├── __init__.py
│ ├── types.py # Role / ToolCall / Message / ModelResponse(1.2)
│ └── fake.py # FakeModel(1.3)
└── tests/
├── test_roundtrip.py # 消息序列化往返(1.2)
└── test_fakemodel.py # 假模型确定性(1.3)
几个约定值得先讲清:
- 仓库根与包同名是常见做法(如
requests),但要注意cd进仓库后import minagent导入的是子目录里的包,不是仓库根。为避免混淆,测试统一从仓库根目录用python -m pytest运行。 __init__.py先留空。等第 17 章定下公开接口时再往里写__all__与 re-export,过早暴露内部符号会让重构变难。tests/与minagent/平级,不放进包内。测试是仓库的一部分,不是可发布的包内容。
README.md 先写三行即可,后面每章补一句进展:
# minagent
从零手写的 Agent 运行时库,配套《AI Agent 开发入门》卷一。
## 环境
- Python 3.14.6(/tmp/agentbook/venv)
- Node 26.5.0(TypeScript 对照线)
README 的作用不是装饰,而是给未来的自己一个「这个仓库现在能干什么」的锚点。每完成一章就更新一次,比事后补写容易得多。
.gitignore 至少覆盖这些:
# 虚拟环境
venv/
.venv/
# Python 产物
__pycache__/
*.py[cod]
.pytest_cache/
*.egg-info/
# 编辑器
.idea/
.vscode/
注意不要忽略 /tmp/agentbook/venv——它根本不在仓库里,写进 .gitignore 只是提醒你别把 venv 拷进项目。
1.1.6 git init 与首个提交
把骨架纳入版本管理:
git init
git add README.md .gitignore minagent/
git commit -m "chore: 初始化 minagent 仓库骨架"
首个提交只放「结构」,不放逻辑——types.py 与 fake.py 要等 1.2、1.3 写完再各自提交。这样 git log 读起来就是一条清晰的成长线,每一章对应一次可运行的推进。如果你更习惯一次性提交,也没问题;关键是每章结束时代码是可运行的。
一个实用习惯:提交前跑一遍 import 冒烟测试,确认包结构没写歪:
/tmp/agentbook/venv/bin/python -c "import minagent; print(minagent.__file__)"
它能打印出 minagent/__init__.py 的绝对路径,说明包可被导入、__init__.py 存在。到 1.2 我们会把这个空包填上第一个真类型。
1.1.7 常见环境问题排查
搭环境时最常见的四类故障,以及判断方法:
| 现象 | 常见原因 | 处理 |
|---|---|---|
import minagent 报 ModuleNotFoundError | 当前目录不是仓库根,或包目录少了一层 | cd minagent 后确认 minagent/minagent/__init__.py 存在 |
pip install 卡住或 404 | 用了官方源/清华源/阿里云源 | 换中科大源,见 1.1.3 |
node file.ts 报 bad option: --experimental-transform-types | Node 26 不支持该标志 | 去掉标志,改用可擦除语法 |
python 指向系统解释器 | 忘了激活 venv,或 shell 缓存了旧路径 | 一律用 /tmp/agentbook/venv/bin/python 绝对路径 |
排查环境问题的通用套路是先确认「我到底在用哪个解释器」。Python 用 sys.executable、Node 用 process.execPath,都能打印出可执行文件的绝对路径。90% 的「明明装了却 import 不到」都是因为命令跑在了另一个解释器下。这个习惯在多人协作、CI、容器里尤其重要——环境差异往往就藏在这一行路径里。
1.1.8 环境自检清单
开新机器或换终端时,按这张表逐条确认:
-
/tmp/agentbook/venv/bin/python -c "import sys; print(sys.version)"输出3.14.6 -
node --version输出v26.5.0 -
pip config get global.index-url指向中科大源 -
minagent/minagent/__init__.py存在 -
python -c "import minagent"无报错 -
git status干净,首个提交已完成
这六条全绿,环境就算立住了。后面每章开头如果涉及新依赖,都会明确写出安装命令与实测版本。
1.1.9 真实模型下会怎样
本节还没碰模型,但值得提前交代:假模型是全书默认路径,真实 API 只在每卷末尾、且经你明确同意后才调用一次。真实调用需要的额外准备包括:ANTHROPIC_API_KEY 环境变量(正文里永远只写 os.environ["ANTHROPIC_API_KEY"],绝不写死密钥)、网络可达 api.anthropic.com(本机实测可达,而 api.openai.com 不可达)、以及一个能容忍延迟与费用的运行预算。这些准备工作与本节的环境搭建是正交的——你把 Python 环境建好,无论后面接假模型还是真模型,代码结构完全一样。这正是第 2 章要立下的 Model 协议的意义:让假模型与真实供应商适配器可互换。
小结
主线 Python 3.14.6、对照线 Node 26.5.0;卷一核心引擎只用标准库。
虚拟环境建在
/tmp/agentbook/venv,所有命令用绝对路径的bin/python调用最稳。pip 必须用中科大源:
--index-url https://mirrors.ustc.edu.cn/pypi/simple。Node 26 只支持类型擦除,TS 示例禁用参数属性 /
enum/namespace。仓库骨架:
minagent/minagent/(包)+minagent/tests/(测试)+README.md+.gitignore。git init后首个提交只放结构;每章结束时保证代码可运行。环境问题先查「我在用哪个解释器」,
sys.executable与process.execPath是最快的判据。
环境就绪。下一节 1.2 Agent 的最小定义与消息协议
会往这个空包里写下第一个真正的类型 Message,并给出它在「模型 ↔ 运行时」之间往返不丢信息的序列化方案。若想回顾本卷整体安排,回看 目录
。
阅读导航:上一节:目录 · 下一节:1.2 Agent 的最小定义与消息协议 。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。