F5.4 F5

什么时候有状态才真正重要

query() 还是 ClaudeSDKClient 不是功能、性能或语言的问题。两个都支持工具,都接受同样的配置,都用同一个模型。唯一的问题是:下一次调用需不需要上一次的上下文?

判断规则

下一次交互是否引用了上一次? 如果是 → ClaudeSDKClient。如果不是 → query()

调试会话:“读 auth.ts” → “这个函数在哪里被调用了”。第二个请求只在有第一次上下文的时候才有意义。这就该用 ClaudeSDKClient

处理 100 张发票:每次提取都是独立的。47 号发票和 12 号发票毫无关系。这就是 100 次 query() 调用。

常见误解

query() 不能用工具” — 错了。query() 跑完整的 agentic 循环。如果一个任务需要调 Read、再调 Grep、再调 Write,这些全在一次 query() 调用内发生。单次执行内的工具链没问题。限制只在跨调用的上下文——下一次 query() 调用不知道上一次做了什么。

“ClaudeSDKClient 更快/更好” — 这个选择关乎状态管理,不关乎性能。query() 没有 30 秒超时限制。ClaudeSDKClient 没有增强的错误处理。两者跑同样的 agentic 循环、用同一个模型。

“到处用 ClaudeSDKClient 保持一致性” — 这给不需要状态的任务增加了会话生命周期开销(async context manager 的建立和清理)。单次任务用 query() 更简单。

对号入座

任务接口原因
分类一个工单query()自包含,没有后续
处理 50 个独立发票50× query()每个都是独立的
多轮客服对话ClaudeSDKClient后续问题引用之前的上下文
来回的调试会话ClaudeSDKClient每一步基于前一步
一次性文档分析query()一次交互就能完成

两者都接受 ClaudeAgentOptions

两个接口接受同样的配置对象。System prompt、允许的工具、权限模式——两者都能配置。接口选择和配置是正交的。


一句话总结: 每次调用独立时选 query(),后续需要之前上下文时选 ClaudeSDKClient——两者都支持工具、同一个模型、同样的配置。