fix(typescript): typescript agent template and streaming fixes#981
Conversation
Package TarballHow to installnpm install https://github.com/aws/agentcore-cli/releases/download/pr-981-tarball/aws-agentcore-0.13.1.tgz |
|
Local traces isnt working - need to auto instrument like we do with python agents |
|
Note: just saw your PR to fix SDK to not use hardcoded 8080 port. Once that's merged, I will make the corresponding change here in the web ui start.ts |
|
merged in the 8080 update in the typescript sdk - aws/bedrock-agentcore-sdk-typescript@25a5ef7 |
6f74483 to
8adf8f6
Compare
Mock fs module in node-packager tests since the packager now writes package.json and copies deps to the staging directory. Update asset snapshots for the new otel-register.ts template content.
- Change default entrypoint from main.ts to main.js (bundled output) - Relax process handler types to avoid esbuild type resolution issues - Add resolveNodeProjectPaths async helper for Node project packaging - Remove configBundles from CDK test fixture to match current schema
Import otel-register.js at the top of main.ts templates so OTEL instrumentation works both in agentcore dev (tsx runs main.ts directly) and deployed (esbuild inlines it into main.js). Removes the separate otel-register.js bundling step since it's now part of the main bundle.
….x compat The template package.json specifies @opentelemetry/resources ^1.30.1 which does not export resourceFromAttributes (a v2.x API). Use new Resource() which is the stable v1.x constructor.
The published bedrock-agentcore SDK (<=0.2.3) hardcodes port 8080 in BedrockAgentCoreApp.run(), ignoring both the port option and PORT env var. The web UI was assigning a dynamic port and then failing waitForServerReady because the agent always bound to 8080. Constraint: SDK run() hardcodes port 8080, port param not yet published Rejected: Build SDK from source | adds build complexity for a workaround Confidence: high Scope-risk: narrow
Three issues fixed: 1. Strands package.json missing model-provider-specific dependencies (@anthropic-ai/sdk, openai, @google/genai) — agents crashed on import. 2. Both Strands and VercelAI templates passed async getApiKey function reference where SDKs expected a resolved string. Refactored to await the key at initialization time with lazy-cached providers. 3. Strands OpenAI template missing required `api: 'chat'` parameter in OpenAIModel constructor. Also added fallback to standard env var names (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY) for local dev when the credential env var is not set. Constraint: withApiKey is async, SDKs expect sync string for apiKey Rejected: Pass function ref to SDK | SDKs don't support async apiKey Confidence: high Scope-risk: moderate Not-tested: deployed mode with withApiKey credential resolution
All 6 Container + non-Bedrock provider combinations (Strands and VercelAI with Anthropic, OpenAI, Gemini) pass Create, Dev (logs), and Invoke. Web UI mode verified working for Container non-Bedrock providers. Confidence: high Scope-risk: narrow
…sted - Strands+Container+Bedrock: deploy + invoke pass - Strands+Container+Anthropic: deploy passes, invoke fails (same credential resolution issue as CodeZip — Known Issue #1) - Remove + destroy lifecycle verified working Confidence: high Scope-risk: narrow
…templates The templates were calling withApiKey(config, fn)() which passes the callback as a second argument to withApiKey (ignored), then calls the returned HOF with no arguments — resulting in fn=undefined. When the inner wrapper executes, it returns the apiKey string via fn(...) which crashes or returns undefined, causing "Could not resolve authentication method" errors on deployed invoke. Fixed to withApiKey(config)(fn)() which correctly chains the HOF: config → wrapper(fn) → wrappedFn() → apiKey string. Constraint: withApiKey is a curried HOF, not a two-arg function Rejected: Inline the identity client call | breaks SDK abstraction Confidence: high Scope-risk: narrow Not-tested: OpenAI and Gemini deployed invoke (same code path, same fix)
Confidence: high Scope-risk: narrow
The web UI handler treated TS HTTP agents as needing a fixed port 8080. If 8080 was occupied, it errored instead of falling back. Now TS HTTP agents prefer 8080 but gracefully use the next available port, and the PORT env var is passed to the agent process. Also fixes flaky dev.test.ts tests that assumed port 8080 was free — they now target an unlikely-to-be-used port so connection-refused behavior is deterministic. Constraint: TS agent templates read process.env.PORT ?? '8080' Rejected: Keep fixed port for TS HTTP | breaks dev when 8080 is occupied Confidence: high Scope-risk: narrow
Add end-to-end tests for TypeScript agent templates with Bedrock: - ts-strands-bedrock: full lifecycle test for TypeScript + Strands - ts-vercelai-bedrock: full lifecycle test for TypeScript + VercelAI - e2e-helper: add language option to support TypeScript projects Constraint: Deploy will fail until AgentCore service accepts NODE_* for CodeZip Confidence: high Scope-risk: narrow
Add skipObservability option to e2e helper to skip logs/traces tests that don't meaningfully validate trace content.
The published SDK v0.2.2 hardcoded PORT=8080, ignoring the port option passed by app.run(). SDK v0.2.4 respects options.port, which is required for the port fallback fix to work end-to-end. Constraint: SDK must accept port option for CLI port fallback to function Confidence: high Scope-risk: narrow
The project name was shown twice — once in the screen header and once in the create-prompt body. Removed the body duplicate.
Allows specifying which CDK repo branch to build from in E2E tests via workflow_dispatch. Defaults to main for PR runs. Useful when CLI changes depend on unreleased CDK features.
This reverts commit 816cef4.
This reverts commit 19fdf00.
…plates Simplifies TypeScript starter templates by removing OpenTelemetry instrumentation, session storage file tools, and gateway MCP client conditionals. Keeps a simple MCP client example for discoverability. Also addresses PR feedback: remove stale handoff/bugbash docs and fix "Strands-only" references to include Vercel AI.
Remove special-case that preferred port 8080 for TypeScript HTTP agents. Now uses the same uiPort+1+index scheme as Python agents, avoiding unnecessary 8080 collisions.
VercelAI was fully supported in the codebase (schema, templates, assets, validation) but missing from user-facing help strings and docs.
The error said "Python package dependency" even for TypeScript projects. The reserved list is language-agnostic, so the message should be too.
TypeScript agents don't support observability/traces. This change: - Adds `supportsTraces` boolean to InvokeConfig runtimes, computed from entrypoint - Guards trace URL display on invoke screen behind `supportsTraces` - Skips transaction search setup on deploy when no Python agents exist - Returns early with clear error from `agentcore traces list/get` for TS agents Constraint: Only Python agents have OpenTelemetry instrumentation Rejected: Check language field | entrypoint is more reliable and already available Confidence: high Scope-risk: narrow
aidandaly24
left a comment
There was a problem hiding this comment.
Synthesized review from a 15-reviewer team pass
Thanks for the big push on TS support. I ran a multi-reviewer review (security, determinism, CDK design, cross-PR contract, tests, perf, template UX, silent failures, schema, dev UX, type design, observability, docs, SDK contract, maintainability) and verified the two most damaging findings against the actual published SDKs (@strands-agents/sdk@1.0.0-rc.4 and bedrock-agentcore@0.2.4 tarballs) before stamping severity.
2 CRITICAL findings (verified against published SDK type defs) — see inline
- Strands template's
tool({ ..., handler: ... })— SDK requirescallback, nothandler. The exampleaddNumberstool ships broken in every Strands TS scaffold (verified againstdist/src/tools/{function-tool,zod-tool}.d.ts). withApiKey({ providerName })(async (apiKey) => apiKey)()is misuse —withApiKeyis a HOF that injects apiKey, requiresworkloadIdentityTokenor a request-scopedcontext.workloadAccessToken, andloadModel()is called at module/agent-cache time before any context exists. Every non-Bedrock TS deploy will throw on first invocation (verified againstdist/src/identity/wrappers.d.ts+types.d.ts).
HIGH findings — see inline
- Entrypoint convention is incoherent across CLI persists / packager reads / Dockerfile uses / CDK writes — default scaffolds happen to work, BYO entrypoint customization is broken
- Strands
package.jsonships unused deps and README claims wrong framework - Strands stream-event filter has zero test (snapshot updates lockstep with template)
- README claims
0.0.0.0:8080but dev server uses dynamic ports; templates don't bind127.0.0.1 - Dockerfile
npm ci || npm installregenerates lockfile; runs lifecycle scripts; shipstsxtoolchain into prod agentcore devrunsnpm installwith full lifecycle scripts; pnpm/yarn detection produces misleading errorstsx watchorphan on Ctrl-C → ports stay bound across runs
HIGH findings on lines this PR doesn't directly touch (action requested but anchored to an unchanged file, so they live in the body)
src/cli/aws/__tests__/agentcore.test.ts:200 — stale Accept-header assertion. Production code (src/cli/aws/agentcore.ts:321, 417) was fixed to 'application/json, text/event-stream' in commit a21dbfda. The test still asserts expect(headers.Accept).toBe('application/json') and passes only because it constructs the helper with a different second arg than production does. No test verifies the SigV4 paths actually request both content types. Update assertion + add a regression test that mocks the SDK client and asserts accept includes text/event-stream.
src/cli/telemetry/schemas/common-shapes.ts:70 — Framework enum missing vercelai. This PR adds VercelAI as a first-class TS framework but the telemetry enum still only knows ['strands', 'langchain_langgraph', 'googleadk', 'openaiagents']. resilientParse replaces unknown values with 'unknown', so every agentcore create --framework VercelAI reports framework=unknown. Cannot measure VercelAI adoption or regression rate. Compounded by src/cli/commands/deploy/utils.ts:5-31 (computeDeployAttrs) having zero language attribution. Add 'vercelai' to Framework and extend computeDeployAttrs with has_typescript_runtime / frameworks: string[].
src/lib/packaging/helpers.ts:214,415 — CLI zip writer has no mtime pin. Both collectFiles and collectFilesSync pass [buffer, { level: 6 }] to fflate — no mtime. The CDK side at agentcore-l3-cdk-constructs/.../helpers.ts:368 pins mtime: new Date('1980-01-02T00:00:00Z') precisely to avoid this. Every CLI-driven CodeZip publish creates a new AgentCore Runtime version even with zero source changes. Mirror the CDK constant.
Top 3 things to look at yourself
- Reconcile the entrypoint contract end-to-end — picks a convention and unblocks customization for BYO TS users.
- Decide who owns
npm install— CLI runs it ondev/create, CDK construct doesn't, the bundler silently no-ops if deps missing. 'agentcore'regression inEXCLUDED_ENTRIES— paired CDK PR re-introduces a fix that was reverted in4883e1c.
Paired CDK review: aws/agentcore-l3-cdk-constructs#181.
The @strands-agents/sdk FunctionToolConfig requires `callback:`, not `handler:`. The incorrect field name caused the example addNumbers tool to silently never execute its function. Confidence: high Scope-risk: narrow
Remove @aws-sdk/client-s3, express, and zod — none are imported by the template code. Reduces install size and avoids zod version conflicts with VercelAI templates. Confidence: high Scope-risk: narrow
Remove incorrect "Fastify-based" description (SDK provides its own server) and replace hardcoded 0.0.0.0:8080 with accurate port info. Confidence: high Scope-risk: narrow
aidandaly24
left a comment
There was a problem hiding this comment.
Thanks for making the updates, tested some of these false positives out and they were indeed false positives. LGTM!
Description
Fixes several issues with TypeScript agent support in the CLI:
text/event-streamin the Accept header, breaking SSE streaming for HTTP agents.session.tscapability file from TypeScript templates.Related Issue
Closes #
Documentation PR
N/A
Type of Change
Testing
How have you tested the change?
npm run test:unitandnpm run test:integnpm run typechecknpm run lintsrc/assets/, I rannpm run test:update-snapshotsand committed the updated snapshotsChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.