github / github/copilot-cli

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

Abierto
#1,552 1 comentario 0 reacciones 0 asignados Ver en GitHub
area:sessions
Lenguaje dominante
Shell
Estrellas
11.2k
Forks
1.9k
Merge medio
14 h 16 min
PR fusionados (30 d)
6

Descripción

### 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_

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.