Conversation
…ing turns on egress The /anthropic/v1/messages egress defaulted response.completed to stop_reason end_turn when the Bifrost StopReason was nil, even when the output carried function_call items. Anthropic SDK consumers that branch on stop_reason == "tool_use" missed tool calls when routing to non-Anthropic backends. Stop-reason inference is now shared between the streaming (message_delta) and non-streaming conversions: explicit stop reason wins, function_call output infers tool_use, else end_turn. Affected packages: - core/providers/anthropic/responses.go Fixes maximhq#4065 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR changes Anthropic stop-reason derivation for streaming and non-streaming response conversion. It adds shared inference logic for ChangesStop reason inference fix
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies" Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/providers/anthropic/responses.go`:
- Around line 3541-3545: The helper bifrostResponsesOutputHasFunctionCall is
incorrectly treating all ResponsesMessageTypeFunctionCall items as tool calls,
even when they are reasoning-only. Update this function to ignore function_call
messages that have ResponsesReasoning set, matching the nearby streaming
conversion logic, so only real tool-use items cause a tool-use stop_reason.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1b228e3f-9200-43d8-97cd-73c422e0b47e
📒 Files selected for processing (2)
core/providers/anthropic/compaction_test.gocore/providers/anthropic/responses.go
… function_call items Addresses review on PR maximhq#4900: reasoning-only items can carry the function_call type but convert to thinking blocks, so they must not force stop_reason tool_use; also restores the explicit tool_calls-without-output mapping test case. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@coderabbitai review — the reasoning-only |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
gh pr view 4900 --repo maximhq/bifrost --json commits --jq '.commits[] | .oid + " " + .messageHeadline' | head -50
echo "---"
gh api repos/maximhq/bifrost/commits/dfd0878d6 --jq '.sha, .commit.message' 2>/dev/null || echo "commit not found directly"Length of output: 1067 🏁 Script executed: #!/bin/bash
set -euo pipefail
gh api repos/maximhq/bifrost/commits/dfd0878d68aa8be3b79d6e1641d5ac50172b848d --jq '.files[].filename'
echo "---diff---"
gh api repos/maximhq/bifrost/commits/dfd0878d68aa8be3b79d6e1641d5ac50172b848d --jq '.files[].patch' 2>/dev/null | head -150Length of output: 2069
✅ Action performedReview finished.
|
244a01d to
ce1b2a6
Compare
Problem
When Bifrost's Anthropic-compatible ingress (
/anthropic/v1/messages) routes to a non-Anthropic backend (e.g. Azure OpenAI), a tool-calling turn emits a correcttool_usecontent block but the terminalmessage_delta.delta.stop_reasonis"end_turn"instead of"tool_use". Anthropic SDK consumers that dispatch tools onstop_reason == "tool_use"(the documented signal) fail to detect the tool call.Root cause
The Anthropic Responses streaming egress converter defaulted
response.completedtostop_reason: "end_turn"unlessBifrostResponsesResponse.StopReasonwas explicitly set. OpenAI/Azure Responses-style completed payloads can carryfunction_calloutput items with no Bifrost stop reason — the converter had enough information to know the turn requested a tool, but didn't infer"tool_use".Fix
Centralized Anthropic stop-reason inference for Responses egress (
inferAnthropicStopReasonFromBifrostResponse), used by both the non-streaming conversion and the streamingresponse.completed→message_deltaconversion:"tool_calls"→"tool_use", etc. via the existing mapping table);function_calloutput items ⇒"tool_use";tool_usecontent blocks ⇒"tool_use"(existing non-streaming inference, kept);"end_turn".Testing
tool_calls+ function-call output ⇒tool_use).TestToAnthropicResponsesStreamResponse_CompletedWithFunctionCallInfersToolUseStopReasoncovering the reported streaming case:response.completed, nilStopReason, function-call output ⇒message_deltawithstop_reason: "tool_use".go build ./...,go vet ./providers/anthropic/,go test -count=1 ./providers/anthropic/(core, cgo enabled) — all pass.Fixes #4065