chore(deps): upgrade strands-agents 1.51.0 → 1.55.0 - #1012
Merged
Conversation
Migrates the deprecated model-level `cache_tools` key to
`CacheConfig(tools_ttl=...)` and fixes the Nova Sonic provider rename that
1.55.0 makes, which would otherwise have silently disabled voice.
Prompt-cache contract (the governing constraint here) is unchanged, proven
two ways rather than by code reading:
- Offline: the full formatted ConverseStream request for our production
config is byte-identical between 1.51.0 and 1.55.0 (same request SHA).
- Live against dev Bedrock: a request formatted by 1.55.0 READ the exact
cache entry (7,059 tokens) that the same request formatted by 1.51.0 had
just written. Bedrock itself confirms the cacheable prefix did not move.
`cache_tools` -> `tools_ttl`
`_warn_on_deprecated_cache_tools` fires on the old key in 1.55.0. With
`cache_config.ttl` unset, `_build_tools_cache_point` resolves `tools_ttl=True`
to the same bare `{"cachePoint": {"type": "default"}}` the deprecated path
emitted, so the toolConfig tail — which sits inside the cached prefix — is
unchanged. The unsupported branch now pins `tools_ttl=False` explicitly
instead of falling through the deprecated key.
New auto-injected system cache point
1.55.0 adds `_should_cache_system()`, guarded by
`not any("cachePoint" in block ...)`. `AgentFactory.create_agent` already
appends its own whenever `bedrock_cache_points_supported()`, and that
predicate is equivalent to the SDK's, so no path gains a second point.
Audited every system-prompt path: the chat agent goes through the factory;
voice uses BidiNovaSonicModel (no cache_config); `/chat/api-converse` uses
raw boto3 on the Bedrock branch and OpenAI-surface models otherwise; there
is exactly one `BedrockModel` construction site. `system_prompt_ttl` is left
at its default True as a safety net for any future path that bypasses the
factory. `_apply_system_cache_ttl` is inert because `cache_config.ttl` stays
unset.
Nova Sonic provider rename (not in the release notes)
1.55.0 moved `models.nova_sonic.BidiNovaSonicModel` to
`models.bedrock.BedrockNovaSonicModel` and flattened its constructor
(`provider_config["audio"]` -> `audio`, `client_config["region"]` -> `region`).
`voice_agent` imports the provider inside a `try/except ImportError` that
degrades to `BIDI_AVAILABLE = False`, so the stale import would not have
crashed — it would have silently turned voice off in the inference-api image,
which does install `--extra bidi`. Adds a contract test that reads the pinned
SDK's source rather than importing it, since CI installs `agentcore`/`dev`
but not `bidi`.
Also updates the sequential-executor cancellation canary: 1.55.0 moved the
per-tool check from `agent._cancel_signal` to `Agent._observe_cancellation()`,
same semantics plus an external-signal mirror.
boto3 stays at 1.43.68 in all five files that pin it — 1.55.0 floors at
>=1.26.0 and `bedrock-agentcore` is unchanged, so nothing forces it.
Fixes we gain on the GPT-5.6 / Mantle Responses path: `length` now beats
`tool_calls` (1.51.0 executed truncated tool arguments), `cachePoint` blocks
are filtered instead of raising `TypeError` on a mid-session model switch, and
document attachments use `filename`/`file_data` instead of `file_url`.
Verified: full backend suite 7783 passed / 0 failed; a 3-turn dev session on
1.55.0 went first_write -> hit -> hit with constant toolConfigHash and
systemPromptHash, no partial_miss, cacheRead:cacheWrite 9097:126 then 9223:34;
a GPT-5.6 (Terra) turn with a text attachment read the document correctly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
philmerrell
force-pushed
the
feature/strands-1-55-upgrade
branch
from
September 9, 2026 04:05
9d5d1da to
161ce6e
Compare
Contributor
Author
|
Rebased onto Both conflicts were in the dependency pins, from #1011 landing
Re-verified on the combined state
One thing worth recording about 0.8.80.8.8's sandbox fix edits
Only the module docstring changed (documenting the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upgrades
strands-agents1.51.0 → 1.55.0 inbackend/pyproject.toml(both theagentcoreandbidiextras).strands-agents-tools(0.8.6) andbedrock-agentcore(1.21.0) are deliberately left alone — separate PRs.The prompt-cache contract is unchanged
This is the governing constraint, so it is proven rather than argued:
Offline — the full formatted ConverseStream request for our production config is byte-identical between the two versions:
58606987da49cd08a6f5489e365f227658606987da49cd08a6f5489e365f2276Live, against dev Bedrock — the same conversation formatted by each version, sent to ConverseStream back to back:
1.55.0 read the exact cache entry 1.51.0 had just written. Bedrock itself confirms the cacheable prefix did not move.
cache_tools→CacheConfig(tools_ttl=...)1.55.0 deprecates the model-level
cache_toolskey (_warn_on_deprecated_cache_tools). Withcache_config.ttlunset,_build_tools_cache_pointresolvestools_ttl=Trueto the same bare{"cachePoint": {"type": "default"}}the deprecated path emitted — so the toolConfig tail, which sits inside the cached prefix, is unchanged. The unsupported branch now pinstools_ttl=Falseexplicitly rather than falling through the deprecated key. The deprecation warning is gone from the suite.The new auto-injected system cache point
1.55.0 adds
_should_cache_system(), which appends a system cachePoint — guarded bynot any("cachePoint" in block ...).AgentFactory.create_agentalready appends its own wheneverbedrock_cache_points_supported(), and that predicate is equivalent to the SDK's_cache_strategytest, so the guard always short-circuits on our paths. Audited every path that builds a system prompt:AgentFactory→ our point already presentBidiNovaSonicModel, nocache_config— not aBedrockModel/chat/api-converseBedrockModelsitesagent_factorysystem_prompt_ttlis left at its defaultTrueas a safety net for any future path that bypasses the factory._apply_system_cache_ttlis inert becausecache_config.ttlstays unset. A new test asserts the system blocks carry exactly one cachePoint.1.55.0 moved
models.nova_sonic.BidiNovaSonicModel→models.bedrock.BedrockNovaSonicModeland flattened its constructor (provider_config["audio"]→audio,client_config["region"]→region).voice_agentimports the provider inside atry/except ImportErrorthat degrades toBIDI_AVAILABLE = False. The stale import would therefore not have crashed — it would have silently turned voice off in the inference-api image, which does install--extra bidi, leaving one INFO line behind.Verified the migrated call still lands the voice, sample rates, channels and format on the model, and that
usage_is_cumulativeis stillTrue(ourbidi_usagede-cumulation depends on it). Added a contract test that reads the pinned SDK's source rather than importing it, becausetests.ymlinstallsagentcore/devbut notbidi.boto3
No move needed. 1.55.0 floors at
boto3>=1.26.0andbedrock-agentcoreis unchanged at 1.21.0 (>=1.43.35), so1.43.68still resolves. It stays pinned in all five files that carry it (pyproject.tomlplus four Lambdarequirements.txt).What we gain
On the GPT-5.6 / Mantle Responses path:
lengthnow beatstool_calls. In 1.51.0 a function call cut off bymax_tokenssurfaced astool_callsand was executed with truncated arguments.cachePointblocks filtered rather than passed through. On 1.51.0 a session switched mid-conversation from Claude to GPT-5.6 raisedTypeError: content_type=<cachePoint> | unsupported type; our session manager preservescachePointin_BEDROCK_CONTENT_BLOCK_KEYS, so this was reachable.{"type":"input_file","file_url":…}to{"type":"input_file","filename":…,"file_data":…}.Also: the sequential executor's per-tool cancellation check moved from
agent._cancel_signaltoAgent._observe_cancellation()— same semantics plus a synchronous mirror of a caller-supplied external signal. We never pass one, soreset_cancellation_stateclearing the internal signal remains sufficient; the canary now binds against the new indirection and a second test pins that relationship.Verification
uv run python -m pytest tests/ -v— 7783 passed, 3 skipped, 0 failed (full suite).Every
strandsimport inbackend/srcre-checked against 1.55.0; all resolve._openai_bedrock.py(we monkeypatch_OPENAI_PATH_MODEL_PREFIXES) is byte-identical.Live 3-turn session on dev driven through a local inference-api running this branch, writing real rows to
dev-boisestateai-v2-sessions-metadata:first_writebdec3e8a9801d15cac3d5e48315be364hitbdec3e8a9801d15cac3d5e48315be364hitbdec3e8a9801d15cac3d5e48315be364No
partial_miss,wastedUsd0 on every call, both static hashes constant. Read:write runs 72:1 and 271:1 — the inverse of the ~1:2 write premium a regression would show.GPT-5.6 (Terra) with a document attachment — the model read a verification phrase out of an attached
.txtthrough the newfilename/file_datashape, and the Responses-path explicit cache hit (cacheRead1,538) on the repeat.Deploy
Merging to
developauto-deploys dev (backend.yml,frontend-deploy.yml,platform.ymlare all push-triggered).🤖 Generated with Claude Code