Skip to content

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.

Before using this generator, ensure you have:

  1. A React website (generated using the ts#react-website generator)
  2. A TypeScript Strands Agent (generated using the ts#strands-agent generator)
  3. Cognito Auth added via the ts#react-website-auth generator
  1. Install the Nx Console VSCode Plugin if you haven't already
  2. Open the Nx Console in VSCode
  3. Click Generate (UI) in the "Common Nx Commands" section
  4. Search for @aws/nx-plugin - connection
  5. Fill in the required parameters
    • Click Generate

    You 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.

    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.

    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-query
    • aws4fetch (if using IAM auth)

    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 local ws:// URL (e.g., ws://localhost:8081/ws), and the client connects directly

    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-local mode, signing is automatically skipped when runtime-config.json is not present
    • Cognito: Embeds the JWT access token in the Sec-WebSocket-Protocol header as a base64url-encoded bearer token, following the AgentCore WebSocket auth protocol

    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.

    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>
    );
    }

    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>
    );
    }

    The connection generator automatically configures serve-local integration for your react website:

    1. Running nx serve-local <website> will also start the agent’s local server
    2. The runtime config is overridden to point to the local WebSocket URL (e.g., ws://localhost:8081/ws)
    3. Like with connected APIs, authentication is skipped in serve-local mode when runtime-config.json is not present

    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.

    For more information, please refer to: