feat(bedrock): configurable Bedrock read/connect timeout#2223
feat(bedrock): configurable Bedrock read/connect timeout#2223go-faustino wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds end-to-end configuration for AWS Bedrock client HTTP connect/read timeouts so long Converse responses aren’t aborted by botocore’s ~60s default read timeout, while preserving existing default behavior when timeouts are unset.
Changes:
- Plumbs
readTimeout/connectTimeoutfrom the ModelConfig CRD → Go translator/types → Python ADK model config. - Updates the Bedrock boto3 client creation to optionally attach a
botocore.config.Configonly when a timeout override is provided. - Adds Python unit tests covering the “no config when unset” behavior and the timeout override cases.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| python/packages/kagent-adk/tests/unittests/models/test_bedrock.py | Adds unit tests asserting boto3 client config behavior for unset/set timeouts. |
| python/packages/kagent-adk/src/kagent/adk/types.py | Extends the Python Bedrock model config schema to include timeout fields and forwards them into Bedrock LLM construction. |
| python/packages/kagent-adk/src/kagent/adk/models/_bedrock.py | Adds optional read_timeout/connect_timeout plumbing into the Bedrock boto3 client via botocore.config.Config. |
| helm/kagent-crds/templates/kagent.dev_modelconfigs.yaml | Regenerates Helm CRD template to include Bedrock timeout fields with minimum validation. |
| go/core/internal/controller/translator/agent/adk_api_translator.go | Maps Bedrock timeout fields from CRD spec into the ADK Bedrock payload. |
| go/api/v1alpha2/zz_generated.deepcopy.go | Regenerates deepcopy for new BedrockConfig fields. |
| go/api/v1alpha2/modelconfig_types.go | Adds BedrockConfig readTimeout/connectTimeout with Minimum=1 validation and docs. |
| go/api/config/crd/bases/kagent.dev_modelconfigs.yaml | Updates the base CRD manifest with Bedrock timeout schema/docs. |
| go/api/adk/types.go | Extends Go ADK Bedrock type to include timeout fields for JSON payloads. |
Files not reviewed (1)
- go/api/v1alpha2/zz_generated.deepcopy.go: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| config = mock_boto.call_args.kwargs["config"] | ||
| assert config.read_timeout == 1800 | ||
| # connect_timeout untouched -> botocore keeps its 60s default | ||
| assert config.connect_timeout == 60 |
There was a problem hiding this comment.
Good call — fixed in 6c3e7d5. The test no longer hard-codes 60; it now asserts config.connect_timeout == BotocoreConfig().connect_timeout, i.e. against botocore's own current default for the installed version, so it won't break if that default changes.
| # Bedrock HTTP client timeouts in seconds. read_timeout overrides botocore's | ||
| # ~60s default, which otherwise aborts long completions with a | ||
| # ReadTimeoutError. None keeps botocore's defaults. | ||
| read_timeout: int | None = None | ||
| connect_timeout: int | None = None |
There was a problem hiding this comment.
Done in 6c3e7d5. read_timeout / connect_timeout are now Field(default=None, ge=1) on both the Bedrock config type (here) and KAgentBedrockLlm, matching the CRD's minimum: 1. Added tests covering accepted positive values and rejected 0/negative (raises ValidationError).
| timeout_config: dict[str, Any] = {} | ||
| if read_timeout is not None: | ||
| timeout_config["read_timeout"] = read_timeout | ||
| if connect_timeout is not None: | ||
| timeout_config["connect_timeout"] = connect_timeout | ||
| if timeout_config: | ||
| kwargs["config"] = BotocoreConfig(**timeout_config) |
There was a problem hiding this comment.
Addressed in 6c3e7d5 by validating at the model boundary rather than inside this private builder. _get_bedrock_client is only reached via KAgentBedrockLlm._client, and KAgentBedrockLlm.read_timeout / connect_timeout are now Field(ge=1) (matching the Bedrock config type and the CRD minimum: 1), so 0/negative values can't reach the botocore Config. I kept this function a thin builder to avoid duplicating the constraint in a third place, but happy to add an explicit guard here too if you'd prefer defense-in-depth for direct callers.
6c3e7d5 to
ebedb07
Compare
The Python ADK's Bedrock client is created via boto3 with no botocore Config, so it uses botocore's ~60s default read timeout. Long Converse completions (large tool-augmented turns, extended reasoning) are aborted with a ReadTimeoutError. Add optional read_timeout / connect_timeout (seconds), plumbed end to end: - _get_bedrock_client builds a botocore Config only when a timeout is set, otherwise keeping boto3 defaults. - KAgentBedrockLlm and the Bedrock config type expose read_timeout / connect_timeout. - BedrockConfig CRD gains readTimeout / connectTimeout, mapped through the Go adk.Bedrock type and the agent translator; CRD + Helm CRD regenerated. Adds Python unit tests covering unset (no Config), read-only, and read+connect timeouts. Signed-off-by: Gonçalo Faustino <goncalo.santos@wellhub.com>
Address review feedback on the Bedrock read/connect timeout config: - Constrain read_timeout / connect_timeout to >= 1 on both the Python Bedrock config type and KAgentBedrockLlm (Field(ge=1)), matching the ModelConfig CRD (minimum: 1) so invalid values can't reach boto3. - Stop hard-coding botocore's 60s default in the timeout test; assert against botocore.config.Config().connect_timeout instead. - Add tests for accepted positive timeouts and rejected 0/negative values. Signed-off-by: Gonçalo Faustino <goncalo.santos@wellhub.com>
ebedb07 to
eab8d1f
Compare
Summary
The Python ADK's Bedrock client is created with
boto3.client("bedrock-runtime", ...)and no botocoreConfig, so it uses botocore's ~60s default read timeout. Long Converse completions — large tool-augmented turns, extended reasoning — are aborted mid-response with aReadTimeoutError, surfaced to the user as an API error.This adds an optional, configurable Bedrock read timeout (and connect timeout), plumbed end to end from the
ModelConfigCRD down to the boto3 client.Changes
_bedrock.py:_get_bedrock_clientnow acceptsread_timeout/connect_timeoutand builds abotocore.config.Configonly when at least one is set, so the default behavior is unchanged.KAgentBedrockLlmexposes the two fields and forwards them.types.py: theBedrockmodel config gainsread_timeout/connect_timeout, passed intoKAgentBedrockLlm.BedrockConfiggainsreadTimeout/connectTimeout(seconds,minimum: 1), mapped through the Goadk.Bedrocktype and the agent translator. CRD manifest and the Helmkagent-crdscopy regenerated withcontroller-gen.Test
Adds Python unit tests in
tests/unittests/models/test_bedrock.py:configpassed when timeouts are unset (default preserved),read_timeoutsetsConfig.read_timeout(connect left at botocore's default),read_timeout+connect_timeoutboth applied.Go:
go build ./api/... ./core/internal/controller/translator/...andgo vet ./api/...pass; deepcopy regenerated.Example