一、引言
LLM 接收上下文并预测下一个 Token,它擅长理解自然语言,却不会因为生成了下面这段内容,就真的调用天气服务:
{
"name": "get_weather",
"arguments": {
"city": "上海"
}
}
这只是模型输出的数据。真正发起网络请求、访问数据库或修改业务状态的主体,仍然是应用程序。
因此,一个完整的 Agent 至少包含两类组件:
┌──────────────────── 概率世界 ────────────────────┐
│ │
│ 用户输入 ──> Prompt/上下文 ──> LLM │
│ │ │
│ │ 生成调用意图 │
│ ▼ │
│ tool_call(name, arguments) │
└──────────────────────────┬────────────────────────┘
│ 协议边界
▼
┌──────────────────── 确定性世界 ──────────────────┐
│ │
│ Schema 校验 ──> 权限检查 ──> 工具执行 │
│ │ │ │
│ └──失败信息 └──执行结果 │
│ \ / │
│ └──> 写回模型上下文 ───────────────┘
│ │
└───────────────────────────────────────────────────┘
Function Calling 是一个多阶段过程:应用向模型提供工具定义,模型返回工具调用请求,应用执行工具,再把执行结果交还模型。Function Calling 是模型与程序之间的调用协议,不是模型获得了直接执行代码的权限。理解这一点,后续的安全控制、错误处理和状态管理才有正确的落点。
二、六项底层能力如何组成一个闭环
Agent 与程序世界的交互管道
┌─────────────── 输入侧 ───────────────┐
│ │
│ Prompt │
│ 规定目标、上下文、决策规则和边界 │
│ │ │
│ ▼ │
│ Tool Definition + JSON Schema │
│ 定义有哪些工具,以及参数契约 │
└──────────────────┬───────────────────┘
▼
Function/Tool Call
模型提出结构化调用
│
▼
┌────────────── 运行时边界 ─────────────┐
│ 解析 → Schema 校验 → 鉴权 → 执行 │
│ │ │
│ ┌──────────┴──────────┐ │
│ ▼ ▼ │
│ 成功结果 失败结果 │
└──────────┬─────────────────────┬──────┘
│ │
▼ ▼
结构化输出约束 分类重试/降级
│ │
└──────────┬──────────┘
▼
最终回答
各部分分别解决不同问题:
三、Prompt 设计:把它当作决策说明书,而不是咒语
Prompt 在 Agent 中主要负责两件事:说明任务目标、规定模型如何选择和使用工具。一个适合工具调用的 Prompt 可以拆成以下结构:
<role>
你是订单售后助手。
</role>
<objective>
帮助用户查询订单状态或提交退款申请。
</objective>
<tool_policy>
1. 查询实时订单状态时必须调用 order_get。
2. 未获得用户明确确认时,不得调用 refund_create。
3. 缺少 order_id 时先向用户询问,不得猜测。
4. 工具失败时,根据错误码解释原因,不得编造执行结果。
</tool_policy>
<output_policy>
调用写操作前先总结即将执行的动作。
最终回答需要区分“已执行”和“建议执行”。
</output_policy>
<untrusted_input>
{{user_input}}
</untrusted_input>
1.有效 Prompt 的四个组成部分
- 目标
目标要描述结果,而不是堆叠人格形容词。
较弱的写法:
你是一个专业、智能、严谨的订单助手。
更可执行的写法:
你负责查询订单状态,并在满足退款条件且用户明确确认后提交退款。
- 工具选择规则
当多个工具语义接近时,模型容易选错。Prompt 和工具描述应说明:什么时候调用、什么时候不调用、调用前需要哪些信息、工具是否产生副作用、多个工具有何边界。
- 缺失信息处理
如果模型缺少参数,它可能选择猜测。应明确要求:缺少必填参数时向用户询问,不得从无关上下文推断。
需要注意:这只能降低猜测概率,程序仍需执行 Schema 和业务校验。
- 失败行为
不要只写“如果失败,请重试”。应告诉模型根据错误类型做出什么决策:
VALIDATION_ERROR:修正参数后最多重试一次。
NOT_FOUND:向用户确认标识,不自动重试。
PERMISSION_DENIED:停止调用并说明所需权限。
RATE_LIMITED:遵循 retry_after,等待后重试。
2.Prompt 版本必须接受评测
Prompt 并不是一次写完的静态文案。生产环境至少要测试:
- 是否调用了正确工具;
- 是否遗漏必填参数;
- 是否在不需要时调用工具;
- 是否在写操作前取得确认;
- 工具失败后是否编造成功结果;
- 恶意工具返回是否改变系统指令;
- 模型或 Prompt 版本变化是否导致行为回归。
因此,Prompt 的可靠性应该由评测数据证明,而不是由“看起来写得很完整”来判断。
四、JSON Schema:Agent 与程序之间的数据合同
JSON 只是一种数据格式,JSON Schema 才负责描述数据结构和验证规则。
使用 JSON Schema 可以定义:
{
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单唯一标识,例如 ord_20261027_001"
},
"amount": {
"type": "number",
"exclusiveMinimum": 0,
"description": "退款金额,单位由 currency 指定"
},
"currency": {
"type": "string",
"enum": ["CNY", "USD"]
},
"reason": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": ["order_id", "amount", "currency", "reason"],
"additionalProperties": false
}
- properties 不代表必填,必须配合required进行使用校验。
- additionalProperties: false 用于封闭对象边界,如果不禁止额外字段,模型可能生成未定义参数。对于工具参数,封闭对象通常比开放对象更安全。
- enum 比自然语言约束更稳定,用于把实例值限制在给定集合中。
Schema 校验和业务校验必须分层:
模型参数
│
▼
[语法解析]
│ JSON 是否能解析?
▼
[Schema 校验]
│ 类型、必填项、枚举、结构是否合法?
▼
[业务校验]
│ 订单存在吗?金额可退吗?状态允许吗?
▼
[授权校验]
│ 当前用户可以操作这个订单吗?
▼
[执行]
Schema 是第一道门,不是最后一道门。
五、Function Calling:模型提出调用,程序掌握执行权
Function Calling 的典型流程可以概括为五步:
(1) 应用把工具定义发给模型
│
▼
(2) 模型返回 function/tool call
│
▼
(3) 应用验证参数并执行函数
│
▼
(4) 应用把执行结果关联到 call_id
│
▼
(5) 模型生成最终答案或继续调用工具
一个工具的核心结构大致如下:
{
"name": "order_get",
"description": "查询当前用户拥有的单个订单。仅在需要实时订单状态时调用。",
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "订单唯一标识,不要使用商品编号或支付流水号"
}
},
"required": ["order_id"],
"additionalProperties": false
}
}
工具描述也是模型输入的一部分,建议详细说明工具用途、适用时机、参数含义和限制,并指出描述质量是影响工具调用效果的重要因素。
一个合格的工具定义应让模型知道:工具做什么?什么时候用?什么时候不用?每个参数代表什么?调用有什么副作用或限制?
例如,下面的描述过于模糊:
创建退款。
更清晰的版本是:
为当前用户拥有且处于可退款状态的订单创建退款。
仅在用户明确确认退款金额和原因后调用。
该工具会产生不可忽略的业务副作用。
查询退款资格时不要调用,应使用 refund_eligibility_get。
Schema 决定参数形状,描述决定模型如何理解工具语义,两者缺一不可。
六、Tool Calling:Function Calling 的上位概念
在许多 API 和框架中,Function Calling 与 Tool Calling 会被混用。工程上可以这样区分:
Tool Calling
├── Function Tool
│ └── 由应用实现的本地函数或远程 API 包装
├── Built-in Tool
│ ├── Web Search
│ ├── Code Execution
│ └── File Search
├── MCP Tool
│ └── 由 MCP Server 暴露的外部能力
└── UI / Computer Tool
└── 浏览器、桌面或界面操作
Function Calling 是 Tool Calling 的一种常见形式。前者强调“以函数和参数的形式表达调用”,后者强调“模型可以使用外部能力”。
工具按执行位置还可以分为以下几类:
客户端工具返回 tool_use 后由应用执行,再以关联 ID 返回 tool_result ;服务端工具由平台执行。
Tool Calling 是状态机,不是一次请求。一个 Agent 可能:
- 不调用工具,直接回答;
- 调用一个工具后回答;
- 并行调用多个独立工具;
- 根据第一个结果决定第二个工具;
- 工具失败后修正参数再调用;
- 达到循环上限后停止。
因此,Agent Runtime 更接近有限状态机:
┌──────────────┐
│ START │
└──────┬───────┘
▼
┌──────────────┐
┌────>│ MODEL_CALL │<────────────┐
│ └───┬──────┬───┘ │
│ │ │ │
│ final │ │ tool_call │
│ ▼ ▼ │
│ ┌──────┐ ┌──────────────┐ │
│ │ DONE │ │ VALIDATE │ │
│ └──────┘ └──┬────────┬──┘ │
│ │ │ │
│ valid│ │error │
│ ▼ ▼ │
│ ┌─────────┐ ┌───────┐ │
│ │ EXECUTE │ │ REPAIR│─┘
│ └────┬────┘ └───────┘
│ │
│ ┌───────┴────────┐
│ │ │
│ success failure
│ │ │
└──────────┴──── result ────┘
运行时必须设置:
- 最大模型轮次;
- 最大工具调用数;
- 单工具超时;
- 总任务截止时间;
- 最大参数修复次数;
- 最大暂时性错误重试次数;
- 取消信号。
否则,“继续调用直到完成”可能变成无限循环和失控账单。
七、输出约束:合法 JSON、Schema 合法与内容正确是三件事
结构化输出存在三个可靠性层级:
Level 1:自然语言要求
“请返回 JSON”
│
▼
可能附带 Markdown、解释文字或语法错误
Level 2:JSON Mode
保证输出可解析为 JSON
│
▼
字段仍可能缺失、类型错误、枚举越界
Level 3:Structured Outputs
输出满足指定 Schema
│
▼
字段内容仍可能存在事实或业务错误
Function Calling 与 Structured Output都可能使用 JSON Schema,前者约束“模型要程序做什么”,后者约束“模型最终对程序说什么”。
即使输出完全符合 Schema,它仍可能是错的,Schema 只能证明类型格式,不能证明真实存在,所以业务代码不能把“Schema 校验通过”当成“事实核验通过”。
另外,结构化输出之外还存在控制信号:
- 安全拒答;
- 输出达到 Token 上限;
- 请求被取消;
- 内容过滤;
- 工具调用未完成;
- 流式输出中断。
消费者不应只做:
JSON.parse(response)
而应先判断:
响应状态
├── completed → 解析并校验
├── refusal → 进入拒答流程
├── incomplete → 判断是否可续写或重试
├── tool_call → 执行工具循环
└── transport_error → 按网络策略处理
八、失败重试:先分类,再决定是否重试
写操作必须具备幂等性。读取天气失败后重试,最坏情况通常是多一次查询。创建退款、发送邮件或扣款重试,可能产生重复副作用。
写工具应接收幂等键:
{
"order_id": "ord_123",
"amount": 100,
"currency": "CNY",
"idempotency_key": "agent_run_abc:refund:ord_123"
}
服务端保存幂等键与执行结果:
首次请求
idempotency_key 不存在
│
▼
执行写操作 ──> 保存结果 ──> 返回成功
重复请求
idempotency_key 已存在
│
▼
不重复执行 ──> 返回首次结果
幂等键应该由可信应用生成,而不是让模型自由生成。否则模型可能在每次重试时产生新键,失去去重作用。
另外,“结果未知”比“明确失败”更危险。假设退款接口在执行后连接超时:
Agent ──创建退款──> 退款服务
Agent <──连接超时──X
此时存在两种可能:服务端没有执行退款、服务端已执行退款,但响应丢失。如果立即重试,可能重复退款。正确流程是:
写操作超时
│
▼
使用幂等键或业务流水号查询状态
│
├── 已成功 → 返回原结果
├── 明确失败 → 评估是否重试
└── 状态未知 → 人工介入或异步对账
因此,Agent Runtime 需要区分 FAILED 和 UNKNOWN 。把两者都映射为异常,会掩盖最棘手的一类一致性问题。
九、一个可落地的 Agent 工具调用循环
type ToolError = {
code: string;
message: string;
retryable: boolean;
};
async function runAgent(userInput: string) {
const messages = [
{ role: "user", content: userInput }
];
const maxTurns = 8;
for (let turn = 0; turn < maxTurns; turn++) {
const response = await callModel({
messages,
tools: toolDefinitions
});
if (response.type === "final") {
return validateFinalOutput(response.output);
}
if (response.type !== "tool_calls") {
throw new Error(`Unsupported response type: ${response.type}`);
}
messages.push(response.assistantMessage);
for (const call of response.calls) {
const tool = toolRegistry.get(call.name);
if (!tool) {
messages.push(toolErrorResult(call.id, {
code: "UNKNOWN_TOOL",
message: `Tool ${call.name} is not available`,
retryable: false
}));
continue;
}
const validation = tool.schema.safeParse(call.arguments);
if (!validation.success) {
messages.push(toolErrorResult(call.id, {
code: "VALIDATION_ERROR",
message: formatValidationError(validation.error),
retryable: true
}));
continue;
}
const authorization = await authorize(
currentUser,
tool,
validation.data
);
if (!authorization.allowed) {
messages.push(toolErrorResult(call.id, {
code: "PERMISSION_DENIED",
message: authorization.reason,
retryable: false
}));
continue;
}
try {
const result = await executeWithPolicy(tool, validation.data, {
timeoutMs: 5000,
idempotencyKey: buildIdempotencyKey(call, currentUser)
});
messages.push(toolSuccessResult(call.id, result));
} catch (error) {
messages.push(
toolErrorResult(call.id, classifyToolError(error))
);
}
}
}
throw new Error("Agent exceeded maximum turns");
}
- 模型只负责提出调用;
- 工具名必须经过允许列表匹配;
- 参数必须经过本地 Schema 校验;
- 鉴权发生在工具执行前;
- 写操作由应用注入幂等键;
- 错误经过分类后再反馈给模型;
- 循环存在明确上限;
- 最终输出仍需独立校验。
十、小结
Agent 连接程序世界的过程,本质上是一套跨越概率系统与确定性系统的协议。
其中:
- Prompt 表达目标和决策规则;
- JSON Schema 定义参数与输出的数据边界;
- Function Calling 让模型提出结构化调用请求;
- Tool Calling 把外部能力纳入多轮执行循环;
- Structured Outputs 让最终结果可被程序稳定消费;
- 校验、鉴权、幂等、错误分类和有限重试共同守住运行时边界。
生产级 Agent 不应依赖模型“自觉地做对”。应用必须掌握执行权,用代码检查模型请求,用最小权限约束工具,用结构化错误帮助模型恢复,并在无法确认执行结果时停止自动动作。
本文由 AI图鉴自动抓取并翻译,版权归原作者所有;如需查看原文请点下方链接。
Introduction
LLM, which receives context and predicts the next Token, is good at understanding the language of nature, but does not really call for weather services because of the following:
{
"name": "get_weather",
"arguments": {
"city": "Shanghai."
}
}
It's just model output data. The subject of genuine web requests, access to databases or changes in business status remains the application.
So, a complete Agent has at least two components:
/
│ │
│User Input - >Prompt/ context - >LLM│
│ │ │
│ Generate call intent │
│ ▼ │
│ tool_call(name, arguments) │
└──────────────────────────┬────────────────────────┘
• Agreed boundary
▼
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
│ │
│Chema Verify - > permission Check - > Tool Execution │
│ │ │ │
I'm sorry.
│ \ / │
Z Write back model Z48Z ─ ─ ─ ─ ─ ─ ─ > > > > > > > >
│ │
└───────────────────────────────────────────────────┘
Function Calling is a multi-stage process: application of a tool definition to the model, model return to tool call request, application of an implementation tool and return of the results to the model. Function Calling is the call protocol between the model and the program, not the permission that the model obtained the direct execution code. To understand this, subsequent security controls, error handling and state management have the right drop point.
II. How the six bottom capabilities form a closed circle
Agent's interface with the program world
Let's go.
│ │
│ Prompt │
• Setting objectives, context, decision-making rules and boundaries
│ │ │
│ ▼ │
│ Tool Definition + JSON Schema │
• Definition of the tools and parameters contract
└──────────────────┬───────────────────┘
▼
Function/Tool Call
Model proposes structured calls
│
▼
It's... it's... it's... it's... it's... it's...
Analysis Schema Validation of Forensics
│ │ │
│ ┌──────────┴──────────┐ │
│ ▼ ▼ │
♪ Success, failure, failure ♪
└──────────┬─────────────────────┬──────┘
│ │
▼ ▼
Structured output constraints Classification retry/ Decline
│ │
└──────────┬──────────┘
▼
Final answer
Each part addresses different issues:
III. Prompt Design: as a decision statement, not a spell
Prompt is mainly responsible for two things in Agent: explaining mission objectives, specifying how models are selected and used. A Prompt for tool call can be broken down into the following structures:
<role>
You're the after-sale assistant.
</role>
<objective>
Helps users query the order status or submit refunds.
</objective>
<tool_policy>
1. When searching for real-time order status, call order get.
2. Refund create may not be called without clear confirmation from the user.
3. In the absence of order id, the user should be asked without speculation.
In the event of a failure of the tool, the result of the implementation may not be fabricated, as the reason is explained by an error code.
</tool_policy>
<output_policy>
Summarizes upcoming actions before calling for writing.
The final answer requires a distinction between “implemented” and “recommendations implemented”.
</output_policy>
<untrusted_input>
{{user_input}}
</untrusted_input>
1. The four components of an effective Prompt
- Target.
The target should describe the results, not the stacking of personality adjectives.
Weaker:
You're a professional, intelligent, strict order assistant.
More enforceable:
You are responsible for checking the status of the order and submitting a refund after the condition for refund has been met and the user has confirmed it.
- Tool selection rules
Models are easily mischosen when more than one tool syntax approaches. Prompt and tool descriptions should indicate when to call, when not, what information is required before calling, whether the tool has side effects, and what boundaries multiple tools have.
- Missing information processing
If the model lacks parameters, it may choose speculation. It should be explicitly required that users are asked if the required parameters are missing and cannot be extrapolated from unrelated context.
It needs to be noted that this only reduces the probability of speculation and that the process still needs to be performed in Schema and business validation.
- Failed behavior.
Do not write only “Please retry if it fails”. The model should be told what decision-making is based on the wrong type:
VALIDATION ERRO: Amend parameters up to retry once.
NOT FOUND: Identify the user, not automatically retry.
Permission DeNIED: Stop calling and explain permission requirements.
RATE LIMITED: Follow retry after waiting after retry.
2. Prompt version subject to evaluation
Prompt is not a static case. At least the production environment should be tested:
- Whether the right tools have been mobilized;
- Whether to fill in the parameters necessary for the omission;
- Whether the tool is called when it is not required;
- Whether to obtain confirmation before writing;
- Whether successful results are fabricated when tools fail;
- Whether the malicious instrument return changes the system instructions;
- Whether a change in the model or Prompt version leads to a return of behaviour.
Therefore, the reliability of Prompt should be determined by the assessment data rather than by “looks complete”.
IV. THE DATA CONTRACT BETWEEN JSON SCHEMA: AGENT AND THE PROCEDURAL
JSON is just a data format, and it's JSON Schema who describes data structure and validation rules.
Using JSON Schema to define:
{
"type": "object",
"properties": {
"order_id": {
"type": "string",
"Description": "Ord 20261027 001"
},
"amount": {
"type": "number",
"exclusiveMinimum": 0,
"Description": "Refund amount, unit specified by currence"
},
"currency": {
"type": "string",
"enum": ["CNY", "USD"]
},
"reason": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": ["order_id", "amount", "currency", "reason"],
"additionalProperties": false
}
- Propertes does not mean they have to be filled in, but they have to cooperate with required to verify their use.
- Additional Projects: false is used to close the object's boundary and, if additional field is not prohibited, the model may generate undefined parameters. For tool parameters, closed objects are usually safer than open objects.
- Enum is more stable than natural language constraints and is used to limit the value of instance to a given pool.
Schema verification and operations verification must be layered:
Model Parameters
│
▼
[grammatical resolution]
JSON, CAN YOU DRIVE IT?
▼
[Schema Verifying]
• Type, required item, count, structure valid?
▼
[Operational verification]
Does the order exist? Is the amount refundable? Is the status allowed?
▼
[authorized verification]
Can the current user handle this order?
▼
[Implementation]
Schema is the first door, not the last door.
V. FUNaction Calling: Modelling calls, program execution Rights
The typical Function Calling process can be summarized as five steps:
(1) Application of tools definition to model
│
▼
(2) Model returns
│
▼
(3) Apply authentication parameters and perform functions
│
▼
(4) Apply to link implementation results to call id
│
▼
(5) Models generate final answers or continue to call tools
The core structure of a tool is as follows:
{
"name": "order_get",
"Description": "Query single orders owned by current users. Call only when a real-time order is required. " I don't know.
"input_schema": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"Description": "Unique identification of order, do not use a commodity number or pay stream."
}
},
"required": ["order_id"],
"additionalProperties": false
}
}
The tool description is also part of the model input, and it is recommended that details be provided on the utility of the tool, the timing of its application, the meaning and limitations of the parameters, and that the quality of the description be an important factor affecting the effects of tool call.
A qualified definition of the tool should let the model know: what the tool does? When? When? What does each parameter represent? What are the side effects or limitations of the call?
For example, the following description is too vague:
Create a refund.
The clearer version is:
Create refunds for orders owned by current users and in refundable status.
Transfers are made only after the user has clearly confirmed the amount and cause of the refund.
The tool will have immeasurable operational side effects.
Do not call when searching for refund eligibility, and use refund eligibility get.
Schema determines the shape of the parameters and describes how the model understands the semantics of the tool.
VI. TOol Calling: Function Calling Up Concept
In many APIs and frames, Function Calling will be mixed with Tool Calling. The distinction can be made in engineering:
Tool Calling
├── Function Tool
│ - Local function from application or remote API packaging
├── Built-in Tool
│ ├── Web Search
│ ├── Code Execution
│ └── File Search
├── MCP Tool
│ - External capabilities exposed by MCP Server
└── UI / Computer Tool
Browser, desktop or interface operation
Faction Calling is a common form for Tool Calling. The former emphasizes " call in the form of functions and parameters ", while the latter emphasizes " models can use external capabilities ".
The tools can also be divided into the following categories by place of implementation:
The client tool returns to the tool use and is executed by application, then by association with the ID; the service-end tool is executed by the platform.
Tool Calling is a status machine, not a request. An Agent might:
- No tools, no direct answers;
- Answer after calling a tool;
- Parallel calls to several independent tools;
- Determine the second tool based on the first result;
- Amending the parameters after the tool has failed to be called;
- Stop when the cycle ceiling is reached.
As a result, Agent Runtme is closer to a limited-state machine:
┌──────────────┐
│ START │
└──────┬───────┘
▼
┌──────────────┐
┌────>│ MODEL_CALL │<────────────┐
│ └───┬──────┬───┘ │
│ │ │ │
│ final │ │ tool_call │
│ ▼ ▼ │
│ ┌──────┐ ┌──────────────┐ │
│ │ DONE │ │ VALIDATE │ │
│ └──────┘ └──┬────────┬──┘ │
│ │ │ │
│ valid│ │error │
│ ▼ ▼ │
│ ┌─────────┐ ┌───────┐ │
│ │ EXECUTE │ │ REPAIR│─┘
│ └────┬────┘ └───────┘
│ │
│ ┌───────┴────────┐
│ │ │
│ success failure
│ │ │
└──────────┴──── result ────┘
Run-time must set:
- Maximum LLM cycle;
- Maximum tool call;
- Single tool timeout;
- The total deadline for the task;
- Maximum parameters repaired;
- Maximum number of temporary errors retry;
- Cancel the signal.
Otherwise, “continue to call until completion” could become an infinity cycle and uncontrolled bill.
VII. Output constraints: Legitimate JSON, Schema Legal and Correct
There are three levels of reliability in structured output:
Level 1: Natural language requirements
"Please return JSON"
│
▼
Possible Markdown, Explanatory Text or Syntax Error
Level 2:JSON Mode
Ensure output interprets to JSON
│
▼
field may still be missing, wrong type, ticking across the border.
Level 3:Structured Outputs
Output meets specified Schema
│
▼
field content may still be factual or business error
Function Calling and Structure Output may use JSON Schema, which binds the "what the model does ", and the "what the model ultimately says to the program".
Even if the output is fully fit with Schema, it may still be wrong, and Schema can only prove the type format and cannot prove it to be real, so the business code cannot consider the "Schema Validation" as a "factual verification pass".
In addition, there are control signals in addition to the structured output:
- Safe refusal;
- Token maximum output;
- The request was cancelled;
- Content filtering;
- tool call is incomplete;
- Fluid output interrupted.
Consumers should not simply:
JSON.parse(response)
It should be judged:
Response Status
Ideas -completed → parsing and verifying
Ideas-refusal poaching process.
Ideas - incomplete
Think - - tool call → Execute Tool Cycle
└ - transfer error → according to network policy
viii. Failed retry: Categorize and decide whether retry
Writing must be of the same kind. retry is read after the weather has failed, and the worst is usually an additional query. The creation of refunds, the sending of mail or the withholding of retry may have repeated side effects.
The writing tool should receive the same key:
{
"order_id": "ord_123",
"amount": 100,
"currency": "CNY",
"idempotency_key": "agent_run_abc:refund:ord_123"
}
Service saves the same key as the execution result:
First request
Outpotcy key does not exist
│
▼
Execute writing operation - > Save result - > Returns successfully
Repeated requests
Other Organiser
│
▼
Do not duplicate > returns the first result
The key should be generated by a credible application, not by free modelling. Otherwise, the model may produce new keys each time retry is lost.
Moreover, “outcome unknown” is more dangerous than “unequivocal failure”. Assuming timeout after implementation:
Agent - Create Refund - > Refund Service
Agent < - Connect timeout - X
At this time, there are two possibilities: the service-end non-execution refund, the service-end implementation refund, but the response is lost. Refunds may be duplicated if retry is immediately available. The correct process is:
Write Operation timeout
│
▼
Query status using a key, etc., or Business Stream
│
Idea-- it's working.
Idea-- Unequivocal failure.
└ state unknown → manual intervention or walk-in reconciliation
Therefore, Agent Runte needs to distinguish between FAILED and UNKNOWN. Mapping both into anomalies would mask the most difficult category of consistency.
IX. A landing tool call cycle
type ToolError = {
code: string;
message: string;
retryable: boolean;
};
async function runAgent(userInput: string) {
const messages = [
{ role: "user", content: userInput }
];
const maxTurns = 8;
for (let turn = 0; turn < maxTurns; turn++) {
const response = await callModel({
messages,
tools: toolDefinitions
});
if (response.type === "final") {
return validateFinalOutput(response.output);
}
if (response.type !== "tool_calls") {
throw new Error(`Unsupported response type: ${response.type}`);
}
messages.push(response.assistantMessage);
for (const call of response.calls) {
const tool = toolRegistry.get(call.name);
if (!tool) {
messages.push(toolErrorResult(call.id, {
code: "UNKNOWN_TOOL",
message: `Tool ${call.name} is not available`,
retryable: false
}));
continue;
}
const validation = tool.schema.safeParse(call.arguments);
if (!validation.success) {
messages.push(toolErrorResult(call.id, {
code: "VALIDATION_ERROR",
message: formatValidationError(validation.error),
retryable: true
}));
continue;
}
const authorization = await authorize(
currentUser,
tool,
validation.data
);
if (!authorization.allowed) {
messages.push(toolErrorResult(call.id, {
code: "PERMISSION_DENIED",
message: authorization.reason,
retryable: false
}));
continue;
}
try {
const result = await executeWithPolicy(tool, validation.data, {
timeoutMs: 5000,
idempotencyKey: buildIdempotencyKey(call, currentUser)
});
messages.push(toolSuccessResult(call.id, result));
} catch (error) {
messages.push(
toolErrorResult(call.id, classifyToolError(error))
);
}
}
}
throw new Error("Agent exceeded maximum turns");
}
- Models are only responsible for proposing calls;
- Tool names must be matched by an authorized list;
- Parameters must be verified locally by Schema;
- Pre-implementation of the instrument;
- Writing operations by applying injections, etc.;
- Misclassification before feedback to the model;
- There are clear ceilings for the cycle;
- The final output needs to be independently verified.
Summary
The process by which Agent connects to the world is essentially a set of protocols that cross the probability and certainty systems.
Of which:
- Prompt on objectives and decision-making rules;
- JSON Schema defines the data boundary between parameters and output;
- Faction Calling to enable models to request structured calls;
- Tool Calling to integrate external capabilities into the multi-cycle implementation cycle;
- Structured Outputs to allow the final results to be programmed to stabilize consumption;
- Validation, assurance, entropy, etc., misclassification and limited retry jointly secure the operational boundary.
Production level Agent should not rely on the model for “self-correcting”. Applications must have enforcement authority, code-check model requests, use a minimum permission binding tool, use structured errors to help the model recover, and stop auto-acting if it is not possible to confirm the execution results.
Auto-fetched and translated by AI Atlas. All rights belong to the original author.