github / github/copilot-cli

Deferred tool results — let tool handlers suspend a turn and resume via submitToolResult()

未关闭
#1,552 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
area:sessions
主要语言
Shell
星标
11.2k
派生
1.9k
平均合并
14 小时 16 分钟
30 天内合并 PR
6

描述

### Describe the feature or problem you'd like to solve

Custom tool handlers must resolve before the tool.call JSON-RPC response is sent — there's no way to signal "I'll have the result later."

### Proposed solution

If `tool.call` can accept a `deferred` result, CLI can remain in a suspended state (e.g. further messages are queued) until client submits tool results later.

This enables long-running tools (human-in-the-loop approvals, etc) especially in durable orchestration where the CLI cannot be kept running for long periods of time. Today these scenarios require something like the following workaround:
- `tool.call` comes in
- client returns 'the tool call ABC has been processed; you will be notified when it completes'
- (while waiting for long-running tool) client may destroy and resume CLI session
- client resumes CLI session and sends message `tool call ABC has results; call get_deferred_result(ABC)`
- CLI calls `get_deferred_result(ABC)` so that the result goes through same tool result flow

This adds extra assistant turns / token usage. It would be useful to have something like:
- `tool.call` comes in
- client returns something like `{ 'result': 'deferred' }`
- (while waiting for long-running tool) client may destroy and resume CLI session
- client resumes CLI session with some new payload `{ 'type': 'submit-deferred-tool-results', 'toolCallId': '...', 'result': { ... } }`
- CLI immediately interprets the results and continues the session

This would simplify the back and forth and does not rely on LLM intelligently knowing to call `get_deferred_result`. In a durable/serverless scenario the CLI may be stopped and resumed on a different worker, so it is challenging to hold the tool.call JSON-RPC call open. The deferred result type lets the CLI checkpoint the pending tool call into session state so it survives destroy/resume.

### Example prompts or workflows

Sample workflows include human-in-the-loop, webhooks, or any long-running tool call in an environment where we expect the CLI session may be destroyed and resumed during the tool execution (e.g. in durable / serverless environments).

This is pseudocode for example SDK code this might enable:

```js
import { CopilotClient, defineTool } from "@github/copilot-sdk";

const client = new CopilotClient();

// 1. Create session with a deferred-capable tool
const session = await client.createSession({
model: "claude-sonnet-4.5",
tools: [
defineTool("request_approval", {
description: "Request human approval for an action.",
parameters: { type: "object", properties: { reason: { type: "string" } }, required: ["reason"] },
handler: async ({ reason }, invocation) => {
// Kick off external process, pass toolCallId for correlation
await sendSlackApprovalRequest(invocation.toolCallId, reason);
return { resultType: "deferred" };
},
}),
],
});

// 2. Send prompt — LLM calls the tool, gets deferred, turn is parked
await session.send({ prompt: "Get approval to deploy v2.0 to production." });

// 3. Save IDs, tear down — worker can scale to zero
const sessionId = session.sessionId;
await session.destroy();
await client.stop();

// ─── time passes: minutes, hours, days ─────────────────────────────
// Slack webhook fires on a completely different worker/container.
// It has sessionId + toolCallId from the original request.

// 4. New worker resumes the session and submits the result
const client2 = new CopilotClient();
const resumed = await client2.resumeSession(sessionId);

await resumed.submitToolResult(toolCallId, {
textResultForLlm: "Approved by @alice at 3:42 PM",
resultType: "success",
});
// CLI resumes the LLM turn with a proper tool_result → assistant responds

await resumed.destroy();
await client2.stop();
```

### Additional context

_No response_

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。