slug
Function Calling 与 Agent Runtime 学习笔记
type
Post
status
Published
date
May 17, 2026
tags
推荐
文字
summary
category
面试高频题库
icon
password
本笔记基于费曼学习法对话整理,从 JSON Schema 出发,逐层拆解到 Agent Loop 的工程本质。
一、整体认知链路
二、核心概念:LLM 只是 Token Generator
关键认知(必须刻进 DNA)
LLM 本质上只是一个 token generator,它能做的只有"吐字"。它没有网络访问、没有文件系统、没有执行环境。
所谓"Function Calling"这个名字其实有点误导,叫 "Function Call Suggestion" 更准确 —— 模型只是在建议调用什么,决定权和执行权完全在 Runtime。
由此推出的工程结论
- 模型可以 hallucinate 不存在的工具名 —— Runtime 必须做合法性校验。
- 模型不知道执行成功还是失败 —— 它对世界的认知完全来自下一轮塞给它的
tool_result。
- 模型不知道时间过去了多久 —— tool 跑了 30 秒还是 30 毫秒,对它没区别。
- "Function Calling 能力"训练的本质 —— fine-tune 模型让它在合适时机输出符合 schema 的 JSON。
Anthropic 官方用 "tool use" 这个词,比 "function calling" 中性,没暗示"模型在调用"。OpenAI 起的 "function calling" 这个名字带偏了一代开发者的心智模型。
三、JSON Schema 的角色
给谁看 + 干什么
视角 | 目的 |
模型看 schema | 知道"我有哪些工具可用、参数长什么样"——为了产出 |
Runtime 看 schema | 校验模型输出的 tool_call 合不合法——为了验收 |
在哪个阶段起作用
Schema 能解决什么,不能解决什么
维度 | Schema 解决了吗 |
模型知道有什么工具 | ✓ 完全解决 |
输出格式合法(类型、字段、JSON 语法) | ✓ 大幅缓解 |
Runtime 能验收 | ✓ 完全解决 |
语义正确(如 city="2026-05-17") | ✗ 没解决 |
Schema 只管类型 / 结构 / 必填字段这种"语法层"的事,管不了"语义对不对"。语义对错本质上靠模型自己的理解能力 + description 写得好不好。
四、Self-Correction 机制
反馈闭环
关键认知
模型本身没有任何"自我纠错"的内在动力,所谓 self-correction 完全是 runtime 编排出来的幻觉。
- 模型生成错误的那一刻,它不觉得自己错了(只是 next token prediction)
- Runtime 不"主动通知"模型 —— 而是被动地准备好材料,等下一次模型推理时被读到
- LLM 是 pull-based / stateless 的,每次 inference 都是冷启动
Self-correction 可行性判据(核心公式)
可纠正 = ∃ 某一层 L,使得 L 能识别错误 ∧ L 能产生错误反馈 ∧ 反馈能进 contextsilent failure = 上述条件都不成立
错误分类示例
场景 | 类型 | 原因 |
city="西安市"(API 要 "西安") | ✓ 可纠正 | API 报错"city not found" |
city="2026-05-17"(类型对,语义错) | ✓ 大概率可纠正 | API 查不到此城市会报错(依赖 API 严格程度) |
city="西宁"(用户原话"西安") | ✗ Silent Failure | Schema 合法、API 正常返回西宁机票,链路无报错 |
date="2026-05-17"(用户想要 18 号) | ✗ Silent Failure | 日期合法、有票,链路无报错 |
对抗 Silent Failure 的手段
手段 | 做法 | 逻辑 |
Human-in-the-loop (HITL) | 关键操作前让人 confirm | 把"语义判断"交给人 |
Confirmation step | Agent 自己说"我要订西宁的票,对吗?" | 把语义错误显性化 |
Reflection / Self-critique | 调用结束后再让模型反思一遍 | 用一次额外的 LLM call 当"审稿人" |
Constrained decoding | 限制模型输出必须从枚举值里选 | 从自由文本变成 dropdown |
Cross-validation | 多次调用对比结果 / 多模型投票 | 用冗余对抗单点错误 |
工程结论:如果想让 Agent 对某类错误"自动纠错",工作不是教模型"更聪明",而是想办法在链路里植入一层能产生错误信号的 "L"。
五、Training vs Inference
核心对比
阶段 | 模型参数(weights)的状态 | 在做什么 |
Training | 可变(mutable) | 通过 gradient descent 不断更新 weights |
Inference | 冻结(frozen / read-only) | weights 完全不动,只做一次 forward pass |
类比
Training = 学生在上学,做错题大脑神经连接会重塑(参数更新) Inference = 学生毕业进考场,大脑被锁死,无论答得对错神经连接一动不动
"冷启动"的真正含义
模型不存在"经历"的概念。所谓"记得",完全是 runtime 在这一次 inference 的 input 里重新喂给它的 context 制造的幻觉。
三个工程事实
- Memory 系统的本质:模型参数永远不变,所有"记忆"都是 runtime 在每次 inference 前临时拼装的 context。
- In-context memory:完整塞入对话历史
- Summarization memory:用 LLM call 压缩历史
- Retrieval-based memory(RAG):vector DB 检索 + 拼进 prompt
- Fine-tuning 属于 Training:fine-tuning 是"再训练",发生在部署之前,产出新 weights。一旦上线,weights 又冻结。
90% 的"让模型更好"的需求都不需要 fine-tuning,而是靠 prompt engineering + tool design + context engineering 解决。
- Temperature 控制采样随机性:
Temperature | 行为 |
T = 0 | 永远选概率最高的(greedy decoding) |
T = 0.7(默认) | 按概率采样,偏向高分 |
T = 1.5 | 分布被"压平",低分 token 也有机会 |
Agent 工程里,对精度敏感的任务通常 T=0(tool_call、结构化输出),创意任务才用高 T。
六、Runtime 是什么
关键认知(破除翻译陷阱)
"运行时"这个中文翻译害了一代人。Runtime 在工程语境里指的是「执行者」,不是「时间段」,也不是「动作集合」。
英文原意更准确的翻译应该是 "运行器" 或 "运行环境"。听到"运行时" → 想成"那个跑代码的程序"。
精确定义
Agent Runtime = 你(开发者)自己写的、负责编排整个 Agent 工作流的那段程序。
三个关键词:
- "你自己写的" —— Runtime 不是 LLM 自带的,是你作为工程师亲手写的代码
- "编排" —— 它的核心动作是"指挥",告诉每一步该干什么
- "程序" —— 它是一段实实在在的代码,不是抽象概念
Runtime vs LLM 的分工
破除"Agent 很聪明"的幻觉
LLM 那一侧只会做一件事:text in → text out 其他所有"智能"行为,全是 Runtime 在后台编排出来的:
- "会调工具" → 是 Runtime 解析 tool_call 然后真去调的
- "会循环" → 是 Runtime 写了个 while 循环
- "会纠错" → 是 Runtime 把错误信号塞回 context
- "有记忆" → 是 Runtime 在每轮请求前重新拼装历史
七、Agent Loop 完整骨架
标准流程(订机票场景)
循环结构(ReAct 的工程实现)
这个循环结构就是 ReAct (Reasoning + Acting) 的工程实现。Hermes-agent、Cursor、Claude Code、LangGraph,全是这个骨架的工业级变种。
八、System Prompt vs Tool Schema(重要区分)
关键直觉的修正
直觉:"最后不都是文本喂给模型吗?" → ✓ 物理上对,工程上错。
关键差异不在"是不是文本",而在"谁负责把它变成文本"。
两种写法对比
写法 A:自己拼到 system prompt(不推荐)
写法 B:用 API 的
tools 参数(业界标准)为什么必须分两个通道?
【第一层】文本是模型厂商内部"翻译"出来的,不是你拼的
Anthropic/OpenAI 后端会按官方训练时见过的格式把 schema 拼进 prompt。这个格式经过 fine-tune,模型对它极度熟悉。
【第二层】响应通道完全不同
- 写法 A:模型返回一段 text,里面"藏着"JSON,你得自己挖
- 写法 B:模型在专门的
tool_use字段输出结构化对象,Runtime 直接用
【第三层】这是模型厂商的"售后保证"边界
用写法 B,厂商保证 tool_use 字段里的 JSON 是合法的(合 schema 的)。用写法 A,全凭模型当时心情。
对比表
维度 | System Prompt | Tool Schema |
API 参数 | messages 字段里 role="system" | 独立的 tools 字段 |
内容形式 | 自然语言指令 | JSON Schema 结构 |
目的 | 告诉模型"你是谁、怎么说话、有什么原则" | 告诉模型"你有哪些工具、参数怎么传" |
响应通道 | 模型在 text 字段回话 | 模型在 tool_use 字段输出结构化调用 |
结构保证 | 无 —— 模型说啥是啥 | 强 —— 厂商保证格式合 schema |
类比
想象你给秘书发指令:
- System Prompt = 说明信:"你是我的秘书,请专业、礼貌"
- Tool Schema = 操作手册:"打印机用法、订餐流程、报销表格在哪"
- User Message = 具体请求:"帮我订明天的午餐"
这三样都是纸,但秘书拿到时分门别类放在不同抽屉,处理方式完全不同。
九、关键认知速查(要背的几句)
- LLM 只是 token generator —— 它从来没有真的"调用"过任何函数。
- Function Calling 是整套机制的名字,不是其中某一步。它包括:声明阶段、输出阶段、执行阶段(Runtime 阶段)。
- LLM 是无状态的(stateless) —— 每次 inference 都是冷启动。所谓"记忆"全是 Runtime 制造的幻觉。
- Self-correction 依赖"错误信号能进 context" —— 不能产生信号的错误就是 silent failure。
- Runtime 是"执行者",不是"时间段" —— 它是你写的那段编排代码。
- Agent 的"智能"是 LLM + Runtime 的合奏 —— 单独把模型拎出来,它什么也做不了。
- Tool Schema 走独立的
tools字段 —— 不要自己拼到 system prompt 里。
十、待深入的话题(后续讨论)
Tool 设计:description 怎么写、参数粒度、错误信息怎么让模型自我纠正
Context Engineering:多轮交互怎么保留/压缩 history,prompt caching 怎么打
Planning:plan-and-execute vs ReAct
Memory:working memory vs long-term memory
Parallel tool calls:模型一次性吐多个 tool_call,runtime 并发执行
Multi-agent orchestration:子 Agent 作为 tool 暴露给主 Agent
hermes-agent 真实代码走读
- Author:盛溪
- URL:https://tangly1024.com/article/Function%20Calling%20%E4%B8%8E%20Agent%20Runtime%20%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!




.jpg?table=block&id=26f7c1d5-a1e9-80d7-a52b-e71bb7079501&t=26f7c1d5-a1e9-80d7-a52b-e71bb7079501)





