关于 query-loop-implementation
面向 AI 应用开发者的查询循环实现指南,将会话状态、任务轮次控制和工具执行分层,并强调安全检查与明确的退出条件。
主要功能
- 01分离会话、循环与工具运行时
- 02采用结构化工具调用消息流
- 03校验输入模式并检查权限
- 04设置轮次、超时和预算限制
- 05定义结构化终止原因
适用场景
- 01为 AI 应用设计查询引擎
- 02审查现有模型与工具循环
- 03为已注册工具加入安全执行
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ simbajigege/ book2skills --skill query-loop-implementation安装后在 Claude Code 中输入/query-loop-implementation确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
LICENSEREADME.mdagents/openai.yamlreferences/query-loop-patterns.md详细介绍
查询循环实现
核心理念
将循环构建为产品基础设施,而不是提示词胶水:
ConversationManager -> QueryLoop -> ToolRuntime
ConversationManager管理持久状态:会话 ID、消息、用户设置、预算和持久化。QueryLoop管理单个任务回合:调用模型、检测工具调用、执行工具、追加工具结果并重复。ToolRuntime管理已注册的工具:架构、权限检查、执行和错误格式化。
以 ReAct 作为思维模型:
Thought -> Action -> Observation -> Thought -> Answer
将其实现为结构化 API 流量:
model thinking/text -> tool_call -> tool_result -> next model call -> final text
实现工作流
-
检查用户的技术栈和当前 LLM 调用位置。 找到消息的构建位置、模型的调用位置,以及是否已配置工具/函数调用。
-
引入最精简的查询循环。 让首个版本保持精简:一个模型调用函数、一个工具注册表和明确的退出条件。
-
统一消息格式。 如有可用的提供方结构化工具调用格式,请使用该格式。除非提供方没有函数/工具调用 API,否则避免解析自由格式的
Action:文本。 -
增加工具执行安全措施。 根据架构验证工具输入,对有风险的工具应用权限检查,将失败封装为工具结果,并记录每次调用。
-
在扩展功能前添加退出和预算保护。 始终包含
maxTurns、超时/取消支持、令牌/费用预算检查,以及致命错误处理路径。 -
将上下文窗口策略留在此技能之外。 将
messages作为循环输入并返回更新后的messages,但将裁剪、检索、摘要和压缩交由单独的上下文管理层处理。
最简循环
根据用户使用的语言和 SDK 调整此结构:
async function runQueryLoop({
initialMessages,
model,
tools,
maxTurns = 10,
signal,
}: {
initialMessages: Message[]
model: ModelClient
tools: ToolRegistry
maxTurns?: number
signal?: AbortSignal
}) {
let messages = [...initialMessages]
for (let turn = 1; turn <= maxTurns; turn++) {
if (signal?.aborted) return { status: "aborted", messages }
const response = await model.generate({
messages,
tools: tools.definitions(),
signal,
})
messages.push(response.message)
const toolCalls = extractToolCalls(response.message)
if (toolCalls.length === 0) {
return {
status: "completed",
finalMessage: response.message,
messages,
}
}
for (const call of toolCalls) {
const result = await tools.execute(call, { signal, messages })
messages.push(makeToolResultMessage(call.id, result))
}
}
return { status: "max_turns", messages }
}
“模型继续判断”这一步并非独立函数。循环在追加 tool_result 消息后再次调用模型时,这一步就会发生。
必需的退出条件
发布前实现以下条件:
- 正常完成:模型响应中没有工具调用。
- 达到最大回合数:经过固定数量的模型-工具循环后停止。
- 中止/超时:用户取消请求或请求超出截止时间时停止。
- 权限被拒:根据产品的安全策略停止,或返回工具错误。
- 超出预算:令牌、费用或运行时间预算耗尽时停止。
- 致命工具错误:工具故障无法由模型纠正时停止。
优先返回结构化的终止原因:
type TerminalReason =
| "completed"
| "max_turns"
| "aborted"
| "timeout"
| "permission_denied"
| "budget_exceeded"
| "fatal_tool_error"
工具运行时契约
每个工具都应定义:
type Tool = {
name: string
description: string
inputSchema: unknown
risk: "read" | "write" | "execute" | "external"
validate(input: unknown): ValidatedInput
canUse(input: ValidatedInput, ctx: ToolContext): Promise<PermissionDecision>
call(input: ValidatedInput, ctx: ToolContext): Promise<ToolResult>
}
执行顺序:
find tool by name
-> schema validate model input
-> run tool-specific validation
-> check permission
-> call tool
-> format success or error as tool_result
如果模型有可能恢复,请将工具错误返回给模型,例如参数无效、文件未找到、搜索结果为空或临时 API 错误。对于安全违规、重复失败、缺少凭据或预算耗尽,应停止循环。
产品设计指南
让模型负责“智能”,让代码负责“可靠性”:
- 让模型决定是否需要再次调用工具。
- 让代码强制执行架构、权限、预算和循环退出条件。
- 让提示词聚焦于工具语义和任务策略。
- 让实现聚焦于确定性的控制流。
对于简单的 AI 应用,起初应避免使用子 Agent、worktree 和流式工具执行。只有在产品确实需要并行工作、隔离或长时间运行的任务时,才添加这些功能。
何时需要更多细节
在设计新的查询引擎、审查现有实现,或向其他工程师解释从 ReAct 到查询循环的架构时,请阅读 references/query-loop-patterns.md。