Problem/Motivation

My company is making use of this module for AI work and in our case, we are required to use Bedrock guardrails. Per the issue #3562254: Set Guardrails when invoking models, we are using a patch to add guardrail configuration to a Bedrock request. When a guardrail intervenes in a chat request, we want to be able to parse the response from Bedrock and extract the guardrail intervention details for logging purposes.

For non streaming chat messages, we have been able to make use of the AI module PostGenerateResponseEvent to parse the response from Bedrock and if the guardrail intervened, we can get the details from the response.

The chat() method in BedrockProvider is executed by the AI ProviderProxy instance in wrapperCall(). In that method, the PostGenerateResponseEvent is dispatched after the response from the chat() method in BedrockProvider runs and the event has access to the 'raw' response from the provider. In BedrockProvider, this looks like:

    $loggable_raw_response = new BedrockJsonSerializeDecorator($response);

    return new ChatOutput($message, $loggable_raw_response, $response['usage']);

The $loggable_raw_response instance has a jsonSerialize() method that when my event subscriber runs, can act on the Bedrock response object and log information. This works fine when the chat is NOT streamed. However when the chat is streamed - as is the case when using the AI Summarize Documents module - the jsonSerialize() method throws an error. This is due to the Bedrock response instance having streamed class instances in the response which the jsonSerialize() method does not account for.

The following error occurs in this scenario:

Object of class Aws\Api\Parser\EventParsingIterator could not be converted to string" at /var/www/html/web/modules/contrib/ai_provider_aws_bedrock/src/Decorator/BedrockJsonSerializeDecorator.php line 39

Line 39 tries to cast a variable to a string when the variable is not an array. In the case of a streamed response, the variable is not an array, but is also not able to be cast to a string, as it's an instance of the object mentioned above.

Steps to reproduce

Proposed resolution

I was able to debug with a streamed response and with some investigation was able to find the format of the streamed response here: https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Conv...

With a known streamed output format, I was able to account for the streamed output and patched jsonSerialize() to handle the stream. I've created an issue fork for this.

Remaining tasks

User interface changes

API changes

Data model changes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

jaydub created an issue. See original summary.

jv24’s picture

I've created a merged patch that combines the changes from MR !13 with an additional fix for the "Undefined array key" warnings that occur during stream processing.

Issue: When using the ConverseStream API, the following PHP warnings are generated:

Warning: Undefined array key "content" in BedrockJsonSerializeDecorator.php on line 39
Warning: Undefined array key 0 in BedrockJsonSerializeDecorator.php on line 39
Warning: Undefined array key "text" in BedrockJsonSerializeDecorator.php on line 39

Root Cause: The MR !13 patch adds stream handling logic that appends text to $json['output']['message']['content'][0]['text'], but this nested array structure is never initialized before the first append operation. PHP's += operator on an undefined array key generates these warnings.

Solution: This patch extends MR !13 by adding an initialization check before appending stream content:

if (!isset($json['output']['message']['content'][0]['text'])) {
  $json['output']['message']['content'][0]['text'] = '';
}

This ensures the nested array structure exists before any append operations, eliminating all three warnings while maintaining the complete ConverseStream functionality from MR !13.

Testing: Tested with AWS Bedrock Claude Sonnet 4 models using regional inference profiles. Stream responses now process without warnings and correctly aggregate all content blocks, metadata, and stop reasons.