Skip to content

fix: bedrock chat converter reasoning messages closes #3688 - #3690

Merged
akshaydeo merged 1 commit into
devfrom
05-22-fix_bedrock_chat_converter_reasoning_messages_closes_3688
May 25, 2026
Merged

fix: bedrock chat converter reasoning messages closes #3688#3690
akshaydeo merged 1 commit into
devfrom
05-22-fix_bedrock_chat_converter_reasoning_messages_closes_3688

Conversation

@TejasGhatte

@TejasGhatte TejasGhatte commented May 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

When constructing Bedrock messages for assistant turns that include reasoning details alongside tool calls, the reasoning content blocks were being appended after text and tool-use blocks. Bedrock requires reasoning blocks to appear first in the content array, so this ordering caused malformed requests during multi-turn conversations involving extended thinking and tool use.

Changes

  • Reordered content block assembly in convertMessage so that reasoning blocks are always prepended before text/image content and tool-use blocks.
  • Added a test case AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst that verifies the first content block is a reasoning block and that tool-use blocks follow it.

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

go test ./core/providers/bedrock/... -run TestMultiTurnReasoningContentPassthrough

The new subtest AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst should pass, confirming that the reasoning block is the first element in the assembled content array and that a tool-use block appears after it.

Breaking changes

  • Yes
  • No

Related issues

Security considerations

No security implications.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@CLAassistant

CLAassistant commented May 22, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


tejas ghatte seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Fixed ordering of message components when processing assistant messages with reasoning details and tool interactions, ensuring reasoning appears before tool use in converted requests.
  • Tests

    • Added test coverage validating correct handling and ordering of assistant messages that include both reasoning details and tool calls.

Walkthrough

Reorders Bedrock content block assembly so assistant reasoning details are emitted before text/image content and tool calls, and adds a test ensuring reasoning blocks appear first and tool-use blocks appear later.

Changes

Reasoning-First Content Block Ordering

Layer / File(s) Summary
Reorder content block assembly in convertMessage
core/providers/bedrock/utils.go
Restructured convertMessage to append reasoning details before converting msg.Content (text/image blocks) and to append assistant tool calls last, changing the final contentBlocks ordering.
Test reasoning-first content block ordering
core/providers/bedrock/bedrock_test.go
Adds a subtest that builds an assistant message with both ReasoningDetails and ToolCalls, converts it to Bedrock requests, and asserts reasoning content is at index 0 with tool-use blocks appearing later and at least three blocks total.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • maximhq/bifrost#3584: Both PRs adjust reasoning block ordering relative to tool calls during message conversion to ensure reasoning details are emitted before tool-call expansion.

Suggested reviewers

  • akshaydeo
  • danpiths

Poem

🐰 Upon the code-path I did hop,

Reasoning first, then tools will drop,
A test to prove the order true,
Blocks aligned — a tidy view,
Hoppity-hop, the build is through!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: reordering Bedrock chat converter to handle reasoning messages correctly, and references the issue being closed.
Description check ✅ Passed The description covers all essential sections: summary of the problem, changes made, type of change, affected areas, testing instructions, breaking changes, and checklist items. Most required elements are present and well-documented.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 05-22-fix_bedrock_chat_converter_reasoning_messages_closes_3688

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"


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@TejasGhatte
TejasGhatte marked this pull request as ready for review May 22, 2026 09:21
@coderabbitai
coderabbitai Bot requested review from akshaydeo and danpiths May 22, 2026 09:22
@greptile-apps

greptile-apps Bot commented May 22, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

The change is a targeted reordering of three content-block append operations within a single function, with no new logic introduced and a focused test covering the fixed scenario.

The fix is minimal and correct — it moves the reasoning-block loop before the existing text/image and tool-call loops without altering any conversion logic. The added test directly exercises the previously broken code path, and all other paths (no reasoning, no tool calls, non-assistant roles) are unaffected.

No files require special attention.

Important Files Changed

Filename Overview
core/providers/bedrock/utils.go Reorders content block assembly in convertMessage so reasoning blocks are prepended before text/image and tool-use blocks, fixing malformed requests to Bedrock when extended thinking and tool calls appear in the same assistant turn.
core/providers/bedrock/bedrock_test.go Adds AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst subtest that verifies the reasoning block is the first element in the assembled content array and a tool-use block follows it.

Reviews (2): Last reviewed commit: "fix: bedrock chat converter reasoning me..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/bedrock/bedrock_test.go`:
- Around line 3980-3988: The current test only checks a tool_use exists after
the first block slice, but we must ensure the first tool_use appears after all
text/image blocks; compute the index of the first tool_use in
assistantMsg.Content and the maximum index of any content block that is a text
or image (e.g., where block.Text != nil or block.Image != nil), then assert that
firstToolUseIndex > maxTextImageIndex; update the test around
assistantMsg.Content and foundToolUse to use these index comparisons so the
assertion enforces "reasoning/text/image blocks before any tool_use".
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2dc3df82-51fc-4676-ba94-bbb51ecd8e5e

📥 Commits

Reviewing files that changed from the base of the PR and between 78376b2 and 931d728.

📒 Files selected for processing (2)
  • core/providers/bedrock/bedrock_test.go
  • core/providers/bedrock/utils.go

Comment thread core/providers/bedrock/bedrock_test.go
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 22, 2026
@akshaydeo
akshaydeo dismissed coderabbitai[bot]’s stale review May 22, 2026 15:16

The merge-base changed after approval.

Copy link
Copy Markdown
Collaborator

I think changelogs are not relevant @TejasGhatte

@TejasGhatte
TejasGhatte force-pushed the 05-22-fix_bedrock_chat_converter_reasoning_messages_closes_3688 branch from 931d728 to faf243e Compare May 25, 2026 08:46

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
core/providers/bedrock/bedrock_test.go (1)

3980-3988: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Strengthen ordering assertion: enforce tool-use comes after all non-tool blocks.

Line 3980 currently only proves tool_use appears after reasoning. It still passes for reasoning -> tool_use -> text, which breaks the “tool calls last” contract.

Suggested test tightening
-		// tool_use must appear after reasoning
-		var foundToolUse bool
-		for _, block := range assistantMsg.Content[1:] {
-			if block.ToolUse != nil {
-				foundToolUse = true
-				break
-			}
-		}
-		assert.True(t, foundToolUse, "tool_use block must appear after reasoning block")
+		// tool_use must appear after all non-tool blocks (reasoning/text/image/document)
+		firstToolUseIdx := -1
+		lastNonToolIdx := -1
+		for i, block := range assistantMsg.Content {
+			if block.ToolUse != nil && firstToolUseIdx == -1 {
+				firstToolUseIdx = i
+			}
+			if block.ReasoningContent != nil || block.Text != nil || block.Image != nil || block.Document != nil {
+				lastNonToolIdx = i
+			}
+		}
+		require.NotEqual(t, -1, firstToolUseIdx, "expected at least one tool_use block")
+		assert.Greater(t, firstToolUseIdx, lastNonToolIdx, "tool_use blocks must come after reasoning/text/image/document blocks")
🤖 Prompt for 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.

In `@core/providers/bedrock/bedrock_test.go` around lines 3980 - 3988, The test
currently only checks that some block with ToolUse appears after the first
content block; update the assertion to ensure all tool-use blocks come after
every non-tool block: scan assistantMsg.Content to find the index of the first
ToolUse block (or the smallest index where block.ToolUse != nil) and the index
of the last non-tool block (largest index where block.ToolUse == nil), then
assert firstToolIndex > lastNonToolIndex; reference assistantMsg.Content,
block.ToolUse and the foundToolUse logic (replace or extend the foundToolUse
loop) so the test fails if any non-tool block appears after a tool-use block.
🤖 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.

Duplicate comments:
In `@core/providers/bedrock/bedrock_test.go`:
- Around line 3980-3988: The test currently only checks that some block with
ToolUse appears after the first content block; update the assertion to ensure
all tool-use blocks come after every non-tool block: scan assistantMsg.Content
to find the index of the first ToolUse block (or the smallest index where
block.ToolUse != nil) and the index of the last non-tool block (largest index
where block.ToolUse == nil), then assert firstToolIndex > lastNonToolIndex;
reference assistantMsg.Content, block.ToolUse and the foundToolUse logic
(replace or extend the foundToolUse loop) so the test fails if any non-tool
block appears after a tool-use block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b162b20d-b5bb-49c9-8f72-299c35a548e6

📥 Commits

Reviewing files that changed from the base of the PR and between 931d728 and faf243e.

📒 Files selected for processing (2)
  • core/providers/bedrock/bedrock_test.go
  • core/providers/bedrock/utils.go

akshaydeo commented May 25, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • May 25, 9:16 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 25, 9:17 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo merged commit 4a5fa57 into dev May 25, 2026
14 of 15 checks passed
@akshaydeo
akshaydeo deleted the 05-22-fix_bedrock_chat_converter_reasoning_messages_closes_3688 branch May 25, 2026 09:17
akshaydeo pushed a commit that referenced this pull request May 26, 2026
## Summary

When constructing Bedrock messages for assistant turns that include reasoning details alongside tool calls, the reasoning content blocks were being appended after text and tool-use blocks. Bedrock requires reasoning blocks to appear first in the content array, so this ordering caused malformed requests during multi-turn conversations involving extended thinking and tool use.

## Changes

- Reordered content block assembly in `convertMessage` so that reasoning blocks are always prepended before text/image content and tool-use blocks.
- Added a test case `AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst` that verifies the first content block is a reasoning block and that tool-use blocks follow it.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [x] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./core/providers/bedrock/... -run TestMultiTurnReasoningContentPassthrough
```

The new subtest `AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst` should pass, confirming that the reasoning block is the first element in the assembled content array and that a tool-use block appears after it.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

No security implications.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
@akshaydeo akshaydeo mentioned this pull request May 26, 2026
akshaydeo added a commit that referenced this pull request May 26, 2026
## ✨ Features

- **Azure v1 API Migration** — Migrated Azure provider to the v1 API:
removed the `api-version` query parameter and the
`/openai/deployments/{model}/...` URL pattern in favor of
`/openai/v1/{operation}`; the `api_version` field has been dropped from
`AzureKeyConfig` (#3661, #3756)
- **EnvVar Support for OTEL & Prometheus Configs** — `CollectorURL`,
`MetricsEndpoint`, headers, push gateway URL, and basic auth credentials
can now be sourced from environment variables (e.g.,
`env.OTEL_COLLECTOR_URL`); added a new `ConfigMarshallerPlugin`
interface that lets plugins control storage/redaction round-trips
(#3651)
- **OTel Extra Header Forwarding** — `x-bf-eh-*` extra headers forwarded
to upstream providers are now also emitted on the request span under
`gen_ai.request.extra_header.*` for end-to-end tracing (#3730)
- **OTel Semantic Conventions** — Aligned OTel attribute keys with the
OpenTelemetry GenAI spec (canonical `gen_ai.*` and new `bifrost.*`
attributes); legacy attributes are retained in parallel to avoid
breaking existing dashboards (#3732)
- **VK Quota with Provider Configs** — `GetVirtualKeyQuotaByValue` and
the `getVirtualKeyQuota` HTTP response now include `provider_configs`
with their budgets and rate limits (#3721)
- **MCP Temp Token Non-Auth Toggle** — Added
`mcp_enable_temp_token_auth` client config flag to gate short-lived MCP
token minting for non-authenticated users (#3720)
- **Responses Stream in JSON Parser** — `jsonparser` plugin now handles
OpenAI Responses API streaming (`ResponsesStreamRequest`) in addition to
chat completions (#3749)
- **Session API Rework** — Logout now calls both the password-based
session logout and OAuth logout endpoints and resets all RTK Query cache
state (#3698)

## 🐞 Fixed

- **Streaming Latency for Observability** — Deferred root span
termination to the trace completer callback for streaming requests so
request latency is no longer inflated by header-flush time (#3762)
- **Stream Cancellation Race** — Set `BifrostContextKeyConnectionClosed`
before closing the stream and short-circuit `idleTimeoutReader.Read`
when the connection is already closed to avoid panics and hangs on
cancellation (#3733)
- **Bedrock Cache Points** — Strip cache points from Bedrock requests
for models that do not support prompt caching (e.g., GLM, Llama) to
avoid Converse API errors (#3754)
- **Bedrock Empty Text Blocks** — Skip empty/nil text blocks during
Bedrock response conversion to avoid invalid messages (#3747)
- **Bedrock Reasoning + Tools** — Preserve reasoning content blocks on
assistant turns that also contain tool calls in the Bedrock chat
converter (#3690)
- **Bedrock Search Content & Video** — Restored search content and video
parts that were being dropped from Bedrock-native passthrough requests
(#3729)
- **Structured Output Stop Reason** — Fixed an incorrect `tool_calls`
finish reason when structured output is combined with extended-thinking
tools (#3685)
- **Gemini Tool Schema Passthrough** — Forward full tool parameter
schemas via `parametersJsonSchema` instead of the lossy `parameters`
form; corrected tool response role to `user`; resolved structured output
+ tools conflict (#3761)
- **Anthropic Stop Reason & Tool Versions** — Normalized stop reason
mapping (`end_turn` to `stop`, `tool_use` to `tool_calls`, `max_tokens`
to `length`) and upgraded `text_editor_20250124`/`str_replace_editor` to
`text_editor_20250728` for computer-use tools (#3761)
- **Azure Endpoint Redaction** — Fixed a panic when
`AzureKeyConfig.Endpoint` is a literal value rather than an env
reference (#3761)
- **Auth Middleware Path Match** — Match temp-token auth middleware
whitelist against the request path only, not the full URI with query
parameters (#3737)
- **Governance Blocked Models UI** — Restored the missing Blocked Models
create/edit UI in the VK provider config sheet (#3750)
- **Logging Plugin Cleanup Drain** — Fixed a shutdown race where
`batchWriter` could drop in-flight log entries; `Cleanup` now drains
both the recovered batch and remaining queue within a 30-second budget
(#3717)
- **Model Rankings Empty Entries** — Excluded entries with empty `model`
values from model rankings matview queries so blank rows no longer
surface in the UI (#3758)
- **User Filter Duplicates** — Recreated `mv_filter_users` matview to
require non-empty `user_name`, eliminating duplicate filter dropdown
entries (#3764)
- **User Filter Display Name** — Use `user_name` instead of `user_id` as
the display label for users in logging filters (#3691)
- **Large Numeric ID Precision** — Preserve large numeric IDs in URL
search params by skipping JSON parsing for plain strings (#3692)

## 🔧 Refactors & Chores

- **Error Propagation for GetAvailable\* APIs** — `GetAvailable*`
methods on `LoggerPlugin`/`LogManager` now return wrapped errors instead
of silently logging and returning empty slices (#3759)
- **Governance Blocklist Matching** — Use `slices.Contains` for VK
blocked-model matching for clearer code with identical semantics (#3727)
- **Exported `ResolvePeriod`** — Renamed `resolvePeriod` to
`ResolvePeriod` so external packages can reuse the period parsing
(#3763)

## 📚 Docs

- **OTEL Env Var Documentation** — Documented `env.VAR_NAME` support for
`collector_url`, `metrics_endpoint`, and headers in OTEL/Prometheus
plugin docs
- **OTEL OSS Features & Examples** — Added OTEL documentation to the OSS
features list with usage examples (#3731)
- **Anthropic Auth Recommendation** — Recommend `ANTHROPIC_AUTH_TOKEN`
over `ANTHROPIC_CUSTOM_HEADERS` for Claude Code authentication (#3686)
@akshaydeo akshaydeo mentioned this pull request May 27, 2026
18 tasks
akshaydeo added a commit that referenced this pull request May 27, 2026
## Summary

This PR releases Bifrost OSS `v1.5.5` and Enterprise `v1.4.4`, bumping all module pins from `v1.5.12`/`v1.3.12` to `v1.5.13`/`v1.3.13` across core, framework, and all plugins. It also hardens the Docker manifest shell scripts, expands CI egress allowlists, and updates documentation to reflect the new SCIM-based user provisioning feature.

## Changes

- **Module version bumps**: All `go.mod`/`go.sum` files updated from `core v1.5.12` → `v1.5.13`, `framework v1.3.12` → `v1.3.13`, and all plugin versions incremented accordingly (`compat`, `governance`, `jsonparser`, `logging`, `maxim`, `mocker`, `otel`, `prompts`, `semanticcache`, `telemetry`).
- **Docker manifest scripts**: Added `#!/usr/bin/env bash` shebang and `set -euo pipefail` to `create-docker-manifest.sh` and `create-docker-manifest-ubi9.sh`; quoted all variable expansions and switched `jq -r` to `jq -er` to fail on null digests.
- **CI egress allowlist**: Added `production.cloudfront.docker.com:443` to Docker-related job allowlists, and added `_https._tcp.dl.google.com:443` and `motd.ubuntu.com:443` to the Ubuntu package job allowlist.
- **Changelog files**: Cleared per-module `changelog.md` files (content moved into the new versioned docs). Added `docs/changelogs/v1.5.5.mdx` and `docs/changelogs/ent-v1.4.4.mdx` with full release notes, and registered both in `docs/docs.json`.
- **Documentation**: Replaced the SSO Integration link with a User Provisioning (SCIM) link in both `README.md` and `transports/README.md`.
- **Enterprise v1.4.4 highlights** (documented): Kafka and Google Cloud Pub/Sub observability sinks, chunked streaming with a 100 MB inter-node message ceiling, BigQuery custom labels via env vars using the new `ConfigMarshallerPlugin` interface, temporary access token expiry extensions, and a multi-node cluster integration harness.
- **OSS v1.5.5 highlights** (documented): Azure v1 API migration, env-var support for OTel/Prometheus configs, OTel extra-header forwarding and semantic-convention alignment, virtual key quota including provider configs, Responses API streaming in `jsonparser`, and a batch of Bedrock, Gemini, Anthropic, Azure, and logging plugin fixes.

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [x] Documentation
- [x] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [x] Providers/Integrations
- [x] Plugins
- [ ] UI (React)
- [x] Docs

## How to test

```sh
# Core/Transports
go version
go test ./...

# Verify Docker manifest scripts exit on error
bash -n .github/workflows/scripts/create-docker-manifest.sh
bash -n .github/workflows/scripts/create-docker-manifest-ubi9.sh
```

Validate that the new changelog pages (`changelogs/v1.5.5` and `changelogs/ent-v1.4.4`) render correctly in the docs site.

## Screenshots/Recordings

N/A

## Breaking changes

- [x] Yes
- [ ] No

The Azure provider no longer accepts `api_version` in `AzureKeyConfig` and has migrated to the `/openai/v1/{operation}` URL pattern. See the [v1.4.0 Migration Guide](https://docs.getbifrost.ai/enterprise/migration-guides/v1.4.0) for full details.

## Related issues

#3661, #3756, #3651, #3730, #3732, #3754, #3747, #3690, #3729, #3685, #3733, #3761, #3735, #3721, #3720, #3749, #3698, #3762, #3750, #3727, #3717, #3759, #3758, #3764, #3691, #3692, #3737, #3763

## Security considerations

- The `ConfigMarshallerPlugin` interface redacts secrets (OTel collector URLs, Prometheus push gateway credentials, BigQuery labels) at config storage time and rehydrates them at load time, preventing plaintext secret persistence.
- Docker manifest scripts now use `set -euo pipefail`, preventing silent failures that could result in malformed or missing image manifests being pushed.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
akhsaul pushed a commit to akhsaul/bifrost that referenced this pull request Aug 27, 2026
…aximhq#3690)

## Summary

When constructing Bedrock messages for assistant turns that include reasoning details alongside tool calls, the reasoning content blocks were being appended after text and tool-use blocks. Bedrock requires reasoning blocks to appear first in the content array, so this ordering caused malformed requests during multi-turn conversations involving extended thinking and tool use.

## Changes

- Reordered content block assembly in `convertMessage` so that reasoning blocks are always prepended before text/image content and tool-use blocks.
- Added a test case `AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst` that verifies the first content block is a reasoning block and that tool-use blocks follow it.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [x] Providers/Integrations
- [ ] Plugins
- [ ] UI (React)
- [ ] Docs

## How to test

```sh
go test ./core/providers/bedrock/... -run TestMultiTurnReasoningContentPassthrough
```

The new subtest `AssistantMessage_WithReasoningAndToolCalls_ReasoningComesFirst` should pass, confirming that the reasoning block is the first element in the assembled content array and that a tool-use block appears after it.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

No security implications.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable
akhsaul pushed a commit to akhsaul/bifrost that referenced this pull request Aug 27, 2026
## ✨ Features

- **Azure v1 API Migration** — Migrated Azure provider to the v1 API:
removed the `api-version` query parameter and the
`/openai/deployments/{model}/...` URL pattern in favor of
`/openai/v1/{operation}`; the `api_version` field has been dropped from
`AzureKeyConfig` (maximhq#3661, maximhq#3756)
- **EnvVar Support for OTEL & Prometheus Configs** — `CollectorURL`,
`MetricsEndpoint`, headers, push gateway URL, and basic auth credentials
can now be sourced from environment variables (e.g.,
`env.OTEL_COLLECTOR_URL`); added a new `ConfigMarshallerPlugin`
interface that lets plugins control storage/redaction round-trips
(maximhq#3651)
- **OTel Extra Header Forwarding** — `x-bf-eh-*` extra headers forwarded
to upstream providers are now also emitted on the request span under
`gen_ai.request.extra_header.*` for end-to-end tracing (maximhq#3730)
- **OTel Semantic Conventions** — Aligned OTel attribute keys with the
OpenTelemetry GenAI spec (canonical `gen_ai.*` and new `bifrost.*`
attributes); legacy attributes are retained in parallel to avoid
breaking existing dashboards (maximhq#3732)
- **VK Quota with Provider Configs** — `GetVirtualKeyQuotaByValue` and
the `getVirtualKeyQuota` HTTP response now include `provider_configs`
with their budgets and rate limits (maximhq#3721)
- **MCP Temp Token Non-Auth Toggle** — Added
`mcp_enable_temp_token_auth` client config flag to gate short-lived MCP
token minting for non-authenticated users (maximhq#3720)
- **Responses Stream in JSON Parser** — `jsonparser` plugin now handles
OpenAI Responses API streaming (`ResponsesStreamRequest`) in addition to
chat completions (maximhq#3749)
- **Session API Rework** — Logout now calls both the password-based
session logout and OAuth logout endpoints and resets all RTK Query cache
state (maximhq#3698)

## 🐞 Fixed

- **Streaming Latency for Observability** — Deferred root span
termination to the trace completer callback for streaming requests so
request latency is no longer inflated by header-flush time (maximhq#3762)
- **Stream Cancellation Race** — Set `BifrostContextKeyConnectionClosed`
before closing the stream and short-circuit `idleTimeoutReader.Read`
when the connection is already closed to avoid panics and hangs on
cancellation (maximhq#3733)
- **Bedrock Cache Points** — Strip cache points from Bedrock requests
for models that do not support prompt caching (e.g., GLM, Llama) to
avoid Converse API errors (maximhq#3754)
- **Bedrock Empty Text Blocks** — Skip empty/nil text blocks during
Bedrock response conversion to avoid invalid messages (maximhq#3747)
- **Bedrock Reasoning + Tools** — Preserve reasoning content blocks on
assistant turns that also contain tool calls in the Bedrock chat
converter (maximhq#3690)
- **Bedrock Search Content & Video** — Restored search content and video
parts that were being dropped from Bedrock-native passthrough requests
(maximhq#3729)
- **Structured Output Stop Reason** — Fixed an incorrect `tool_calls`
finish reason when structured output is combined with extended-thinking
tools (maximhq#3685)
- **Gemini Tool Schema Passthrough** — Forward full tool parameter
schemas via `parametersJsonSchema` instead of the lossy `parameters`
form; corrected tool response role to `user`; resolved structured output
+ tools conflict (maximhq#3761)
- **Anthropic Stop Reason & Tool Versions** — Normalized stop reason
mapping (`end_turn` to `stop`, `tool_use` to `tool_calls`, `max_tokens`
to `length`) and upgraded `text_editor_20250124`/`str_replace_editor` to
`text_editor_20250728` for computer-use tools (maximhq#3761)
- **Azure Endpoint Redaction** — Fixed a panic when
`AzureKeyConfig.Endpoint` is a literal value rather than an env
reference (maximhq#3761)
- **Auth Middleware Path Match** — Match temp-token auth middleware
whitelist against the request path only, not the full URI with query
parameters (maximhq#3737)
- **Governance Blocked Models UI** — Restored the missing Blocked Models
create/edit UI in the VK provider config sheet (maximhq#3750)
- **Logging Plugin Cleanup Drain** — Fixed a shutdown race where
`batchWriter` could drop in-flight log entries; `Cleanup` now drains
both the recovered batch and remaining queue within a 30-second budget
(maximhq#3717)
- **Model Rankings Empty Entries** — Excluded entries with empty `model`
values from model rankings matview queries so blank rows no longer
surface in the UI (maximhq#3758)
- **User Filter Duplicates** — Recreated `mv_filter_users` matview to
require non-empty `user_name`, eliminating duplicate filter dropdown
entries (maximhq#3764)
- **User Filter Display Name** — Use `user_name` instead of `user_id` as
the display label for users in logging filters (maximhq#3691)
- **Large Numeric ID Precision** — Preserve large numeric IDs in URL
search params by skipping JSON parsing for plain strings (maximhq#3692)

## 🔧 Refactors & Chores

- **Error Propagation for GetAvailable\* APIs** — `GetAvailable*`
methods on `LoggerPlugin`/`LogManager` now return wrapped errors instead
of silently logging and returning empty slices (maximhq#3759)
- **Governance Blocklist Matching** — Use `slices.Contains` for VK
blocked-model matching for clearer code with identical semantics (maximhq#3727)
- **Exported `ResolvePeriod`** — Renamed `resolvePeriod` to
`ResolvePeriod` so external packages can reuse the period parsing
(maximhq#3763)

## 📚 Docs

- **OTEL Env Var Documentation** — Documented `env.VAR_NAME` support for
`collector_url`, `metrics_endpoint`, and headers in OTEL/Prometheus
plugin docs
- **OTEL OSS Features & Examples** — Added OTEL documentation to the OSS
features list with usage examples (maximhq#3731)
- **Anthropic Auth Recommendation** — Recommend `ANTHROPIC_AUTH_TOKEN`
over `ANTHROPIC_CUSTOM_HEADERS` for Claude Code authentication (maximhq#3686)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants