Skip to content

fix(bedrock): streaming fallback to Converse API + image base64 decode + bearer token routing - #34742

Closed
JiaDe-Wu wants to merge 1 commit into
NousResearch:mainfrom
JiaDe-Wu:fix/bedrock-streaming-fallback-and-image
Closed

fix(bedrock): streaming fallback to Converse API + image base64 decode + bearer token routing#34742
JiaDe-Wu wants to merge 1 commit into
NousResearch:mainfrom
JiaDe-Wu:fix/bedrock-streaming-fallback-and-image

Conversation

@JiaDe-Wu

Copy link
Copy Markdown
Contributor

Three fixes for the Bedrock Claude path that share a common theme: the AnthropicBedrock SDK doesn't handle all Bedrock scenarios correctly, and the native Converse API path is the reliable fallback.

1. Streaming fallback (new)

When the AnthropicBedrock SDK's stream accumulator receives a Bedrock error event (throttling, overload, 5xx) before message_start, it raises RuntimeError: Unexpected event order and discards the actual error payload. After 3 retries the session dies.

Fix: detect this specific RuntimeError in the conversation loop and auto-switch api_mode from anthropic_messages to bedrock_converse for the rest of the session. The Converse API handles these error events gracefully via boto3's native error handling.

2. Image base64 decode (fixes #33317)

_convert_content_to_converse() passed the base64 string directly as source.bytes. boto3 re-encodes at the wire layer, resulting in double-encoding. Bedrock rejects with "Failed to sanitize image".

Fix: base64.b64decode(data) before passing to source.bytes.

3. Bearer token routing (fixes #28156 part 1)

Users with AWS_BEARER_TOKEN_BEDROCK were routed through the AnthropicBedrock SDK (which only supports SigV4 signing), causing RuntimeError: could not resolve credentials from session.

Fix: check for bearer token env var in the dual-path routing logic. If present, always use bedrock_converse regardless of model.

Files

  • agent/conversation_loop.py -- streaming fallback handler
  • agent/bedrock_adapter.py -- base64 decode fix
  • hermes_cli/runtime_provider.py -- bearer token routing
  • tests/agent/test_bedrock_adapter.py -- 3 new tests

Testing

121 bedrock_adapter tests passing (Python 3.11 + 3.14).

Ref: #33317, #28156, #14737

…e + bearer token routing

Three fixes for the Bedrock Claude path:

1. Streaming fallback: When AnthropicBedrock SDK raises 'Unexpected event
   order' (SDK misparses Bedrock error events as message_start), auto-switch
   to native Converse API for the rest of the session instead of failing
   after 3 retries.

2. Image base64 decode (NousResearch#33317): data URL payloads were passed as base64
   strings to source.bytes, but boto3 re-encodes at the wire layer. Now
   decoded to raw bytes before passing to Converse API.

3. Bearer token routing (NousResearch#28156): Users with AWS_BEARER_TOKEN_BEDROCK are
   now routed through Converse API regardless of model, since the
   AnthropicBedrock SDK only supports SigV4 signing.

3 new tests. 121 bedrock_adapter tests passing.
@alt-glitch

Copy link
Copy Markdown
Collaborator

Significant overlap with existing open PRs:

This PR bundles all three fixes together. Consider whether to merge this or the individual PRs.

@JiaDe-Wu

Copy link
Copy Markdown
Contributor Author

Good callout. The individual PRs (#28085, #33536, #24507, #26531) are all 50-200 commits stale and would need rebasing. This PR bundles the fixes onto current main with tests, so it can merge as-is without conflict resolution. Happy to close if maintainers prefer to rebase the originals instead.

@RamsAI-bot

Copy link
Copy Markdown

For anyone tracking bearer-token Bedrock support: the two PRs that look closest to a complete fix are #24507 (main-loop Converse routing + AWS_BEARER_TOKEN_BEDROCKAWS_BEARER_TOKEN promotion) and #28085 (auxiliary dual-path Converse client). They were verified to compose cleanly (cherry-pick, 0 conflicts) and together cover both the main loop and auxiliary tasks (title generation / compression; vision still has a separate gap).

Relative to this PR: the routing here omits the token promotion that #24507 carries (which matters for cron jobs / subagents that don't inherit the interactive session's env), and the base64 image-decode fix is also included in #28085. The streaming-overload → Converse fallback in this PR is independently useful for SigV4 hosts.

@RamsAI-bot

Copy link
Copy Markdown

Update — the aux vision gap noted in my comment above is now resolved by #28085's second commit (acd5de2da), verified working against real bearer-token Bedrock. So #24507 + #28085 (in full) now cover the main loop and all aux tasks — title generation, compression, and vision — under AWS_BEARER_TOKEN_BEDROCK.

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

Thanks for consolidating the Bedrock reports. The image and bearer-routing premises are both still present on current main, but this bundle needs a focused salvage rather than a direct application.

Problems

  • agent/bedrock_adapter.py:91-101 creates boto3 clients without promoting AWS_BEARER_TOKEN_BEDROCK to boto3's AWS_BEARER_TOKEN. This PR routes bearer users to Converse but does not provide that token to the new client path; related PR #24507 contains the missing promotion.
  • The new fallback changes agent.api_mode permanently from a string-matched RuntimeError. Current agent/agent_init.py:895-915 initializes _bedrock_guardrail_config only when Converse is selected at startup, so this transition would lose configured guardrails.
  • No test exercises the new conversation-loop fallback; the added tests cover only conversion and provider resolution.
  • base64.b64decode(data) is non-strict and the fallback still sends arbitrary bytes for malformed input.

Suggested changes

  • Add guarded bearer-token promotion in the boto3 client factory with regression coverage.
  • Use a tested Converse-transition helper that preserves Bedrock runtime state, including guardrails, and restrict fallback to a confirmed retryable stream failure.
  • Strictly validate data URLs and skip malformed image blocks; add a live-path fallback regression test.

Automated hermes-sweeper review.

Comment thread agent/bedrock_adapter.py
# results in double-encoding and Bedrock rejects it with
# "Failed to sanitize image". Ref: #33317.
import base64
try:

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.

base64.b64decode() defaults to non-strict parsing, so malformed payloads can silently decode to junk; the exception fallback then still sends arbitrary bytes to Bedrock. Use validate=True and omit an invalid image block rather than forwarding it.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
@teknium1 teknium1 closed this Jul 15, 2026
@teknium1 teknium1 added the area/streaming Streaming responses: gateway delivery, provider wire label Jul 19, 2026
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/streaming Streaming responses: gateway delivery, provider wire comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P3 Low — cosmetic, nice to have provider/bedrock AWS Bedrock (boto3, IAM) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

4 participants