输入模式决定的是:任务开始后,你的应用还能不能继续给 Agent 发送消息。
它不区分文本、图片等消息内容,也不决定回复是否逐块显示。无论选择哪种输入模式,SDK 都会以消息流返回 Agent 的回复。如何处理回复,见流式输出。
Qoder Agent SDK 提供两类输入方式:
选择时只需要考虑一个问题:任务开始后,是否还要继续给 Agent 发消息?
把字符串传给
Java 的一次性查询在 CLI 返回本轮
流式输入允许你的应用在任务开始后继续发送消息。除了聊天中的多轮对话,它还可以在任务进行中补充信息、改变执行方向,或安排稍后处理的消息。
三个 SDK 的推荐接口不同:
TypeScript 的消息字段见
Python 的
这种写法只适合预先准备好的消息。它不能根据 Agent 刚刚返回的内容决定下一条消息,也不能调用
Java 还可以在拿到用户输入之前启动 CLI。
Agent 回复期间,也可以继续发送消息。
相同优先级的消息按发送顺序处理。要立即改变当前方向,使用
有时你只想补充背景信息,不希望 Agent 立即回复。此时设置
调用
Java 的
要取消一条尚未开始处理的消息,先给它设置会话内唯一的 UUID。TypeScript 使用消息的
取消成功返回
Java 中从其他线程关闭会话后,正在读取的游标以
| 输入方式 | TypeScript | Python | Java | 什么时候使用 |
|---|---|---|---|---|
| 单消息输入 | query({ prompt: string }) | query(prompt=str) | client.query(OneShotQueryRequest) | 一次性任务、批处理、CI 脚本 |
| 流式输入 | query({ prompt: AsyncIterable<SDKUserMessage> }) | 推荐使用 QoderSDKClient;预先确定的消息流也可传给 query() | client.openSession(options) 返回的 QoderSession | 聊天界面、多消息会话、运行中追加或调整任务 |
- 不需要。使用单消息输入。
- 需要。例如用户还会追问,或者应用要根据 Agent 的回复决定下一步。使用流式输入。
单消息输入
把字符串传给 query() 会启动一个独立任务。任务开始后,不能再向这次调用追加用户消息。任务完成后,SDK 自动结束会话。
ResultMessage 后结束。仍应把消息流读到结束,再关闭游标或 QoderQuery;ResultOutcome.ERROR 表示本轮失败,没有抛异常不等于成功。
单消息输入不影响工具审批。如果 Agent 需要执行尚未获得许可的工具,canUseTool / can_use_tool 仍然可以询问用户。你不需要为此把 prompt 改成消息流。详见审批与用户输入。
流式输入
流式输入允许你的应用在任务开始后继续发送消息。除了聊天中的多轮对话,它还可以在任务进行中补充信息、改变执行方向,或安排稍后处理的消息。
三个 SDK 的推荐接口不同:
- TypeScript:把
AsyncIterable<SDKUserMessage>传给query()。它是一个可以持续yield用户消息的异步迭代器。聊天 UI、消息队列或其他事件都可以向它提供消息。 - Python:使用
QoderSDKClient保持会话。调用client.query(...)发送一条新消息,再用client.receive_response()接收这一轮的回复。 - Java:用
client.openSession(options)打开QoderSession。调用session.send(...)发送一条新消息,再从同一个消息游标读取回复,读到ResultMessage表示这一轮结束。
多消息会话
SDKUserMessage。在 Python 中,每次 receive_response() 接收一轮回复。收到 ResultMessage 后,可以继续发送下一条消息。
在 Java 中,每条输入是一个 UserInput。send() 完成只表示输入已写入 CLI,不表示回复结束。同一个会话的消息流只能消费一次,应跨轮复用同一个游标;关闭游标会同时关闭会话。
Python 异步消息流的边界
Python 的 query() 也接受 AsyncIterable[dict[str, Any]]。如果多条消息在任务开始前就已经确定,可以用这种方式依次发送。下面只展示 Python 异步消息流的核心写法,query 和 options 的创建方式见前面的完整示例:
Python
interrupt() 或取消排队消息。聊天界面等交互式应用应使用 QoderSDKClient。
预先启动 CLI(Java)
Java 还可以在拿到用户输入之前启动 CLI。client.prepare(options) 完成启动、认证和初始化,但不发送输入,用来消除首次请求的启动延迟:
Java
PreparedQuery 只能转换一次。转换后由新的 QoderSession 或 QoderQuery 负责释放资源;一直没有用上时,调用 close() 丢弃它。
运行中追加输入
Agent 回复期间,也可以继续发送消息。priority 决定 Agent 什么时候处理这条消息:
| 值 | 行为 |
|---|---|
now | 停止当前回复,立即处理这条消息 |
next | 默认值;在下一个合适的时机处理 |
later | 等当前回复结束后处理 |
priority: 'now'。如果只想停止当前回复,不想发送新消息,请使用中断当前回复。
Java 用 UserInput.Builder 的 priority(SendPriority.NOW / NEXT / LATER) 设置优先级。Java 的 UserInput 默认优先级是 NOW,不是 next;运行中追加消息时,按需要显式设置。
下面的代码需要放入前面的 TypeScript 消息生成器、已连接的 Python client 会话或 Java 的 QoderSession 中:
添加上下文但不触发回复
有时你只想补充背景信息,不希望 Agent 立即回复。此时设置 shouldQuery: false(TypeScript)、should_query=False(Python)或 shouldQuery(false)(Java)。这条消息仍会加入对话,何时生效由 priority 决定。
中断当前回复
调用 interrupt() 可以停止 Agent 当前的回复,但不会结束会话。中断后仍可继续发送消息。TypeScript 在 query() 返回的对象上调用;Python 需要使用 QoderSDKClient;Java 在 QoderQuery 或 QoderSession 上调用。
interrupt() 返回 InterruptResult,成功只表示 CLI 接受了中断请求,本轮何时结束仍以 ResultMessage 为准。
interrupt() 不会删除等待处理的消息。如果其中某条消息已经不需要,请单独取消。要结束整个会话,请调用关闭方法或退出 async with 代码块。
取消排队消息
要取消一条尚未开始处理的消息,先给它设置会话内唯一的 UUID。TypeScript 使用消息的 uuid 字段,Python 使用 message_uuid 参数。Java 不需要自己生成 ID:用 session.submit(input) 代替 send(input) 发送,返回的 MessageSubmission 立即带有 SDK 分配的 MessageId:
下面只展示取消操作本身,假设 q / client 和对应的消息 UUID 已经创建:
true / True。如果消息不存在或已经开始处理,则返回 false / False。没有 UUID 的消息不能单独取消;同一会话中不要重复使用 UUID。
Java 中,还没写入 CLI 的消息由 SDK 在本地取消,这条消息的 written() 以 CancellationException 结束,会话不受影响。已经开始写入的消息,只有 CLI 支持对应能力时才会尝试远端取消,否则返回 false。只需要写入确认时用 send(),需要在写入前拿到 ID 时用 submit()。
结束输入和关闭会话
- TypeScript:字符串任务完成后,SDK 自动结束会话。使用异步消息流时,迭代器结束表示不再发送消息。要提前关闭整个会话,可以使用
AbortController或调用q.close()。 - Python:一次性
query()会自动结束。使用QoderSDKClient时,推荐用async with自动连接和断开;也可以手动调用connect()/disconnect()。 - Java:一次性查询读到消息流结束后,关闭游标或
QoderQuery。QoderSession用完后关闭;需要确保已接受的输入都写入 CLI 时,先等待completeInput(),它会拒绝后续输入,但不等待回复。关闭QoderClient会级联关闭它创建的全部查询和会话。
messages() 和 options:
自动关闭
根据外部条件提前关闭
SessionClosedException 结束。不要在 SDK 回调或推送处理器里调用阻塞式 close(),在这些位置使用 closeAsync()。
会话关闭后,不能再向它发送消息。