agents: detect [END_OF_ANSWER] from text, not the provider stop reason - #1702
Merged
Merged
Conversation
Every proper finish through Bifrost looked like a stall. The agents registered [END_OF_ANSWER] as a provider stop sequence, so Anthropic consumed the marker and the only evidence of a finish was the raw stop reason "stop_sequence". Bifrost maps that to "stop" inbound and "stop" back to "end_turn" outbound (core/providers/anthropic/utils.go, v1.6.2 and v1.8.6 alike), so needsContinuation saw end_turn with no marker in the text, nudged the model twice, and reported `incomplete: stall` — which Hive's propose_code_change then refused, diff and all. Every repo_agent run behind the gateway paid two wasted rounds. Drop the stop sequence from the repo, graph, log, and jarvis sub-agents. The marker stays in the text, where createHasEndMarkerCondition, needsContinuation, and extractFinalAnswer already detect and strip it — the path every non-Anthropic provider was on all along, and the only one that survives a gateway. Providers that honor `stop` and report a plain "stop" either way (OpenAI-compatible) gain stall detection they never had. The rawFinishReason "stop_sequence" check stays as harmless belt-and-braces. turns.ts strips the marker before text becomes a reasoning Turn, so the protocol token never reaches the graph. Hive already strips it at its stream and MCP boundaries. Verified against a local server with the exact Hive request that failed: completed, no continuation nudges, preview.ok with the two-file diff, no marker in the returned content.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every proper agent finish through Bifrost looked like a stall. The agents registered
[END_OF_ANSWER]as a provider stop sequence, so Anthropic consumed the marker and the only evidence of a finish was the raw stop reasonstop_sequence. Bifrost maps that lossily —stop_sequence→stopinbound,stop→end_turnoutbound (core/providers/anthropic/utils.go, same in v1.6.2 and v1.8.6) — soneedsContinuationsawend_turnwith no marker in the text, nudged the model twice, and reportedincomplete: stall. Hive'spropose_code_changethen refused a correct diff (stakwork/hive#5308 made that refusal explicit). Everyrepo_agentrun behind the gateway paid two wasted rounds; a two-line change took 47s and 114k tokens.Fix
Drop
stopSequences: ["[END_OF_ANSWER]"]from the repo, graph, log, and jarvis sub-agents. The marker stays in the text, wherecreateHasEndMarkerCondition,needsContinuation, andextractFinalAnsweralready detect and strip it. That's the path every non-Anthropic provider was already on, and the only one that survives a gateway. OpenAI-compatible providers (plainstopeither way) gain stall detection they never had. TherawFinishReason === "stop_sequence"check stays as harmless belt-and-braces.turns.tsstrips the marker before text becomes areasoningTurn, so the protocol token never reaches the graph. Hive already strips it at its stream (useStreamProcessor) and MCP (orgMcpTools) boundaries.Verification
test:nodesubset for repo/utils/turns/stream/log sessions: 108/108;tscclean.propose_code_changerequest that failed:status: completed,incomplete: undefined, 0 continuation nudges in the transcript,preview.okwith the two-file diff, marker present in the transcript text and absent from the returnedcontent.Follow-ups (not in this PR)
runCanvasAgentstill registers the stop sequence; harmless there (nothing reads the raw reason) but could be unified.