session.rpc.ui.elicitation() returns instant decline (1-2ms) without showing modal after sendAndWait
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- javascript, node.js
- Domain
- api, developer-experience
Research direction
Start at the joinSession command handler and trace the session.sendAndWait() and session.rpc.ui.elicitation() paths, including the ask_user fallback. Reproduce the instant decline on Windows with the minimal example and inspect the session events. Done means interactive elicitation can collect input after sendAndWait, or the extension receives a distinct, actionable unavailable result.
Written by the indexing model from the issue text.
Description
Environment
- Copilot CLI version: 1.0.36
- Extension SDK:
@github/copilot-sdk/extension(joinSessionAPI) - OS: Windows 11 (Windows_NT)
Summary
When a Copilot CLI extension calls session.rpc.ui.elicitation() from inside a command handler that previously called session.sendAndWait(), the elicitation resolves with { action: "decline" } in 1-2ms without ever presenting a modal to the user. The session reports capabilities.ui.elicitation = true and mode = interactive, yet the user never sees any prompt.
The extension's agent-mediated fallback (sending a prompt asking the model to call ask_user) also fails because the ask_user tool auto-declines with "The user is not available to respond" for turns injected by sendAndWait.
Net result: The extension cannot collect any human input after delegating work via sendAndWait, making interactive gates (review finding selection, publish attestation) impossible.
Steps to reproduce
- Load a Copilot CLI extension that registers a command via
joinSession({ commands: [...] }) - In the command handler, call
session.sendAndWait()to delegate to another command - After
sendAndWaitresolves, callsession.rpc.ui.elicitation()with a valid schema - Observe that it resolves instantly with
{ action: "decline" }--- no UI is shown
Minimal reproduction
import { joinSession } from "@github/copilot-sdk/extension";
const session = await joinSession({
commands: [
{
name: "test-elicit",
description: "Test elicitation after sendAndWait",
handler: async (context) => {
// Step 1: Delegate work to the model
await session.sendAndWait({ prompt: "Say hello" }, 60_000);
// Step 2: Try to elicit user input
const start = Date.now();
const result = await session.rpc.ui.elicitation({
message: "Pick an option",
requestedSchema: {
type: "object",
properties: {
choice: {
type: "string",
title: "Your choice",
enum: ["A", "B", "C"],
default: "A",
},
},
required: ["choice"],
},
});
const elapsed = Date.now() - start;
// Logs: "Elicitation returned decline in 1ms"
await session.log(
Elicitation returned {result.action} in {elapsed}ms
);
},
},
],
});
Observed behavior
Timeline from session events
T+0s session.info "interactive elicitation: available; session mode: unknown"
<- session.capabilities.ui.elicitation reports true
T+997s sendAndWait("/review ...") called, completes successfully
T+997s session.rpc.mode.set({ mode: "interactive" }) succeeds
<- mode is now "interactive"
T+997s session.rpc.ui.elicitation() called
<- returns { action: "decline" } in 1ms
<- NO MODAL IS SHOWN TO THE USER
T+997s Agent-mediated fallback: sendAndWait() with prompt asking model to call ask_user
<- model calls ask_user
<- ask_user returns: "The user is not available to respond"
<- model returns {"action":"decline"}
T+1024s Second elicitation attempt (text fallback)
<- session.rpc.ui.elicitation() returns decline in 2ms (again, no modal)
<- agent-mediated fallback also fails with "user not available"
Raw session event evidence
{
"type": "session.warning",
"data": {
"message": "Direct elicitation returned decline in 1ms (mode: interactive); treating as synthetic decline."
},
"timestamp": "2026-04-27T03:00:07.856Z"
}
{
"type": "tool.execution_complete",
"data": {
"toolTelemetry": {
"properties": {
"elicitation_action": "decline",
"elicitation_field_types": "[\"multi-enum\",\"string\"]"
}
},
"result": {
"content": "The user is not available to respond and will review your work later."
}
},
"timestamp": "2026-04-27T03:00:31.300Z"
}
Expected behavior
session.rpc.ui.elicitation() should present an interactive modal to the user and block until the user accepts, declines, or cancels. If the host cannot present a modal in the current execution context (e.g., inside a sendAndWait callback), it should either:
- Queue the elicitation and present it after the current turn completes, or
- Throw an error with a clear message like
"Elicitation not supported during sendAndWait callbacks", or - Return a distinct result (e.g.,
{ action: "unavailable" }) so extensions can distinguish "host can't show UI" from "user clicked decline"
Additionally, ask_user should work for model turns injected by extensions via sendAndWait. The user IS present --- they typed a command and are waiting. The sendAndWait turn is extension-initiated, but the session is still interactive.
Call context where elicitation fails
User types: /submit-pr
-> handleSubmitPr()
-> runPreflight() <- works
-> sendAndWait("/review ...") <- works (30min timeout)
-> recordAndLogReviewOutput() <- works
-> askForReviewDecisions() <- FAILS HERE
-> elicit(message, schema)
-> session.rpc.ui.elicitation() <- returns decline in 1ms
-> agentMediatedElicitation()
-> sendAndWait(prompt) <- model calls ask_user
-> ask_user <- "user not available"
Extension workaround code (currently failing)
async function elicit(message, requestedSchema) {
if (!session.capabilities?.ui?.elicitation) {
return agentMediatedElicitation(message, requestedSchema, "unavailable");
}
const mode = await ensureInteractiveMode(message);
if (mode === "autopilot") {
return agentMediatedElicitation(message, requestedSchema, "autopilot");
}
const elicitStart = Date.now();
const result = await session.rpc.ui.elicitation({ message, requestedSchema });
const elicitMs = Date.now() - elicitStart;
// Detect synthetic decline (returned too fast for human interaction)
const isSyntheticDecline =
result.action === "decline" &&
(["autopilot", "unknown"].includes(await refreshSessionMode())
|| elicitMs < 2000);
if (isSyntheticDecline) {
return agentMediatedElicitation(message, requestedSchema,
licitation-returned-in-{elicitMs}ms);
}
return result;
}
async function agentMediatedElicitation(message, requestedSchema, reason) {
// Asks the model to call ask_user on behalf of the extension
// FAILS: ask_user auto-declines for sendAndWait-injected turns
const response = await sendAndCaptureContent(
agentElicitationPrompt(message, requestedSchema, reason),
15 * 60 * 1000
);
// ...parse JSON response...
}
Both layers fail:
- Layer 1 fails because
session.rpc.ui.elicitation()returnsdeclinein 1ms - Layer 2 fails because
ask_userauto-declines for turns injected bysendAndWait
Impact
- Extensions cannot implement interactive multi-step workflows
session.capabilities.ui.elicitationcapability check is misleading --- reportstruebut doesn't work in practice- Extensions requiring human-in-the-loop gates (security attestation, publish confirmation) cannot enforce them
- The
sendAndWait->elicitpattern is the most natural way to build multi-step extension workflows, and it's completely broken
- Dominant language
- Java
- Stars
- 10.5k
- Forks
- 1.5k
- Avg merge
- 1d 12h
- Merged PRs (30d)
- 133
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from github/copilot-sdk
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
github/copilot-sdk#2709 · 1 comment ·
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
github/copilot-sdk#2673 ·
-
bug testing
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
github/copilot-sdk#2628 ·
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
github/copilot-sdk#2627 · 1 comment ·
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
github/copilot-sdk#2493 ·
All issues in github/copilot-sdk
Similar issues
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 90/100
apache/cloudstack#14222 ·
-
[BUG]茶杯方块在取茶时会引发崩溃 Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
1.0.0-alpha2 Type/Improvement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
wso2/dpdp-accelerator#272 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
apache/rocketmq-dashboard#4860 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
infinispan/infinispan#18150 ·