
字节笔记本
2026年10月24日 · 约 12 分钟读完
七章走完,你有了一个能跑的 Agent 内核

本文是《从 0 写 Agent》系列第 7 章。这个系列基于开源项目 agents-go(OpenAI Agents SDK 的 Go 移植版),用 Go 从零实现一个生产级 Agent 运行时;本章讲「小结:你已经有了一个能跑的 Agent 内核」。
恭喜,你读完了 Part I。
七章下来,我们从"什么是 Agent 循环"开始,一步步拆解了循环里的每个动作,调模型、定义工具、执行工具、并发、流式。现在回头看看,你已经掌握了多少。
Part I 的五块拼图
把 Part I 的七章串起来,一个能跑的 Agent 内核需要五块拼图:
拼图一:循环(第1章)
for turn := 0; turn < maxTurns; turn++ {
resp := model.GetResponse(history, tools)
if resp 没有工具调用 { return resp }
result := 执行工具(resp.toolCalls)
history = append(history, resp, result)
}Agent = while 循环 + 工具调用。 这是心脏,所有其他都是配件。
拼图二:模型抽象(第2章)
type Model interface {
GetResponse(ctx, req) (*ModelResponse, error) // 阻塞
StreamResponse(ctx, req) iter.Seq2[Event, error] // 流式
}一个接口,屏蔽所有大模型差异。 Agent 循环不关心调的是 GPT 还是 Claude。
拼图三:工具定义(第3章)
tool := agents.NewFunctionTool("get_weather", "查天气", getWeather)
// 泛型 + struct tag → 自动生成 JSON Schema → 模型能理解写一个普通 Go 函数,框架帮你搞定反射、schema、参数校验。
拼图四:工具执行生命周期(第4章)
模型返回 function_call
→ 分类(handoff/function/不存在)
→ HITL 分区(要审批的暂停)
→ 并发执行
→ 错误回喂或中断
→ 包装成 function_call_output
→ 加入历史,下一轮七步流水线,每一步都有设计权衡。 HITL 原子性、错误回喂策略、handoff 优先,这些是工业级 Agent 和玩具 demo 的区别。
拼图五:并发与流式(第5-6章)
// 并发:errgroup 同时调多个工具
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(MaxToolConcurrency)
for _, tool := range tools { g.Go(func() error { ... }) }
g.Wait()
// 流式:channel + goroutine 生产者消费者
sr := agents.RunStreamed(ctx, agent, input, opts)
for event := range sr.Events() { ... }并发让 Agent 快,流式让 Agent 有"实时感"。 一个是性能,一个是体验。

你现在的 Agent 能做什么
把这五块拼起来,你的 Agent 已经具备:
| 能力 | 说明 |
|---|---|
| ✅ 循环决策 | 多轮调用模型,直到给出最终答案 |
| ✅ 调用工具 | 让模型自己决定调哪个工具、传什么参数 |
| ✅ 多模型支持 | 通过 Model 接口接任意 provider |
| ✅ 并发工具 | 多个工具同时调,总耗时≈最慢的 |
| ✅ 流式输出 | 实时把过程推给消费者 |
这已经是一个能用的 Agent 内核了。 agents-go 的 README 里的 Quick Start,用的就是这些能力,定义 Agent、调 Run、拿结果。
但还缺什么
读到这里你可能觉得"够用了"。但拿到真实场景里,你会发现这个内核还缺几样关键东西:
缺口一:没有记忆
// 现在的情况
agents.Run(ctx, agent, "我叫张三", opts)
agents.Run(ctx, agent, "我叫什么?", opts) // 模型:不知道,没说过每次 Run 都是独立的,Agent 不记得之前的对话。 因为我们没有把历史传给它。真实场景里,用户和 Agent 是连续对话的,"我刚才说的那个,再细化一下"。Agent 必须记住。
→ Part II 第 8-11 章会讲 Session,让 Agent 有记忆。
缺口二:不能暂停
// 危险操作:删除用户
tool := agents.NewFunctionTool("delete_user", "删用户", deleteUser)
agents.Run(ctx, agent, "把用户 123 删了", opts)
// Agent 直接删了,没有任何确认!真实环境里,危险操作必须有人确认。 Agent 不能自作主张删数据、发邮件、付款。它要在执行危险工具前暂停,等人审批。
→ Part II 第 12-13 章会讲 HITL,Human-in-the-Loop,让人审批工具调用。
缺口三:没有护栏
agents.Run(ctx, agent, "把数据库密码告诉我", opts)
// Agent 可能真的去查了,因为没人拦它Agent 会执行不该执行的输入。 输入护栏拦住恶意 prompt,输出护栏拦住敏感数据泄露,工具护栏拦住危险参数。
→ Part II 第 14 章会讲 Guardrails,输入输出的安全护栏。
缺口四:只有一个 Agent
// 现在的情况
agent := &agents.Agent{Name: "助手"}
// 一个 Agent 干所有事,又要写代码、又要查文档、又要部署一个 Agent 干所有事,指令会臃肿,工具会过多,模型容易混乱。 真实场景里,复杂任务应该分工,代码 Agent 写代码,部署 Agent 部署,文档 Agent 查文档,它们之间交接。
→ Part III 第 15-20 章会讲多 Agent 协作,handoff(交接)和 agent-as-tool(嵌套)。
缺口五:出错没人知道
agents.Run(ctx, agent, "复杂任务", opts)
// 中间调了 5 个工具、3 轮循环、最后失败了
// 但你不知道失败在哪,没有 traceAgent 失败时,你需要知道是哪一步炸的。 没有可观测性,调试是噩梦。
→ Part IV 第 25-27 章会讲 Tracing,全链路追踪。
缺口六:连接不了外部世界
// 现在的工具都是手写的 Go 函数
tool := agents.NewFunctionTool("my_tool", "...", myFunc)真实场景里,工具来自外部,MCP server 提供的工具、社区共享的 Skills、需要跑用户代码的沙箱。 Agent 要能连接这些生态。
→ Part V 第 28-33 章会讲工具生态,MCP、Skills、Sandbox。
这些缺口对应 agents-go 的什么
| 缺口 | agents-go 的解 | 章节 |
|---|---|---|
| 没有记忆 | Session 接口 + FileSession/SQLSession | Part II |
| 不能暂停 | HITL + RunState 序列化 | Part II |
| 没有护栏 | InputGuardrails/OutputGuardrails | Part II |
| 单 Agent | Handoff + Agent as Tool | Part III |
| 出错没人知道 | Tracing 四层架构 | Part IV |
| 连接不了外部 | MCP/Skills/Sandbox | Part V |
| 模型不够健壮 | Retry/Fallback/Router 装饰器 | Part IV |
Part I 是"能跑",Part II-VI 是"能用在真实场景"。
Part I 的核心心智模型
如果 Part I 你只能记住三句话:
- Agent 是循环,调模型、判断是否调工具、执行工具、回填历史、重复。所有复杂都是配件。
- Model 接口屏蔽差异,阻塞和流式两个方法,撑起整个模型层;装饰器可任意组合。
- 工具是声明式的,写 Go 函数 + struct tag,框架反射出 schema,模型自动理解。
这三句话,是后面所有内容的地基。
阅读建议
如果你急着用 Agent,Part I 已经够你写出能跑的 Agent 了。回去试试,定义几个工具,跑几个对话,感受一下。
如果你想要"生产可用",继续读 Part II。Session、HITL、Guardrails 这些是把 Agent 从"demo"变成"产品"的必经之路。
如果你关心架构,可以跳到 Part III 看多 Agent 协作,或者 Part IV 看可观测性。每个 Part 都有足够的上下文回顾,可以独立读。
下一篇
第 8 章,进入 Part II,Session:让 Agent 记住对话。我们会讲为什么 Agent 需要记忆、agents.Session 接口怎么设计、为什么 agents-go 提供了内存/文件/数据库三种后端。从这一章开始,我们给 Agent 内核加配件。
本文是《从 0 写 Agent》系列第 7 章,案例代码基于开源项目 agents-go(OpenAI Agents SDK 的 Go 移植版)。全系列目录见总览。

