Skip to content

feat: bedrock system tools - #3435

Merged
akshaydeo merged 1 commit into
devfrom
05-12-feat_bedrock_system_tools
May 15, 2026
Merged

feat: bedrock system tools#3435
akshaydeo merged 1 commit into
devfrom
05-12-feat_bedrock_system_tools

Conversation

@TejasGhatte

@TejasGhatte TejasGhatte commented May 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds support for Amazon Nova system tools (nova_grounding and nova_code_interpreter) through the Bedrock Converse and Converse-Stream paths. These are AWS-managed tools that the model invokes and executes automatically within a single turn — no client-side tool loop is required. The changes wire up bidirectional translation between Bedrock's native system tool format and Bifrost's neutral schema (web_search and code_interpreter), covering both non-streaming and streaming response handling.

Changes

  • nova_grounding support: Enables WebSearch: true for the Bedrock provider feature map. Translates nova_groundingweb_search in tool config conversion. Handles citation deltas in the streaming path, emitting them as url_citation annotations. Maps citationsContent blocks in non-streaming responses to url_citation annotations on text content blocks.

  • nova_code_interpreter support: Translates nova_code_interpretercode_interpreter in tool config conversion. Introduces CodeInterpreterIndices tracking in BedrockResponsesStreamState to distinguish code interpreter tool calls from regular function calls during streaming. Emits code_interpreter_call.in_progress, code_interpreter_call.code_delta, code_interpreter_call.code.done, and code_interpreter_call.completed stream events instead of the function-call event sequence. In non-streaming responses, merges the toolUse (code) and paired nova_code_interpreter_result toolResult blocks into a single code_interpreter_call output item with execution logs.

  • Stop reason fix: Server-managed tools resolve their own toolResult in the same turn. The stop reason derivation now pre-scans for matched toolUse/toolResult pairs so that hasToolUse stays false for self-resolving tools, preserving the original end_turn stop reason rather than incorrectly emitting tool_use.

  • New Bedrock types: Added BedrockSystemTool, BedrockSystemToolType, BedrockCitation, BedrockCitationLocation, BedrockWebCitationLocation, BedrockCitationsContent, and a Type field on BedrockToolResult to support nova_code_interpreter_result identification.

  • Integration tests: Added TestNovaSystemTools with four test cases (50–53) covering nova_grounding and nova_code_interpreter in both non-streaming and streaming modes via the Bedrock Converse API.

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/...
go test ./core/providers/anthropic/...

For integration tests against a live Bedrock endpoint with Nova model access:

cd tests/integrations/python
pip install -r requirements.txt
pytest tests/test_bedrock.py::TestNovaSystemTools -v

Test cases require AWS credentials with access to us.amazon.nova-2-lite-v1:0 and the nova_grounding / nova_code_interpreter system tools enabled in your account. Tests will be skipped automatically if the tools are unavailable or the API key is not configured.

Breaking changes

  • Yes
  • No

Related issues

Security considerations

Nova system tools are fully AWS-managed and execute in AWS infrastructure. No user-supplied code or credentials are passed through Bifrost beyond the standard Bedrock API call. Citation URLs returned by nova_grounding are surfaced as annotations and are not fetched or processed by Bifrost.

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

@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Bedrock provider enables web search and Amazon Nova system tools (code interpreter and grounding) with citation support.
    • Streaming now preserves Nova tool events, incremental code/snippet deltas, and streamed citation annotations; tool lifecycles and stop-reason handling improved.
  • Tests

    • Added integration tests validating Nova system tools in both streaming and non-streaming modes.

Walkthrough

Adds Bedrock Nova system-tool support: new Bedrock types for citations and system tools, streaming-state tracking and event branching for nova_code_interpreter and nova_grounding, Bedrock↔Bifrost tool conversion and message buffering, Anthropic Bedrock WebSearch flag, a Nova2 model helper, and integration tests.

Changes

Nova system tools integration

Layer / File(s) Summary
Nova system tools data model
core/providers/bedrock/types.go
Adds CitationsContent to BedrockContentBlock, optional Type in BedrockToolResult, optional SystemTool in BedrockTool, new BedrockSystemToolType/constants and BedrockSystemTool struct, streaming Citation field on deltas, and citation model types (BedrockWebCitationLocation, BedrockCitationLocation, BedrockCitation, BedrockCitationsContent).
Streaming state infrastructure
core/providers/bedrock/responses.go
BedrockResponsesStreamState gains CodeInterpreterIndices map[int]bool, NovaGroundingIndices map[int]bool, NovaGroundingCitations map[int][]schemas.ResponsesWebSearchToolCallActionSearchSource, and AnnotationIndices map[int]int; pool New/acquire/flush initialize and reset these maps.
Streaming event generation & finalization
core/providers/bedrock/responses.go
Tool-call start/close and delta handling branch for nova_code_interpreter vs regular tools: emits code_interpreter_call.in_progress, code_interpreter_call.code_delta, code_interpreter_call.code.done + code_interpreter_call.completed; citation deltas converted to url_citation annotation events; adds helper emitters and updates FinalizeBedrockStream.
Tool conversion & message conversion
core/providers/bedrock/responses.go
Maps nova_groundingweb_search and nova_code_interpretercode_interpreter; pre-scans nova_code_interpreter_result blocks and pairs them with tool uses; buffers server-managed toolUse+toolResult blocks to prepend to assistant messages; maps grounding citations to url_citation annotations; converts nova_code_interpreter tool uses into completed code_interpreter_call messages with parsed code and paired outputs; updates stop-reason/tool-use detection; reconstructs Bedrock citationsContent from url_citation annotations.
WebSearch provider feature flag
core/providers/anthropic/types.go
Sets ProviderFeatures[schemas.Bedrock].WebSearch = true.
Nova2 model helper
core/schemas/utils.go
Adds IsNova2Model(model string) bool to detect nova-2 variants containing lite or sonic.
Nova system tools integration tests
tests/integrations/python/tests/test_bedrock.py
Adds TestNovaSystemTools with four tests covering nova_grounding and nova_code_interpreter in non-streaming and streaming modes, asserting response structure, tool evidence, valid stop reasons, and streamed deltas.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • maximhq/bifrost#3506: Modifies Bedrock stop-reason derivation and tool-use/IncompleteDetails mapping, related to updated stop-reason logic here.

Suggested reviewers

  • akshaydeo

Poem

A rabbit hops where Nova tools unwind,
Citations bloom and parsed code we find,
Streams whisper deltas, snippets in a line,
Grounding and interpreter stitch results divine,
Bifrost and Bedrock hum in sync. 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: bedrock system tools' clearly summarizes the main change—adding support for Amazon Nova system tools in Bedrock.
Description check ✅ Passed The PR description is comprehensive and follows the template structure, covering all major sections including Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, and Checklist.
Docstring Coverage ✅ Passed Docstring coverage is 95.00% which is sufficient. The required threshold is 80.00%.
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-12-feat_bedrock_system_tools

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.

TejasGhatte commented May 12, 2026

Copy link
Copy Markdown
Collaborator Author

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

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test Suite Available

This PR can be tested by a repository admin.

Run tests for PR #3435

@TejasGhatte
TejasGhatte marked this pull request as ready for review May 12, 2026 14:03
@CLAassistant

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.

@greptile-apps

greptile-apps Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 3/5

The core round-trip conversion and non-streaming paths look correct after the changes, but the streaming path for nova_grounding still emits a protocol-incorrect event type for tool-use input deltas, which was flagged in a previous review pass and remains unaddressed.

The nova_grounding toolUse delta handler falls through to the else branch (line 882-889) and emits function_call_arguments.delta on a web_search_call output item — wrong per the Responses API contract, and a spec-compliant streaming consumer may treat it as an error. This was flagged in a prior review cycle and is still present. The round-trip issues (silent drop of code_interpreter_call, unmatched nova_grounding toolUse) noted in the same cycle appear fixed. The overall feature is logically sound and the non-streaming path looks correct.

core/providers/bedrock/responses.go — the ToolUse delta branch around line 872 needs a state.NovaGroundingIndices[outputIndex] guard to suppress the spurious function_call_arguments.delta event for nova_grounding.

Important Files Changed

Filename Overview
core/providers/bedrock/responses.go Large change adding nova_grounding and nova_code_interpreter support across streaming and non-streaming paths; most round-trip issues from the earlier review are now addressed, but one streaming-path protocol violation remains unfixed (nova_grounding input deltas still emit function_call_arguments.delta instead of being suppressed).
core/providers/bedrock/types.go Adds BedrockSystemTool, citation types, and new constants; all look structurally correct and well-documented.
core/providers/anthropic/types.go Adds WebSearch and CodeExecution feature flags for the Bedrock provider; straightforward and consistent with the pattern used by other providers.
core/schemas/utils.go Adds IsNova2Model helper; the variant gating on "lite"/"sonic" may be overly restrictive for future Nova 2 tiers.
tests/integrations/python/tests/test_bedrock.py Adds four integration test cases (50-53) for nova_grounding and nova_code_interpreter across streaming and non-streaming modes; tests skip gracefully when the API key or tools are unavailable.

Reviews (8): Last reviewed commit: "feat: bedrock system tools" | Re-trigger Greptile

Comment thread core/providers/bedrock/responses.go Outdated
Comment thread core/providers/bedrock/responses.go Outdated
Comment thread core/providers/bedrock/responses.go

@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: 3

🧹 Nitpick comments (2)
core/providers/anthropic/types.go (1)

181-186: ⚡ Quick win

Update the Bedrock support note to match the new WebSearch: true flag.

The comment still says Bedrock does not support WebSearch, but Line 186 enables it. Please align the note to avoid future confusion/regressions.

Proposed comment-only fix
-	// Notably NOT supported per docs: MCP, Skills, FilesAPI, WebFetch,
-	// WebSearch, CodeExecution, FastMode, TaskBudgets, AdvisorTool,
+	// Notably NOT supported per docs: MCP, Skills, FilesAPI, WebFetch,
+	// CodeExecution, FastMode, TaskBudgets, AdvisorTool,
 	// InferenceGeo, RedactThinking, AdvancedToolUse (full), PromptCachingScope.
+	// WebSearch is enabled here for Bedrock Nova grounding tool support.
🤖 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/anthropic/types.go` around lines 181 - 186, The comment
describing Bedrock support is out of sync with the flag in schemas.Bedrock where
WebSearch is set to true; update the explanatory comment above schemas.Bedrock
to remove WebSearch from the "Notably NOT supported" list (or explicitly state
it is supported) so the prose matches the WebSearch: true entry and avoid future
confusion between the comment and the schemas.Bedrock configuration.
core/providers/bedrock/responses.go (1)

812-825: ⚡ Quick win

Partial JSON delta parsing will usually fail.

The code attempts to parse each streaming delta chunk as complete JSON to extract the code field. However, streaming deltas are typically partial JSON fragments (e.g., {"code": "pri without closing), so json.Unmarshal will fail on most chunks.

This means codeDelta will be empty for most delta events, and only the final chunk (if it happens to be valid JSON) will produce a non-empty delta. Consider accumulating the full JSON in ToolArgumentBuffers and only parsing when complete, or emitting raw deltas without attempting to extract the code field from partial chunks.

🤖 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/responses.go` around lines 812 - 825, The current
logic tries to json.Unmarshal partial streaming chunks from toolUseDelta.Input
to extract code (inside the state.CodeInterpreterIndices handling), which fails
for fragments; instead either append the raw chunk to the existing
ToolArgumentBuffers[outputIndex] and only attempt json.Unmarshal when the
accumulated buffer parses successfully, or skip parsing entirely and emit the
raw delta string (toolUseDelta.Input) as the Delta in
schemas.BifrostResponsesStreamResponse so every fragment is forwarded; update
the branch that constructs schemas.BifrostResponsesStreamResponse for
CodeInterpreterCallCodeDelta to use the buffered/accumulated value or the raw
chunk rather than attempting to unmarshal every partial chunk.
🤖 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/responses.go`:
- Around line 777-800: The annotationIndex is currently hardcoded to 0 for each
citation in the delta handling block, causing collisions when multiple citations
are emitted for the same output/content; add a counter in
BedrockResponsesStreamState (e.g., a map keyed by outputIndex+contentIndex or a
nested map like AnnotationIndexByOutputContent) to track the next annotation
index per output/content, use that counter instead of the hardcoded
annotationIndex, increment and persist the counter after emitting a citation
(update any places that create responses like the chunk.Delta.Citation handling
and ensure existing uses of ContentIndexToOutputIndex remain unchanged).

In `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 2969-2973: Replace the broad except Exception catch with a
specific except botocore.exceptions.ClientError and only call pytest.skip when
the caught ClientError's service error code (accessed via
e.response['Error']['Code']) matches explicit Bedrock validation/unsupported
codes (e.g., 'ValidationException', 'UnknownOperation', 'NotFound' or whatever
service codes your provider returns); otherwise re-raise the exception. Update
the four similar Nova test blocks (the except blocks shown) to use
botocore.exceptions.ClientError, inspect e.response['Error']['Code'] for allowed
skip codes, and call pytest.skip with the original error when matched,
re-raising for any other errors.
- Around line 3131-3139: The assertion currently allows passing when only a
"toolUse" block exists; change the check to require either non-empty synthesized
text or an explicit execution result by verifying presence of "toolResult" in
content_blocks. Update the variables/logic around has_tool_use/full_text to
instead compute has_tool_result = any("toolResult" in b for b in content_blocks)
and assert full_text or has_tool_result (and apply the same change to the
similar assertion later around the other block at 3141-3145), so the test fails
when execution/result synthesis is missing.

---

Nitpick comments:
In `@core/providers/anthropic/types.go`:
- Around line 181-186: The comment describing Bedrock support is out of sync
with the flag in schemas.Bedrock where WebSearch is set to true; update the
explanatory comment above schemas.Bedrock to remove WebSearch from the "Notably
NOT supported" list (or explicitly state it is supported) so the prose matches
the WebSearch: true entry and avoid future confusion between the comment and the
schemas.Bedrock configuration.

In `@core/providers/bedrock/responses.go`:
- Around line 812-825: The current logic tries to json.Unmarshal partial
streaming chunks from toolUseDelta.Input to extract code (inside the
state.CodeInterpreterIndices handling), which fails for fragments; instead
either append the raw chunk to the existing ToolArgumentBuffers[outputIndex] and
only attempt json.Unmarshal when the accumulated buffer parses successfully, or
skip parsing entirely and emit the raw delta string (toolUseDelta.Input) as the
Delta in schemas.BifrostResponsesStreamResponse so every fragment is forwarded;
update the branch that constructs schemas.BifrostResponsesStreamResponse for
CodeInterpreterCallCodeDelta to use the buffered/accumulated value or the raw
chunk rather than attempting to unmarshal every partial chunk.
🪄 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: 73524ccd-c6bd-41af-8314-b93ac12eb421

📥 Commits

Reviewing files that changed from the base of the PR and between aaca5c6 and 4b2ac3f.

📒 Files selected for processing (4)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • tests/integrations/python/tests/test_bedrock.py

Comment thread core/providers/bedrock/responses.go
Comment thread tests/integrations/python/tests/test_bedrock.py
Comment thread tests/integrations/python/tests/test_bedrock.py
@TejasGhatte
TejasGhatte force-pushed the 05-12-feat_bedrock_system_tools branch from 4b2ac3f to 3b40f1e Compare May 12, 2026 19:34

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/providers/bedrock/responses.go (1)

791-817: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Code delta extraction from JSON fragments will fail and emit empty values.

During streaming, each toolUseDelta.Input contains an incremental JSON fragment (e.g., {"co, de": ", print(), not a complete JSON object. The current code attempts to unmarshal each fragment individually as complete JSON, which fails silently (_ = json.Unmarshal), leaving codeChunk.Code empty for most/all deltas.

The final code.done event works correctly because it parses the accumulated buffer via emitCodeInterpreterDoneEvents, but intermediate code_delta events will emit empty strings.

Emit the raw delta like regular function calls do (line 811: &toolUseDelta.Input), allowing clients to accumulate fragments. The final code.done event provides the parsed code once the full buffer is available.

Proposed fix
 if state.CodeInterpreterIndices[outputIndex] {
-	// Extract the code field from the accumulated JSON delta
-	var codeChunk struct {
-		Code string `json:"code"`
-	}
-	_ = json.Unmarshal([]byte(toolUseDelta.Input), &codeChunk)
-	codeDelta := codeChunk.Code
+	// Emit raw delta — JSON fragments accumulate across chunks.
+	// Clients reconstruct code from deltas; code.done event provides final parsed code.
+	codeDelta := toolUseDelta.Input
 	response = &schemas.BifrostResponsesStreamResponse{
🤖 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/responses.go` around lines 791 - 817, The code
currently attempts to json.Unmarshal each incremental JSON fragment in
toolUseDelta.Input into codeChunk.Code (inside the
state.CodeInterpreterIndices[outputIndex] branch) which fails for partial
fragments; change this branch to emit the raw fragment just like the else
branch: set response.Type to
ResponsesStreamResponseTypeCodeInterpreterCallCodeDelta,
SequenceNumber/OutputIndex/ContentIndex as done, and set Delta to
&toolUseDelta.Input (removing the silent json.Unmarshal and codeChunk usage) so
clients can accumulate fragments; preserve the itemID assignment and the
existing return shape.
🤖 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 `@tests/integrations/python/tests/test_bedrock.py`:
- Line 3074: The assertion uses an unnecessary f-string for a literal message
(assert full_text, f"Expected non-empty streamed text from nova_grounding, got
empty"); remove the leading `f` so the assertion message is a normal
string—i.e., change the message to "Expected non-empty streamed text from
nova_grounding, got empty" where the `full_text` assertion is performed.

---

Outside diff comments:
In `@core/providers/bedrock/responses.go`:
- Around line 791-817: The code currently attempts to json.Unmarshal each
incremental JSON fragment in toolUseDelta.Input into codeChunk.Code (inside the
state.CodeInterpreterIndices[outputIndex] branch) which fails for partial
fragments; change this branch to emit the raw fragment just like the else
branch: set response.Type to
ResponsesStreamResponseTypeCodeInterpreterCallCodeDelta,
SequenceNumber/OutputIndex/ContentIndex as done, and set Delta to
&toolUseDelta.Input (removing the silent json.Unmarshal and codeChunk usage) so
clients can accumulate fragments; preserve the itemID assignment and the
existing return shape.
🪄 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: 243fbca8-d91c-4b7c-99cc-e94b2646264e

📥 Commits

Reviewing files that changed from the base of the PR and between 4b2ac3f and 3b40f1e.

📒 Files selected for processing (4)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • tests/integrations/python/tests/test_bedrock.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/providers/bedrock/types.go
  • core/providers/anthropic/types.go

Comment thread tests/integrations/python/tests/test_bedrock.py Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 13, 2026

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
core/providers/bedrock/responses.go (2)

2484-2556: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Gate inferred Nova system tools on the target model.

This helper now appends nova_grounding / nova_code_interpreter whenever those message types appear in history, but ensureResponsesToolConfigForConversation() runs even when bifrostReq.Model is not a Nova model. Replaying a web_search_call or code_interpreter_call history into another Bedrock family will synthesize an invalid systemTool config. Pass the target model into this inference path and only emit SystemTool entries for Nova models.

🤖 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/responses.go` around lines 2484 - 2556, The code
unconditionally sets hasNovaGrounding/hasNovaCodeInterpreter from message
history and later appends Nova system tools even when the target model isn't
Nova; update ensureResponsesToolConfigForConversation() (or the calling path
that builds tool inference) to accept the target model (bifrostReq.Model) and
gate the final appends: only append BedrockSystemTool entries for
BedrockSystemToolNovaGrounding and BedrockSystemToolNovaCodeInterpreter when the
provided model is a Nova model (use the existing model-check helper if available
or check Nova model name/prefix). Keep the message-scanning logic for
hasNovaGrounding/hasNovaCodeInterpreter but add a conditional around the two
blocks that append system tools so non-Nova models never receive those
SystemTool entries.

857-893: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Parse code deltas from the accumulated JSON buffer.

toolUseDelta.Input is just the latest JSON fragment, but code_interpreter_call.code_delta is derived from unmarshalling that fragment in isolation. Bedrock splits tool JSON arbitrarily, so most chunks won't decode and this path will emit empty or corrupted code deltas. Use state.ToolArgumentBuffers[outputIndex] as the parse source and track the last emitted code length so you only send the newly completed suffix.

🤖 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/responses.go` around lines 857 - 893, The current
handler unmarshals only the latest fragment (toolUseDelta.Input) which can be
partial; instead parse from the accumulated buffer
state.ToolArgumentBuffers[outputIndex] and keep a per-output "last emitted
length" marker (e.g. add or use state.ToolArgumentEmittedLengths[outputIndex])
so you only attempt to unmarshal complete JSON and emit the new suffix beyond
the last emitted length; for code interpreter calls (when
state.CodeInterpreterIndices[outputIndex] is true) repeatedly try to unmarshal
the buffer into the codeChunk struct, advance the emitted-length marker to the
successfully parsed code's end, set codeDelta to the newly completed suffix, and
construct the ResponsesStreamResponse with that delta (fall back to not emitting
if no new complete JSON is present); preserve existing behavior for function
call argument deltas when not enough JSON is available.
🧹 Nitpick comments (2)
tests/integrations/python/tests/test_bedrock.py (2)

2984-2995: ⚡ Quick win

Assert citation signal in non-streaming grounding responses.

This currently validates only text/keywords, so it can pass even if citation mapping regresses. Add a citation assertion (Bedrock citationsContent or mapped annotation equivalent) for the grounding path.

Suggested assertion hardening
         full_text = " ".join(b["text"] for b in content_blocks if b.get("text", "").strip())
         assert full_text, (
             f"Expected non-empty text in grounding response, got: {content_blocks}"
         )
+
+        # Grounding should surface at least one citation signal.
+        has_citation_signal = any(
+            b.get("citationsContent") or b.get("annotations") for b in content_blocks
+        )
+        assert has_citation_signal, (
+            f"Expected citation metadata in grounding response, got: {content_blocks}"
+        )

As per coding guidelines: always check the stack if there is one for the current PR ... see all changes in the light of the whole stack.

🤖 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 `@tests/integrations/python/tests/test_bedrock.py` around lines 2984 - 2995,
The test currently only checks full_text built from content_blocks and must also
assert that grounding responses include citation metadata; update the grounding
assertions around full_text/content_blocks (the nova_grounding path) to verify
Bedrock's citation field (e.g., check response["citationsContent"] or mapped
annotation equivalents within content_blocks) exists and is non-empty and/or
contains expected source identifiers, failing the test if no citation mapping is
present; reference the variables full_text and content_blocks and add the new
assertion directly after the existing text assertions so missing citations cause
test failure.

3052-3075: ⚡ Quick win

Track and validate citation deltas in streaming grounding test.

The stream assertion currently checks only text and stop. Given this stack adds citation-delta handling, add a check for citation deltas so this path is actually covered.

Suggested assertion hardening
         event_types = []
         text_parts = []
+        citation_deltas = []
         start_time = time.time()
         timeout = 60  # grounding may take longer due to web fetch
 
         for event in stream:
@@
             if "contentBlockDelta" in event:
                 delta = event["contentBlockDelta"].get("delta", {})
                 if "text" in delta and delta["text"]:
                     text_parts.append(delta["text"])
+                if delta.get("citation"):
+                    citation_deltas.append(delta["citation"])
@@
         full_text = "".join(text_parts)
         assert full_text, f"Expected non-empty streamed text from nova_grounding, got empty"
+        assert citation_deltas, "Expected at least one citation delta from nova_grounding stream"

As per coding guidelines: always check the stack if there is one for the current PR ... see all changes in the light of the whole stack.

🤖 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 `@tests/integrations/python/tests/test_bedrock.py` around lines 3052 - 3075,
The test loop currently only tracks "messageStart"/"messageStop" and text
deltas; add detection and tracking for citation deltas so the new citation-delta
streaming path is exercised: inside the for event in stream loop (where
event_types and text_parts are used) add a branch to detect citation deltas
(e.g., if "citationDelta" in event or if contentBlockDelta.delta contains a
citation field), append a marker (e.g., "citationDelta") to event_types and
collect any citation payloads into a new list (e.g., citation_parts), then
update the assertions to assert that "citationDelta" is in event_types and that
citation_parts contains expected non-empty items (or at least one citation),
while keeping the existing text and messageStop assertions using the same
variables full_text and event_types.
🤖 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/responses.go`:
- Around line 552-607: ToBedrockConverseStreamResponse() currently only maps the
older generic events and will drop the new Nova events (code_interpreter_call.*,
web_search_call.*, and citation-annotation); update that function to reverse-map
the new Bifrost stream types produced in this diff (e.g.,
ResponsesStreamResponseTypeCodeInterpreterCallInProgress,
ResponsesStreamResponseTypeWebSearchCallInProgress,
ResponsesStreamResponseTypeWebSearchCallSearching,
ResponsesStreamResponseTypeOutputItemAdded and citation-related events) back
into Bedrock-style streaming Converse responses. Implement handlers that: detect
these stream response Types and reconstruct the corresponding Bedrock
tool-start/tool-delta/tool-end JSON payloads (for code interpreter use the
CodeInterpreter indices/state like state.CodeInterpreterIndices to buffer and
emit JSON chunks; for Nova grounding use state.NovaGroundingIndices and
state.NovaGroundingCitations to recreate web_search call start/delta/completion
and attach citation annotations). Ensure ItemID/Item mapping (toolUseID) and
sequence/content indices are preserved when emitting the Bedrock messages so
Bifrost→Bedrock bridges don't drop tool starts, deltas, completions, or citation
updates.

---

Outside diff comments:
In `@core/providers/bedrock/responses.go`:
- Around line 2484-2556: The code unconditionally sets
hasNovaGrounding/hasNovaCodeInterpreter from message history and later appends
Nova system tools even when the target model isn't Nova; update
ensureResponsesToolConfigForConversation() (or the calling path that builds tool
inference) to accept the target model (bifrostReq.Model) and gate the final
appends: only append BedrockSystemTool entries for
BedrockSystemToolNovaGrounding and BedrockSystemToolNovaCodeInterpreter when the
provided model is a Nova model (use the existing model-check helper if available
or check Nova model name/prefix). Keep the message-scanning logic for
hasNovaGrounding/hasNovaCodeInterpreter but add a conditional around the two
blocks that append system tools so non-Nova models never receive those
SystemTool entries.
- Around line 857-893: The current handler unmarshals only the latest fragment
(toolUseDelta.Input) which can be partial; instead parse from the accumulated
buffer state.ToolArgumentBuffers[outputIndex] and keep a per-output "last
emitted length" marker (e.g. add or use
state.ToolArgumentEmittedLengths[outputIndex]) so you only attempt to unmarshal
complete JSON and emit the new suffix beyond the last emitted length; for code
interpreter calls (when state.CodeInterpreterIndices[outputIndex] is true)
repeatedly try to unmarshal the buffer into the codeChunk struct, advance the
emitted-length marker to the successfully parsed code's end, set codeDelta to
the newly completed suffix, and construct the ResponsesStreamResponse with that
delta (fall back to not emitting if no new complete JSON is present); preserve
existing behavior for function call argument deltas when not enough JSON is
available.

---

Nitpick comments:
In `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 2984-2995: The test currently only checks full_text built from
content_blocks and must also assert that grounding responses include citation
metadata; update the grounding assertions around full_text/content_blocks (the
nova_grounding path) to verify Bedrock's citation field (e.g., check
response["citationsContent"] or mapped annotation equivalents within
content_blocks) exists and is non-empty and/or contains expected source
identifiers, failing the test if no citation mapping is present; reference the
variables full_text and content_blocks and add the new assertion directly after
the existing text assertions so missing citations cause test failure.
- Around line 3052-3075: The test loop currently only tracks
"messageStart"/"messageStop" and text deltas; add detection and tracking for
citation deltas so the new citation-delta streaming path is exercised: inside
the for event in stream loop (where event_types and text_parts are used) add a
branch to detect citation deltas (e.g., if "citationDelta" in event or if
contentBlockDelta.delta contains a citation field), append a marker (e.g.,
"citationDelta") to event_types and collect any citation payloads into a new
list (e.g., citation_parts), then update the assertions to assert that
"citationDelta" is in event_types and that citation_parts contains expected
non-empty items (or at least one citation), while keeping the existing text and
messageStop assertions using the same variables full_text and event_types.
🪄 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: 7d7df591-d1ca-470e-aaee-c93f116fa27b

📥 Commits

Reviewing files that changed from the base of the PR and between 3b40f1e and 5f860b0.

📒 Files selected for processing (4)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • tests/integrations/python/tests/test_bedrock.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/providers/anthropic/types.go

Comment thread core/providers/bedrock/responses.go
@TejasGhatte
TejasGhatte force-pushed the 05-12-feat_bedrock_system_tools branch from 5f860b0 to f126abe Compare May 15, 2026 06:45

@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 `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 3049-3050: The tests currently assume response_stream contains
"stream" only; change the lookup to fall back to "eventStream" so SDK shape
differences don't cause false failures — replace usages like stream =
response_stream.get("stream") with stream = response_stream.get("stream") or
response_stream.get("eventStream") in the relevant tests (the ones using
response_stream in tests 51 and 53, similar to test_04_converse_streaming), and
keep the existing assert that stream is not None.
🪄 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: 5f5d898c-8d45-4491-b68f-fd66eddd15e6

📥 Commits

Reviewing files that changed from the base of the PR and between 5f860b0 and f126abe.

📒 Files selected for processing (5)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • core/schemas/utils.go
  • tests/integrations/python/tests/test_bedrock.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/types.go
  • core/providers/bedrock/responses.go

Comment thread tests/integrations/python/tests/test_bedrock.py Outdated
Comment thread core/providers/bedrock/responses.go Outdated
@TejasGhatte
TejasGhatte force-pushed the 05-12-feat_bedrock_system_tools branch from f126abe to 25c38fe Compare May 15, 2026 10:00
@TejasGhatte
TejasGhatte changed the base branch from main to graphite-base/3435 May 15, 2026 10:00
@TejasGhatte
TejasGhatte force-pushed the 05-12-feat_bedrock_system_tools branch from 25c38fe to cd7ceaa Compare May 15, 2026 10:01
@TejasGhatte
TejasGhatte changed the base branch from graphite-base/3435 to dev May 15, 2026 10:01

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/providers/anthropic/types.go (1)

182-188: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Bedrock capability comment is now stale and contradicts the flags

Lines 182–184 say Bedrock does not support WebSearch/CodeExecution, but Lines 186–187 now enable both. Please update the comment (or split by model-specific support) so future maintenance doesn’t regress this intentionally enabled behavior.

Suggested comment update
- // Notably NOT supported per docs: MCP, Skills, FilesAPI, WebFetch,
- // WebSearch, CodeExecution, FastMode, TaskBudgets, AdvisorTool,
+ // Notably NOT supported per docs: MCP, Skills, FilesAPI, WebFetch,
+ // FastMode, TaskBudgets, AdvisorTool,
  // InferenceGeo, RedactThinking, AdvancedToolUse (full), PromptCachingScope.
+ // WebSearch and CodeExecution are enabled here for Bedrock Nova system tools.
🤖 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/anthropic/types.go` around lines 182 - 188, The comment above
the schemas.Bedrock capability map is stale and contradicts the actual flags
(WebSearch and CodeExecution are set true); update the comment to either remove
the blanket "NOT supported" list or split it by model/provider so it reflects
current enabled capabilities for schemas.Bedrock (and mention WebSearch and
CodeExecution explicitly), or add a clarifying note that some features are
enabled per-provider while others remain unsupported; ensure the comment and the
schemas.Bedrock map stay consistent so future changes to WebSearch,
CodeExecution, or other flags (e.g., ComputerUse, Bash, Memory) don’t conflict.
🧹 Nitpick comments (1)
tests/integrations/python/tests/test_bedrock.py (1)

2984-3001: ⚡ Quick win

Add explicit non-streaming citation evidence assertions for nova_grounding.

This test currently validates grounded text only. It should also assert citation evidence so the non-streaming citation mapping path in this stack can’t regress silently.

Suggested hardening
         full_text = " ".join(b["text"] for b in content_blocks if b.get("text", "").strip())
         assert full_text, (
             f"Expected non-empty text in grounding response, got: {content_blocks}"
         )
+        citation_urls = []
+        for block in content_blocks:
+            citations_content = block.get("citationsContent", {})
+            for citation in citations_content.get("citations", []):
+                web = citation.get("location", {}).get("web", {})
+                if web.get("url"):
+                    citation_urls.append(web["url"])
+        assert citation_urls, (
+            f"Expected grounding citations in non-streaming response, got: {content_blocks}"
+        )

As per coding guidelines **: always check the stack if there is one and review changes in light of the whole stack.

🤖 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 `@tests/integrations/python/tests/test_bedrock.py` around lines 2984 - 3001,
The test currently only checks grounded text; add explicit assertions that the
non-streaming citation evidence path is present by verifying citation data is
returned: iterate content_blocks and assert at least one block has a non-empty
citation/evidence field (e.g., check block.get("citation") or
block.get("evidence") is truthy) and assert the top-level response contains a
non-empty citations mapping (e.g., response.get("citations") or
response.get("groundingEvidence") is a dict/list with entries); keep these
checks adjacent to the existing full_text and stop_reason assertions so failures
point to nova_grounding citation regressions.
🤖 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/responses.go`:
- Around line 859-867: The buffer currently concatenates raw toolUseDelta.Input
JSON blobs into state.ToolArgumentBuffers[outputIndex], which breaks later JSON
parsing; instead, when state.CodeInterpreterIndices[outputIndex] is true,
extract the "snippet" field from toolUseDelta.Input (using
providerUtils.GetJSONField or equivalent) and append that snippet text to
state.ToolArgumentBuffers[outputIndex] (not the full JSON), preserving ordering
and whitespace; update the branch around codeDelta and any other spots that
append for code interpreter deltas to consistently accumulate only the snippet
pieces so later parsing of the complete code body succeeds.
- Around line 3350-3356: The serialized tool input for the Nova code interpreter
is using the wrong field name ("code") and must match what
convertSingleBedrockMessageToBifrostMessages expects ("snippet"); update the
BedrockContentBlock creation where ToolUse.Input is built (the block that sets
BedrockToolUse.ToolUseID, Name == BedrockSystemToolNovaCodeInterpreter) to
marshal map[string]string{"snippet": code} (and likewise any other place that
marshals this tool input), so ConvertBifrostMessagesToBedrockMessages ⇄
convertSingleBedrockMessageToBifrostMessages use the same "snippet" field.
- Around line 2280-2295: The loop over bifrostReq.Params.Tools currently only
emits web_search/code_interpreter as Bedrock system tools when isNova2 is true,
causing those tool entries to be dropped for other models; add an explicit check
inside that loop: if tool.Type is ResponsesToolTypeWebSearch or
ResponsesToolTypeCodeInterpreter and isNova2 is false, return an error (or
otherwise surface an unsupported-model error) instead of letting the tool fall
through—this should be done before the existing isNova2 block so callers see an
informative error for unsupported-model Nova system tools rather than silent
dropping; reference the bifrostReq.Params.Tools iteration, the isNova2 variable,
ResponsesToolTypeWebSearch, ResponsesToolTypeCodeInterpreter,
BedrockSystemToolNovaGrounding, BedrockSystemToolNovaCodeInterpreter and the
ResponsesToolFunction path when making the change.

In `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 3073-3081: The current handling in the contentBlockDelta branch
uses an elif so citation extraction is skipped whenever text is present; update
the logic in the block that inspects event["contentBlockDelta"] / delta so
text_parts.append(delta["text"]) and citation_urls.append(web["url"]) are
evaluated independently (replace the elif with a separate if for the "citation"
path and keep the existing text check), using the same variables referenced
(contentBlockDelta, delta, text_parts, citation_urls) so citations produced
alongside text are captured.

---

Outside diff comments:
In `@core/providers/anthropic/types.go`:
- Around line 182-188: The comment above the schemas.Bedrock capability map is
stale and contradicts the actual flags (WebSearch and CodeExecution are set
true); update the comment to either remove the blanket "NOT supported" list or
split it by model/provider so it reflects current enabled capabilities for
schemas.Bedrock (and mention WebSearch and CodeExecution explicitly), or add a
clarifying note that some features are enabled per-provider while others remain
unsupported; ensure the comment and the schemas.Bedrock map stay consistent so
future changes to WebSearch, CodeExecution, or other flags (e.g., ComputerUse,
Bash, Memory) don’t conflict.

---

Nitpick comments:
In `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 2984-3001: The test currently only checks grounded text; add
explicit assertions that the non-streaming citation evidence path is present by
verifying citation data is returned: iterate content_blocks and assert at least
one block has a non-empty citation/evidence field (e.g., check
block.get("citation") or block.get("evidence") is truthy) and assert the
top-level response contains a non-empty citations mapping (e.g.,
response.get("citations") or response.get("groundingEvidence") is a dict/list
with entries); keep these checks adjacent to the existing full_text and
stop_reason assertions so failures point to nova_grounding citation regressions.
🪄 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: d954cba3-1d35-4978-8706-eb49522141c1

📥 Commits

Reviewing files that changed from the base of the PR and between f126abe and cd7ceaa.

📒 Files selected for processing (5)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • core/schemas/utils.go
  • tests/integrations/python/tests/test_bedrock.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/schemas/utils.go
  • core/providers/bedrock/types.go

Comment thread core/providers/bedrock/responses.go
Comment thread core/providers/bedrock/responses.go
Comment thread core/providers/bedrock/responses.go Outdated
Comment thread tests/integrations/python/tests/test_bedrock.py
@TejasGhatte
TejasGhatte force-pushed the 05-12-feat_bedrock_system_tools branch from cd7ceaa to 5c00b07 Compare May 15, 2026 10:44

@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.

🧹 Nitpick comments (1)
tests/integrations/python/tests/test_bedrock.py (1)

3071-3071: ⚡ Quick win

Remove per-event streaming log noise at Line 3071.

print(event) inside the stream loop can flood CI logs and make long runs slower/flakier. Keep only summarized assertions/logs.

Suggested minimal patch
-            print(event)
🤖 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 `@tests/integrations/python/tests/test_bedrock.py` at line 3071, The test
contains a noisy per-event print call ("print(event)") inside the streaming loop
that floods CI logs; remove the "print(event)" call and either drop it entirely
or replace it with a single summarized log or assertion after the stream
completes (e.g., check event count or key fields) so the test only emits
concise, meaningful output; locate the streaming loop in
tests/integrations/python/tests/test_bedrock.py where "print(event)" appears and
update the loop to avoid per-event printing.
🤖 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.

Nitpick comments:
In `@tests/integrations/python/tests/test_bedrock.py`:
- Line 3071: The test contains a noisy per-event print call ("print(event)")
inside the streaming loop that floods CI logs; remove the "print(event)" call
and either drop it entirely or replace it with a single summarized log or
assertion after the stream completes (e.g., check event count or key fields) so
the test only emits concise, meaningful output; locate the streaming loop in
tests/integrations/python/tests/test_bedrock.py where "print(event)" appears and
update the loop to avoid per-event printing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 44faaf44-1cc3-4361-bc89-38db4334b404

📥 Commits

Reviewing files that changed from the base of the PR and between cd7ceaa and 5c00b07.

📒 Files selected for processing (5)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • core/schemas/utils.go
  • tests/integrations/python/tests/test_bedrock.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • core/schemas/utils.go
  • core/providers/anthropic/types.go
  • core/providers/bedrock/types.go
  • core/providers/bedrock/responses.go

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 15, 2026

@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.

🧹 Nitpick comments (2)
tests/integrations/python/tests/test_bedrock.py (2)

2979-2995: ⚡ Quick win

Assert citation evidence in non-streaming grounding responses.

This test currently proves text generation but not the non-streaming citation contract, so citation reconstruction regressions can still pass.

Suggested assertion hardening
         content_blocks = msg.get("content", [])
         assert isinstance(content_blocks, list) and len(content_blocks) > 0, (
             f"Expected non-empty content blocks, got: {content_blocks}"
         )
+        has_citations_content = any("citationsContent" in b for b in content_blocks)
+        assert has_citations_content, (
+            f"Expected at least one citationsContent block from nova_grounding, got: {content_blocks}"
+        )

         # nova_grounding returns multiple content blocks: empty text, toolUse,
🤖 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 `@tests/integrations/python/tests/test_bedrock.py` around lines 2979 - 2995,
The test currently only asserts generated text (content_blocks and full_text)
but doesn't validate the non-streaming citation contract; update the assertions
to also verify that grounding responses include citation evidence by checking
each content block in content_blocks for expected citation-related fields or
markers (e.g., presence of a "citation" key, "toolResult" entries with
source/attribution metadata, or explicit source URLs/ids) and assert at least
one citation is present and non-empty alongside the existing full_text checks so
that regressions in citation reconstruction fail the test (use the variables
content_blocks, full_text, and msg to locate and modify the assertions).

2997-3001: ⚡ Quick win

Tighten stop-reason assertions to validate the stop-reason fix.

Allowing "max_tokens" here weakens regression coverage for the stack’s server-managed-tool stop-reason behavior. These prompts are short and should end with "end_turn".

Suggested assertion update
-        assert stop_reason in ("end_turn", "max_tokens"), (
-            f"Unexpected stopReason: {stop_reason}"
-        )
+        assert stop_reason == "end_turn", f"Unexpected stopReason: {stop_reason}"

Also applies to: 3178-3181

🤖 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 `@tests/integrations/python/tests/test_bedrock.py` around lines 2997 - 3001,
The test currently allows stop_reason to be either "end_turn" or "max_tokens" by
checking stop_reason = response.get("stopReason", "") and asserting it in
("end_turn", "max_tokens"); tighten this to assert only "end_turn" (i.e.,
replace the tuple with "end_turn") to validate the server-managed-tool
stop-reason behavior, and make the same change for the other identical assertion
instance that also reads response.get("stopReason", "") later in the file so
both checks only accept "end_turn".
🤖 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.

Nitpick comments:
In `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 2979-2995: The test currently only asserts generated text
(content_blocks and full_text) but doesn't validate the non-streaming citation
contract; update the assertions to also verify that grounding responses include
citation evidence by checking each content block in content_blocks for expected
citation-related fields or markers (e.g., presence of a "citation" key,
"toolResult" entries with source/attribution metadata, or explicit source
URLs/ids) and assert at least one citation is present and non-empty alongside
the existing full_text checks so that regressions in citation reconstruction
fail the test (use the variables content_blocks, full_text, and msg to locate
and modify the assertions).
- Around line 2997-3001: The test currently allows stop_reason to be either
"end_turn" or "max_tokens" by checking stop_reason = response.get("stopReason",
"") and asserting it in ("end_turn", "max_tokens"); tighten this to assert only
"end_turn" (i.e., replace the tuple with "end_turn") to validate the
server-managed-tool stop-reason behavior, and make the same change for the other
identical assertion instance that also reads response.get("stopReason", "")
later in the file so both checks only accept "end_turn".

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5806e955-ae52-4f2e-a8d7-988d79726e1f

📥 Commits

Reviewing files that changed from the base of the PR and between 5c00b07 and 7afb2ad.

📒 Files selected for processing (5)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • core/schemas/utils.go
  • tests/integrations/python/tests/test_bedrock.py
✅ Files skipped from review due to trivial changes (1)
  • core/schemas/utils.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 15, 2026
Comment thread core/providers/bedrock/responses.go

@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: 3

🤖 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 `@tests/integrations/python/tests/test_bedrock.py`:
- Around line 3066-3068: The tests currently only assert that messageStop was
received (variables got_message_stop / messageStop) but do not verify the stop
reason; update both streaming Nova tests to assert messageStop.stopReason equals
the expected self-resolving stop (e.g., "stop" or the specific enum/string used
in the codebase) wherever messageStop is set inside the streaming loop,
replacing the loose existence check with a strict check of
messageStop.stopReason; apply the same change to the other occurrences
referenced (around the other blocks using got_message_stop/messageStop at the
noted locations).
- Around line 3246-3248: The test collects parsed text into text_parts but never
asserts on it, so add assertions to ensure the final streamed assistant answer
is present: after the stream finishes assert that text_parts is not empty (or
equals the expected final message) and that got_message_stop is True; also
assert that code_snippets contains the expected parsed snippet(s) when
exercising the code-delta path. Update the test blocks that initialize
text_parts, code_snippets and got_message_stop (the sections around the existing
variables text_parts, code_snippets, got_message_stop) to include these
assertions so the test fails if the assistant drops the post-execution text
block; apply the same assertions in the other occurrence noted (the second test
block covering the 3302-3308 region).
- Around line 2958-2961: The test currently only asserts the answer text for the
non-streaming response and misses verifying the new citationsContent round-trip;
update the assertions in the test_bedrock integration test to also assert that
the non-streaming response includes the expected citationsContent (e.g., check
the response object/variable used for the non-streaming call contains a
non-empty/expected citationsContent field and that its contents match the
streaming version or expected citation structure). Apply the same additional
assertions in the second block that corresponds to lines 2979-2995 so both
non-streaming cases validate citationsContent.
🪄 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: 60ee72d4-38af-4241-993d-f59b24cb9cc3

📥 Commits

Reviewing files that changed from the base of the PR and between 7afb2ad and 941e75c.

📒 Files selected for processing (5)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go
  • core/providers/bedrock/types.go
  • core/schemas/utils.go
  • tests/integrations/python/tests/test_bedrock.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/providers/anthropic/types.go
  • core/providers/bedrock/responses.go

Comment thread tests/integrations/python/tests/test_bedrock.py
Comment thread tests/integrations/python/tests/test_bedrock.py
Comment thread tests/integrations/python/tests/test_bedrock.py

akshaydeo commented May 15, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • May 15, 3:30 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 15, 3:31 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo merged commit d2a19bf into dev May 15, 2026
15 of 16 checks passed
@akshaydeo
akshaydeo deleted the 05-12-feat_bedrock_system_tools branch May 15, 2026 15:31
akshaydeo pushed a commit that referenced this pull request May 15, 2026
## Summary

Adds support for Amazon Nova system tools (`nova_grounding` and `nova_code_interpreter`) through the Bedrock Converse and Converse-Stream paths. These are AWS-managed tools that the model invokes and executes automatically within a single turn — no client-side tool loop is required. The changes wire up bidirectional translation between Bedrock's native system tool format and Bifrost's neutral schema (`web_search` and `code_interpreter`), covering both non-streaming and streaming response handling.

## Changes

- **`nova_grounding` support**: Enables `WebSearch: true` for the Bedrock provider feature map. Translates `nova_grounding` ↔ `web_search` in tool config conversion. Handles `citation` deltas in the streaming path, emitting them as `url_citation` annotations. Maps `citationsContent` blocks in non-streaming responses to `url_citation` annotations on text content blocks.

- **`nova_code_interpreter` support**: Translates `nova_code_interpreter` ↔ `code_interpreter` in tool config conversion. Introduces `CodeInterpreterIndices` tracking in `BedrockResponsesStreamState` to distinguish code interpreter tool calls from regular function calls during streaming. Emits `code_interpreter_call.in_progress`, `code_interpreter_call.code_delta`, `code_interpreter_call.code.done`, and `code_interpreter_call.completed` stream events instead of the function-call event sequence. In non-streaming responses, merges the `toolUse` (code) and paired `nova_code_interpreter_result` `toolResult` blocks into a single `code_interpreter_call` output item with execution logs.

- **Stop reason fix**: Server-managed tools resolve their own `toolResult` in the same turn. The stop reason derivation now pre-scans for matched `toolUse`/`toolResult` pairs so that `hasToolUse` stays false for self-resolving tools, preserving the original `end_turn` stop reason rather than incorrectly emitting `tool_use`.

- **New Bedrock types**: Added `BedrockSystemTool`, `BedrockSystemToolType`, `BedrockCitation`, `BedrockCitationLocation`, `BedrockWebCitationLocation`, `BedrockCitationsContent`, and a `Type` field on `BedrockToolResult` to support `nova_code_interpreter_result` identification.

- **Integration tests**: Added `TestNovaSystemTools` with four test cases (50–53) covering `nova_grounding` and `nova_code_interpreter` in both non-streaming and streaming modes via the Bedrock Converse API.

## Type of change

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

## Affected areas

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

## How to test

```sh
go test ./core/providers/bedrock/...
go test ./core/providers/anthropic/...
```

For integration tests against a live Bedrock endpoint with Nova model access:

```sh
cd tests/integrations/python
pip install -r requirements.txt
pytest tests/test_bedrock.py::TestNovaSystemTools -v
```

Test cases require AWS credentials with access to `us.amazon.nova-2-lite-v1:0` and the `nova_grounding` / `nova_code_interpreter` system tools enabled in your account. Tests will be skipped automatically if the tools are unavailable or the API key is not configured.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

Nova system tools are fully AWS-managed and execute in AWS infrastructure. No user-supplied code or credentials are passed through Bifrost beyond the standard Bedrock API call. Citation URLs returned by `nova_grounding` are surfaced as annotations and are not fetched or processed by Bifrost.

## 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 pushed a commit that referenced this pull request May 20, 2026
## Summary

Adds support for Amazon Nova system tools (`nova_grounding` and `nova_code_interpreter`) through the Bedrock Converse and Converse-Stream paths. These are AWS-managed tools that the model invokes and executes automatically within a single turn — no client-side tool loop is required. The changes wire up bidirectional translation between Bedrock's native system tool format and Bifrost's neutral schema (`web_search` and `code_interpreter`), covering both non-streaming and streaming response handling.

## Changes

- **`nova_grounding` support**: Enables `WebSearch: true` for the Bedrock provider feature map. Translates `nova_grounding` ↔ `web_search` in tool config conversion. Handles `citation` deltas in the streaming path, emitting them as `url_citation` annotations. Maps `citationsContent` blocks in non-streaming responses to `url_citation` annotations on text content blocks.

- **`nova_code_interpreter` support**: Translates `nova_code_interpreter` ↔ `code_interpreter` in tool config conversion. Introduces `CodeInterpreterIndices` tracking in `BedrockResponsesStreamState` to distinguish code interpreter tool calls from regular function calls during streaming. Emits `code_interpreter_call.in_progress`, `code_interpreter_call.code_delta`, `code_interpreter_call.code.done`, and `code_interpreter_call.completed` stream events instead of the function-call event sequence. In non-streaming responses, merges the `toolUse` (code) and paired `nova_code_interpreter_result` `toolResult` blocks into a single `code_interpreter_call` output item with execution logs.

- **Stop reason fix**: Server-managed tools resolve their own `toolResult` in the same turn. The stop reason derivation now pre-scans for matched `toolUse`/`toolResult` pairs so that `hasToolUse` stays false for self-resolving tools, preserving the original `end_turn` stop reason rather than incorrectly emitting `tool_use`.

- **New Bedrock types**: Added `BedrockSystemTool`, `BedrockSystemToolType`, `BedrockCitation`, `BedrockCitationLocation`, `BedrockWebCitationLocation`, `BedrockCitationsContent`, and a `Type` field on `BedrockToolResult` to support `nova_code_interpreter_result` identification.

- **Integration tests**: Added `TestNovaSystemTools` with four test cases (50–53) covering `nova_grounding` and `nova_code_interpreter` in both non-streaming and streaming modes via the Bedrock Converse API.

## Type of change

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

## Affected areas

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

## How to test

```sh
go test ./core/providers/bedrock/...
go test ./core/providers/anthropic/...
```

For integration tests against a live Bedrock endpoint with Nova model access:

```sh
cd tests/integrations/python
pip install -r requirements.txt
pytest tests/test_bedrock.py::TestNovaSystemTools -v
```

Test cases require AWS credentials with access to `us.amazon.nova-2-lite-v1:0` and the `nova_grounding` / `nova_code_interpreter` system tools enabled in your account. Tests will be skipped automatically if the tools are unavailable or the API key is not configured.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

Nova system tools are fully AWS-managed and execute in AWS infrastructure. No user-supplied code or credentials are passed through Bifrost beyond the standard Bedrock API call. Citation URLs returned by `nova_grounding` are surfaced as annotations and are not fetched or processed by Bifrost.

## 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 20, 2026
18 tasks
akshaydeo added a commit that referenced this pull request May 20, 2026
## Summary

This PR cuts the `v1.5.11` / `v1.3.11` release across core, framework, and all plugins, and introduces a new Claude skill (`release-checklist`) for pre-release migration safety auditing.

## Changes

- **`release-checklist` skill** — Adds `.claude/skills/release-checklist/SKILL.md`, a read-only pre-release audit tool that scans Go-defined database migrations changed in a release for high-scale deadlock/lock-contention risks and boot-time-blocking operations. It produces a structured `PASS`/`WARN`/`FAIL` report with a concrete remediation plan per finding. The skill is designed to grow via an extensible Checks Registry.
- **Version bumps** — `core` → `1.5.11`, `framework` → `1.3.11`, `transports` → `1.5.3`, `plugins/governance` → `1.5.11`, `plugins/logging` → `1.5.11`, `plugins/semanticcache` → `1.5.11`, `plugins/otel` → `1.2.11`, `plugins/maxim` → `1.6.11`, `plugins/prompts` → `1.0.11`, and remaining plugins bumped accordingly.
- **Changelogs populated** — All per-package changelogs updated with the full set of features and fixes shipping in this release.

Key highlights in this release:
- Temporary access tokens for scoped, time-limited API access
- MCP per-user OAuth flow refactor
- Bedrock Mantle inference engine support
- Azure Realtime provider with enriched session tracking
- Direct access control (DAC) and virtual key rotation
- Cluster-aware log metadata and per-node usage aggregation
- Feature flag framework
- Config-hash-based file value override of DB on restart
- Semantic cache plugin rewrite
- Numerous streaming stability, Bedrock, Anthropic, and Gemini fixes
- AWS SDK and dependency security updates

## Type of change

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

## Affected areas

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

## How to test

```sh
# Verify version files reflect the new release
cat core/version          # expect 1.5.11
cat framework/version     # expect 1.3.11
cat transports/version    # expect 1.5.3

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

To exercise the new `release-checklist` skill, invoke it via Claude with:
```
/release-checklist origin/dev...HEAD
```
Expected output: a structured report with `PASS`/`WARN`/`FAIL` per check and a Remediation Plan table for any findings.

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

#3603, #3565, #3489, #3334, #3335, #3435, #3554, #3590, #3444, #3198, #3581, #3610, #3599, #3567, #3382, #3461 and others listed in the changelogs.

## Security considerations

- AWS SDK and dependency security updates are included (#3461).
- `FullyRedacted()` for proxy passwords and `MarshalForStorage()` for `ProxyConfig` prevent partial secret leakage in API responses (#3445).
- The `release-checklist` skill is strictly read-only and never modifies files.

## 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)
- [ ] I verified the CI pipeline passes locally if applicable
@akshaydeo akshaydeo mentioned this pull request May 20, 2026
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.

3 participants