React to TypeScript Strands Agent
Nx Plugin for AWS provides a generator to quickly integrate your TypeScript Strands Agent with a React website. It sets up all necessary configuration for connecting to your agent via tRPC over WebSocket, including AWS IAM and Cognito authentication support. The integration provides full end-to-end type safety between your frontend and the agent’s tRPC router.
Prerequisites
Section titled “Prerequisites”Before using this generator, ensure you have:
- A React website (generated using the
ts#react-websitegenerator) - A TypeScript Strands Agent (generated using the
ts#strands-agentgenerator) - Cognito Auth added via the
ts#react-website-authgenerator
Run the Generator
Section titled “Run the Generator”- Install the Nx Console VSCode Plugin if you haven't already
- Open the Nx Console in VSCode
- Click
Generate (UI)in the "Common Nx Commands" section - Search for
@aws/nx-plugin - connection - Fill in the required parameters
- Click
Generate
pnpm nx g @aws/nx-plugin:connectionyarn nx g @aws/nx-plugin:connectionnpx nx g @aws/nx-plugin:connectionbunx nx g @aws/nx-plugin:connectionYou can also perform a dry-run to see what files would be changed
pnpm nx g @aws/nx-plugin:connection --dry-runyarn nx g @aws/nx-plugin:connection --dry-runnpx nx g @aws/nx-plugin:connection --dry-runbunx nx g @aws/nx-plugin:connection --dry-runYou will be prompted to select your React website as the source project and the project containing your Strands Agent as the target project. If your target project contains multiple components (such as multiple agents or other component types), you will be prompted to specify a targetComponent to disambiguate.
Options
Section titled “Options”| Parameter | Type | Default | Description |
|---|---|---|---|
| sourceProject Required | string | - | The source project |
| targetProject Required | string | - | The target project to connect to |
| sourceComponent | string | - | The source component to connect from (component name, path relative to source project root, or generator id). Use '.' to explicitly select the project as the source. |
| targetComponent | string | - | The target component to connect to (component name, path relative to target project root, or generator id). Use '.' to explicitly select the project as the target. |
Generator Output
Section titled “Generator Output”The generator creates the following structure in your React application:
Directorysrc
Directorycomponents
- <AgentName>AgentClientProvider.tsx Sets up the tRPC WebSocket client and bindings to your agent’s tRPC router
- QueryClientProvider.tsx TanStack React Query client provider
Directoryhooks
- useSigV4.tsx Hook for signing requests with SigV4 (IAM only)
- use<AgentName>Agent.tsx Hooks returning the tRPC options proxy and vanilla tRPC client
Additionally, it installs the required dependencies:
@trpc/client@trpc/tanstack-react-query@tanstack/react-queryaws4fetch(if using IAM auth)
How It Works
Section titled “How It Works”WebSocket Connection
Section titled “WebSocket Connection”The generated client connects to your Strands Agent via tRPC over WebSocket. The agent exposes a tRPC router (including the invoke subscription for streaming agent responses) over a WebSocket endpoint.
- Deployed: The agent runtime ARN is loaded from Runtime Configuration. The ARN is converted to a WebSocket URL following the Bedrock AgentCore Runtime WebSocket protocol:
wss://bedrock-agentcore.<region>.amazonaws.com/runtimes/<encoded-arn>/ws - Local development: When running with
serve-local, the runtime config override sets the value to a localws://URL (e.g.,ws://localhost:8081/ws), and the client connects directly
Authentication
Section titled “Authentication”The generated code handles authentication depending on your agent’s configuration:
- IAM (default): Uses AWS SigV4 presigned URLs to authenticate the WebSocket connection. Credentials are obtained from the Cognito Identity Pool configured with your website’s auth. In
serve-localmode, signing is automatically skipped whenruntime-config.jsonis not present - Cognito: Embeds the JWT access token in the
Sec-WebSocket-Protocolheader as a base64url-encoded bearer token, following the AgentCore WebSocket auth protocol
Infrastructure
Section titled “Infrastructure”If your agent uses IAM auth, the Cognito Identity Pool’s authenticated role must have the bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream permission to invoke agents via WebSocket:
const identity = new UserIdentity(this, 'Identity');const myAgent = new MyAgent(this, 'MyAgent');
identity.identityPool.authenticatedRole.addToPrincipalPolicy( new PolicyStatement({ actions: ['bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream'], resources: [myAgent.agentCoreRuntime.agentRuntimeArn], }),);If your agent uses Cognito auth, you do not need to define any additional infrastructure to connect your website to your agent.
Using the Generated Code
Section titled “Using the Generated Code”Using TanStack Query
Section titled “Using TanStack Query”The most common use case is streaming the agent’s response using the invoke subscription with the use<AgentName>Agent hook, which returns a tRPC options proxy for use with TanStack Query:
import { useSubscription } from '@trpc/tanstack-react-query';import { useMyAgentAgent } from './hooks/useMyAgentAgent';
function ChatComponent() { const trpc = useMyAgentAgent();
const subscription = useSubscription( trpc.invoke.subscriptionOptions( { message: 'What can you help me with?' }, { enabled: true, onStarted: () => { console.log('Agent started responding'); }, onData: (token) => { console.log('Received token:', token); }, onError: (error) => { console.error('Agent error:', error); }, }, ), );
return ( <div> <p>Status: {subscription.status}</p> {subscription.data && <p>Latest token: {subscription.data}</p>} {subscription.error && <p>Error: {subscription.error.message}</p>} </div> );}Using the Vanilla tRPC Client
Section titled “Using the Vanilla tRPC Client”The use<AgentName>AgentClient hook provides access to the vanilla tRPC client for more control over the subscription lifecycle:
import { useState } from 'react';import { useMyAgentAgentClient } from './hooks/useMyAgentAgent';
function ChatComponent() { const client = useMyAgentAgentClient(); const [messages, setMessages] = useState<string[]>([]);
const sendMessage = (message: string) => { const subscription = client.invoke.subscribe( { message }, { onData: (token) => { setMessages((prev) => [...prev, token]); }, onComplete: () => { console.log('Agent finished'); }, onError: (error) => { console.error('Error:', error); }, }, );
// Clean up when done return () => subscription.unsubscribe(); };
return ( <div> <button onClick={() => sendMessage('Hello!')}>Send</button> <div> {messages.map((msg, i) => ( <span key={i}>{msg}</span> ))} </div> </div> );}Local Development
Section titled “Local Development”The connection generator automatically configures serve-local integration for your react website:
- Running
nx serve-local <website>will also start the agent’s local server - The runtime config is overridden to point to the local WebSocket URL (e.g.,
ws://localhost:8081/ws) - Like with connected APIs, authentication is skipped in
serve-localmode whenruntime-config.jsonis not present
Type Safety
Section titled “Type Safety”The integration provides complete end-to-end type safety. Your IDE will provide full autocompletion and type checking for all agent procedure calls. The types are automatically inferred from your agent’s tRPC router definition, ensuring that any changes to your agent’s API are immediately reflected in your frontend code.
More Information
Section titled “More Information”For more information, please refer to: