feat(bb-agent): migrate streaming execution to AgentCore Runtime (1/5) - #250
Draft
pjkroker wants to merge 9 commits into
Draft
feat(bb-agent): migrate streaming execution to AgentCore Runtime (1/5)#250pjkroker wants to merge 9 commits into
pjkroker wants to merge 9 commits into
Conversation
…me/AsyncJob Streaming now runs over SSE everywhere — AgentCore Runtime on AWS, a local dev-server SSE route in mock/dev — replacing the Lambda + SQS + AppSync/Realtime side-channel. Verified end-to-end on real AWS (stream + HITL interrupt/resume + DynamoDB history) and locally. - streamSSE() is the primary API; stream()/resume() kept as @deprecated compat wrappers (async-iterable + complete()). Removed the Realtime channel surface (getChannel/channel/channelId) — breaking. - index.cdk.ts provisions the AgentCore Runtime via fromCodeAsset() with a synth-time co-bundle of the app backend; no more Realtime/AsyncJob. - agentcore-entry.ts (BedrockAgentCoreApp harness) + dev-stream.ts (local SSE). - core dev-server: generic __BLOCKS_DEV_ROUTE_HANDLERS__ hook; BlocksStack exposes backendModulePath. - useChat consumes one streamChunks SSE transport. - bump @strands-agents/sdk ^1.7.0, add bedrock-agentcore.
Superseded by the synth-time co-bundle in agentcore-bundle.ts. Reverts build to plain tsc, drops the bundle:agentcore script, and repoints the CDK test's agentcoreAssetPath at dist/ (any existing dir works for fromCodeAsset).
esbuild is imported on the published CDK synth path (index.cdk.ts → agentcore-bundle.ts top-level import). As a devDependency it wouldn't be installed for consumers, so cdk synth on the default co-bundle path would throw 'Cannot find module esbuild'. lint:deps now passes.
Reflects streamSSE()/getStreamEndpoint()/AgentCoreStreamResult, the SSE-based AgentStreamResult (async-iterable + complete()), and removal of the Realtime channel surface (channel/channelId, StreamOptions.channelId). check:api green.
The >29s slow-tool test assumed the old async model (agentStream returns immediately, chunks arrive out-of-band). Under SSE the RPC drains the stream, so a >30s turn exceeds the API Gateway timeout (504). Long-running agents are AgentCore's domain, not the buffered RPC path this test app uses.
🦋 Changeset detectedLatest commit: de1924d The changes in this PR will be included in the next version bump. This PR includes changesets to release 22 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Type the CDK constructor as AgentConfig instead of `any`, and declare the CDK-only `auth` and `agentcoreAssetPath` fields on AgentConfig. Previously `config?: any` meant a typo (e.g. agentCoreAssetPath) or wrong auth shape failed silently at synth rather than at dev time.
The header (Type/AWS Services), the Architecture table, and the flow diagram still described the removed Lambda + SQS/AsyncJob + AppSync/Realtime design. Update them to the AgentCore model: AgentCore Runtime + DistributedTable ×2 + FileBucket; drop SQS/AppSync from AWS Services; replace the stream()→AsyncJob→Realtime flow with the streamSSE() generator + its transports (browser WebSocket, /invocations SSE, local dev SSE).
PR #1 ships only the /invocations (HTTP+SSE) AWS path and the local-dev SSE route; the browser-direct WebSocket (/ws) path lands in the next PR. Remove the /ws branch, the dangling 'browser WebSocket path' reference, and the 'browser streams to' phrasing from getStreamEndpoint so the doc matches the code in this PR.
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.
Stacked PR 1 of 5 — the core migration. Layers on top: #251 WebSocket streaming, #252 README, #261 server-resolved tool context, #262 runtime-role BB grants.
Problem
The Agent BB ran its streaming loop on Lambda + SQS + Realtime (API Gateway WebSocket). The fundamental ceiling is Lambda's 15-minute max execution — long-running / multi-step agents were not achievable on AWS. Bedrock AgentCore Runtime (sessions up to 8h, native streaming) is purpose-built for this.
Scope of this PR (read first)
This is the foundation layer, not the end state. It lands the
streamSSE()API, removes Realtime/AsyncJob, and provisions the AgentCore Runtime (co-bundled + serveable). What it does NOT yet do: wire the browser to AgentCore. On this PR alone, the browser still reaches the agent through buffered RPC — the Lambda callsstreamSSE(), drains the full generator, and returns the chunks in one response. So:ws-transport+/wshandler +getStreamEndpointconsumption), which stacks on this PR.In other words: #250 is a regression-free foundation; #250 + #251 together are the actual migration. Don't ship #250 alone as "the AgentCore migration." Reviewers: this is why there is no client WebSocket code here — it's intentionally in #251.
Changes (breaking)
streamSSE(message, options?)— a transport-agnostic async generator. SharedstreamAgent()core owns the Strands loop + DynamoDB/S3 history persistence (incl. HITL approval records).stream()/resume()kept as@deprecatedcompatibility wrappers (async-iterable +complete()).getChannel(),channel/channelIdon the result are gone;resume()drops its leadingchannelIdarg.index.cdk.tsprovisions an AgentCoreRuntimeviafromCodeAsset()(Node 22 CodeZip, no Docker) + synth-time co-bundle of the app backend (agentcore-bundle.ts); no more Realtime/AsyncJob.agentcore-entry.tshosts the agent on thebedrock-agentcoreharness (/invocations+/ping);dev-stream.tsserves the equivalent SSE route locally.getStreamEndpoint()is added onAgentBase(AWS override returns the runtime endpoint; base/mock throws a clear AWS-only error) — the consumer of it ships in feat(bb-agent): browser-direct WebSocket streaming + server-verified identity (2/5) #251.useChatconsumes a singlestreamChunkstransport seam (the local/buffered transport here; the WebSocket transport in feat(bb-agent): browser-direct WebSocket streaming + server-verified identity (2/5) #251).__BLOCKS_DEV_ROUTE_HANDLERS__hook +BlocksStack.backendModulePath.Validation
bb-agentbuild clean + 77 tests pass;npm run lintclean;API.mdregenerated. CDK synth test assertsAWS::BedrockAgentCore::Runtimeis emitted (verifiedaws-cdk-lib@2.257.0exports the constructs). Rebased onto currentmain(reconciled with the lazy-load-Strands refactor #153).Merge order (stacked PRs — read before merging)
These five PRs stack: #250 → #251 → #252 → #261 → #262, each targeting the one below for a clean per-layer diff. They all ultimately merge into
main, bottom-up — do NOT merge them into each other.This repo squash-merges, so promoting each upper PR needs a base retarget plus a rebase (squash gives
mainnew commit SHAs, so a plain retarget would re-show the lower layer's diff).main(this PR; already targetsmain). Squash-merge.git fetch origin # In the GitHub UI: change #251 base agentcore/1-core -> main git switch agentcore/2-websocket-identity git rebase --onto origin/main agentcore/1-core agentcore/2-websocket-identity git push --force-with-leasemain.git fetch origin # In the GitHub UI: change #252 base agentcore/2-websocket-identity -> main git switch agentcore/3-docs git rebase --onto origin/main agentcore/2-websocket-identity agentcore/3-docs git push --force-with-leasemain.git fetch origin # In the GitHub UI: change #261 base agentcore/3-docs -> main git switch agentcore/4-tool-context git rebase --onto origin/main agentcore/3-docs agentcore/4-tool-context git push --force-with-leasemain.git fetch origin # In the GitHub UI: change #262 base agentcore/4-tool-context -> main git switch agentcore/5-runtime-role-grants git rebase --onto origin/main agentcore/4-tool-context agentcore/5-runtime-role-grants git push --force-with-leasemain.Notes:
streamSSEcode; fix(agent): AgentCore runtime role inherits the handler's BB grants (5/5) #262 (runtime-role BB grants) is the capstone — the migration isn't functionally complete for agents whose tools use other BBs without it. Merge bottom-up only.mainmoves; the E2E Sandbox job can flake on transient AWS API-Gateway 429 throttles — re-run if it fails on that.git worktree removethe split worktree; the frozen original branch can then be deleted.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.