Skip to content

Commit 9f4933a

Browse files
fix: skip completion eval when work was delegated to subagent (#179)
When the agent loop called spawn_subagent or invoke_agent, the completion evaluator now skips rather than re-prompting. The SubagentResultHandler will deliver the result — re-prompting races with it and produces duplicate answers (the user sees both the subagent result and the re-prompted primary response). Also updates directives to allow direct handling of simple closed questions that need only 1-2 tool calls. The subagent overhead is counterproductive for "when does my class end?" style queries. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 682fe7b commit 9f4933a

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

src/RockBot.Agent/agent/directives.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,15 @@ at a locked input box.
108108
- Exploratory, research-oriented, or multi-source data tasks.
109109
- Anything the user asks to do "in the background" or "while we talk."
110110

111-
#### Handle directly (no subagent) only when
111+
#### Handle directly (no subagent) when
112112

113113
- The response requires **zero tool calls** — purely conversational, drawn from
114114
context already in your window.
115+
- The task is a **simple, closed question** that needs one or two tool calls to
116+
answer — e.g. "when does my class end?", "what's on my calendar today?",
117+
"do I have any unread emails from Bob?" For these, the subagent overhead
118+
(spawning, context building, synthesis) takes longer than just calling the
119+
tool directly. Answer the question, done.
115120
- The task requires exactly **one fast local tool call** (a single memory lookup,
116121
a single working memory read) where the round-trip is under a second.
117122
- You are synthesizing results that subagents have already returned — reading

src/RockBot.Host/AgentLoopRunner.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,18 @@ public async Task<string> RunAsync(
219219
if (!enableCompletionEval || maxReprompts == 0 || reprompt == maxReprompts)
220220
return result.Response;
221221

222+
// Skip evaluation when the agent delegated to a subagent. Spawning a
223+
// subagent is intentional delegation — the SubagentResultHandler will
224+
// synthesize and publish the result. Re-prompting here would race with
225+
// that handler and produce duplicate answers.
226+
if (chatMessages.Any(m => m.Contents.OfType<FunctionCallContent>()
227+
.Any(fc => fc.Name is "spawn_subagent" or "invoke_agent")))
228+
{
229+
HostDiagnostics.CompletionCheckSkipped.Add(1);
230+
logger.LogInformation("Completion evaluator: SKIPPED (delegated to subagent/agent)");
231+
return result.Response;
232+
}
233+
222234
// Evaluate whether the response actually completes the original request.
223235
var (complete, reason) = await EvaluateCompletionAsync(
224236
originalUserRequest, result.Response, cancellationToken);

0 commit comments

Comments
 (0)