Bug: noReply pattern broken in 1.0.69+ (agent loop refactor regression)
Summary
The noReply: true option for client.session.prompt() is broken in OpenCode 1.0.69 and later. Tools that use this pattern to silently insert context into the session now hang indefinitely with status "queued".
Version Information
Expected Behavior (1.0.68 and earlier)
When a plugin calls client.session.prompt({ noReply: true, ... }), the context should be inserted into the session without triggering an AI response, and the function should return immediately with the created user message.
// Inside a tool handler
await client.session.prompt({
path: { id: sessionID },
body: {
noReply: true, // Should skip AI inference and return immediately
parts: [{ type: "text", text: "Context to insert..." }],
},
});
// Tool returns confirmation
return "✓ Context inserted successfully";
Result in 1.0.68: ✅ Context inserted, tool returns immediately, agent continues normally.
Actual Behavior (1.0.69+)
The same code now causes the tool to hang indefinitely with status "queued" in the TUI. The tool never completes.
Result in 1.0.69+: ❌ Tool hangs, session becomes unresponsive.
Root Cause Analysis
In 1.0.68, the prompt() function had an early return for noReply:
// packages/opencode/src/session/prompt.ts (1.0.68)
export async function prompt(input: PromptInput): Promise<MessageV2.WithParts> {
// ... setup code ...
const userMsg = await createUserMessage(input);
await Session.touch(input.sessionID);
// Early return for context-only messages (no AI inference)
if (input.noReply) {
return userMsg; // ✅ Returns immediately
}
// ... continue with agent loop ...
}
In 1.0.69, this early return was removed during the agent loop refactor:
// packages/opencode/src/session/prompt.ts (1.0.69+)
export const prompt = fn(PromptInput, async (input) => {
const session = await Session.get(input.sessionID);
await SessionRevert.cleanup(session);
await createUserMessage(input); // Note: changed to not return userMsg
await Session.touch(input.sessionID);
return loop(input.sessionID); // ❌ Always enters loop, even with noReply: true
});
The Problem: The loop waits for an assistant message with a finish reason, but when noReply: true, no assistant message is ever created. The loop runs forever, waiting for a response that will never come.
Proposed Fix
Restore the noReply early return in packages/opencode/src/session/prompt.ts:
export const prompt = fn(PromptInput, async (input) => {
const session = await Session.get(input.sessionID);
await SessionRevert.cleanup(session);
const userMsg = await createUserMessage(input); // Capture return value
await Session.touch(input.sessionID);
// Early return for context-only messages (no AI inference)
if (input.noReply) {
return userMsg; // ✅ Return immediately, skip agent loop
}
return loop(input.sessionID);
});
Steps to Reproduce
- Create a plugin with a tool that uses
noReply (see test plugin example below)
- Use OpenCode 1.0.69+ and call the tool
- Expected: Tool returns immediately with confirmation message
- Actual: Tool hangs indefinitely with status "queued"
Test Plugin
// .opencode/plugin/test-noreply.ts
import { type Plugin, tool } from "@opencode-ai/plugin";
export const TestNoReplyPlugin: Plugin = async ({ client }) => {
return {
tool: {
test_noreply: tool({
description: "Test noReply pattern",
args: {
message: tool.schema.string(),
},
async execute(args, ctx) {
// Insert context using noReply
await client.session.prompt({
path: { id: ctx.sessionID },
body: {
noReply: true,
parts: [{ type: "text", text: `Context: ${args.message}` }],
},
});
return "✓ Context inserted";
},
}),
},
};
};
Impact
This regression affects plugins that inject context into sessions for:
- Background information that needs to persist across tool output compaction
- Multi-step workflows where context must survive between tool calls
- Any tool requiring persistent context in the conversation history
References
Bug:
noReplypattern broken in 1.0.69+ (agent loop refactor regression)Summary
The
noReply: trueoption forclient.session.prompt()is broken in OpenCode 1.0.69 and later. Tools that use this pattern to silently insert context into the session now hang indefinitely with status "queued".Version Information
8ba48ed7)de50234a)a1214fff- "Refactor agent loop" (Refactor agent loop #4412)Expected Behavior (1.0.68 and earlier)
When a plugin calls
client.session.prompt({ noReply: true, ... }), the context should be inserted into the session without triggering an AI response, and the function should return immediately with the created user message.Result in 1.0.68: ✅ Context inserted, tool returns immediately, agent continues normally.
Actual Behavior (1.0.69+)
The same code now causes the tool to hang indefinitely with status "queued" in the TUI. The tool never completes.
Result in 1.0.69+: ❌ Tool hangs, session becomes unresponsive.
Root Cause Analysis
In 1.0.68, the
prompt()function had an early return fornoReply:In 1.0.69, this early return was removed during the agent loop refactor:
The Problem: The loop waits for an assistant message with a finish reason, but when
noReply: true, no assistant message is ever created. The loop runs forever, waiting for a response that will never come.Proposed Fix
Restore the
noReplyearly return inpackages/opencode/src/session/prompt.ts:Steps to Reproduce
noReply(see test plugin example below)Test Plugin
Impact
This regression affects plugins that inject context into sessions for:
References
a1214fff- "Refactor agent loop" (#4412) (Nov 17, 2025)packages/opencode/src/session/prompt.tsv1.0.68(commit8ba48ed7)v1.0.69(commitde50234a)