Skip to content

TypeScript Strands エージェント

TypeScript Strands Agent を生成し、ツールを使用したAIエージェントを構築します。オプションで Amazon Bedrock AgentCore Runtime にデプロイできます。このジェネレーターは、WebSocket 上の tRPC を使用して、AgentCore の双方向ストリーミングサポートを活用し、リアルタイムで型安全な通信を実現します。

Strands は、AIエージェントを構築するための軽量なフレームワークです。主な機能は次のとおりです:

  • 軽量でカスタマイズ可能: シンプルなエージェントループで邪魔にならない
  • 本番環境対応: 完全な可観測性、トレーシング、スケールのためのデプロイオプション
  • モデルとプロバイダーに依存しない: さまざまなプロバイダーの多くの異なるモデルをサポート
  • コミュニティ主導のツール: コミュニティが提供する強力なツールセット
  • マルチエージェントサポート: エージェントチームや自律エージェントなどの高度な技術
  • 柔軟な対話モード: 会話、ストリーミング、非ストリーミングサポート

TypeScript Strands Agent は2つの方法で生成できます:

  1. インストール Nx Console VSCode Plugin まだインストールしていない場合
  2. VSCodeでNxコンソールを開く
  3. クリック Generate (UI) "Common Nx Commands"セクションで
  4. 検索 @aws/nx-plugin - ts#strands-agent
  5. 必須パラメータを入力
    • クリック Generate
    パラメータ デフォルト 説明
    project 必須 string - The project to add the Strands Agent to
    computeType string BedrockAgentCoreRuntime The type of compute to host your Strands Agent.
    name string - The name of your Strands Agent (default: agent)
    iacProvider string Inherit The preferred IaC provider. By default this is inherited from your initial selection.

    ジェネレーターは、既存の TypeScript プロジェクトに次のファイルを追加します:

    • Directoryyour-project/
      • Directorysrc/
        • Directoryagent/ (指定した場合はカスタム名)
          • index.ts Bedrock AgentCore Runtime のエントリーポイント
          • init.ts tRPC の初期化
          • router.ts エージェントプロシージャを含む tRPC ルーター
          • agent.ts サンプルツールを含むメインエージェント定義
          • client.ts エージェントを呼び出すための提供されたクライアント
          • agent-core-trpc-client.ts AgentCore Runtime 上のエージェントに接続するためのクライアントファクトリー
          • agent-core-mcp-client.ts AgentCore Runtime 上の MCP サーバーに接続するためのクライアントファクトリー
          • Dockerfile エージェントをホストするためのエントリーポイント (computeTypeNone に設定されている場合は除外)
      • package.json Strands 依存関係で更新
      • project.json エージェント serve ターゲットで更新

    このジェネレータは選択した iacProvider に基づいてInfrastructure as Codeを生成するため、packages/common に関連するCDKコンストラクトまたはTerraformモジュールを含むプロジェクトを作成します。

    共通のInfrastructure as Codeプロジェクトは以下の構造を持ちます:

    • Directorypackages/common/constructs
      • Directorysrc
        • Directoryapp/ プロジェクト/ジェネレータ固有のインフラストラクチャ用コンストラクト
        • Directorycore/ app 内のコンストラクトで再利用される汎用コンストラクト
        • index.ts app からコンストラクトをエクスポートするエントリーポイント
      • project.json プロジェクトのビルドターゲットと設定

    Strands Agent をデプロイするために、次のファイルが生成されます:

    • Directorypackages/common/constructs/src
      • Directoryapp
        • Directoryagents
          • Directory<project-name>
            • <project-name>.ts エージェントをデプロイするための CDK コンストラクト
            • Dockerfile CDK コンストラクトで使用されるパススルー docker ファイル

    TypeScript Strands Agent は、WebSocket 上の tRPC を使用し、AgentCore の双方向ストリーミングサポートを活用して、クライアントとエージェント間のリアルタイムで型安全な通信を実現します。

    tRPC は WebSocket 上で Query、Mutation、Subscription プロシージャをサポートしているため、任意の数のプロシージャを定義できます。デフォルトでは、router.tsinvoke という名前の単一のサブスクリプションプロシージャが定義されています。

    ツールは、AIエージェントがアクションを実行するために呼び出すことができる関数です。agent.ts ファイルに新しいツールを追加できます:

    import { Agent, tool } from '@strands-agents/sdk';
    import z from 'zod';
    const letterCounter = tool({
    name: 'letter_counter',
    description: 'Count occurrences of a specific letter in a word',
    inputSchema: z.object({
    word: z.string().describe('The input word to search in'),
    letter: z.string().length(1).describe('The specific letter to count'),
    }),
    callback: (input) => {
    const { word, letter } = input;
    const count = word.toLowerCase().split(letter.toLowerCase()).length - 1;
    return `The letter '${letter}' appears ${count} time(s) in '${word}'`;
    },
    });
    // エージェントにツールを追加
    export const agent = new Agent({
    systemPrompt: 'You are a helpful assistant with access to various tools.',
    tools: [letterCounter],
    });

    Strands フレームワークは次を自動的に処理します:

    • Zod スキーマを使用した入力検証
    • ツール呼び出しのための JSON スキーマ生成
    • エラー処理とレスポンスのフォーマット

    デフォルトでは、Strands エージェントは Claude 4 Sonnet を使用しますが、モデルプロバイダー間を簡単に切り替えることができます:

    import { Agent } from '@strands-agents/sdk';
    import { BedrockModel } from '@strands-agents/sdk/models/bedrock';
    import { OpenAIModel } from '@strands-agents/sdk/models/openai';
    // Bedrock を使用
    const bedrockModel = new BedrockModel({
    modelId: 'anthropic.claude-sonnet-4-20250514-v1:0',
    });
    let agent = new Agent({ model: bedrockModel });
    let response = await agent.invoke('What can you help me with?');
    // または、モデルプロバイダーを切り替えるだけで OpenAI を使用
    const openaiModel = new OpenAIModel({
    apiKey: process.env.OPENAI_API_KEY,
    modelId: 'gpt-4o',
    });
    agent = new Agent({ model: openaiModel });
    response = await agent.invoke('What can you help me with?');

    詳細な設定オプションについては、モデルプロバイダーに関する Strands ドキュメントを参照してください。

    Strands エージェントに MCP サーバーからツールを追加できます。

    py#mcp-server または ts#mcp-server ジェネレーターを使用して作成した MCP サーバー (または Bedrock AgentCore Runtime でホストされている他のサーバー) を使用する場合、agent-core-mcp-client.ts にクライアントファクトリーが生成されます。

    agent.ts でエージェントの初期化を更新して、MCP クライアントを作成してツールを追加できます。次の例は、IAM (SigV4) 認証でこれを実行する方法を示しています:

    agent.ts
    import { Agent } from '@strands-agents/sdk';
    import { AgentCoreMcpClient } from './agent-core-mcp-client.js';
    const mcpClient = AgentCoreMcpClient.withIamAuth({
    agentRuntimeArn: process.env.MCP_AGENTCORE_RUNTIME_ARN!,
    region: process.env.AWS_REGION || 'us-west-2',
    sessionId: 'my-session-id',
    });
    export const agent = new Agent({
    systemPrompt: '...',
    tools: [mcpClient],
    });

    上記の IAM 認証の例では、インフラストラクチャで2つのことを設定する必要があります。まず、MCP サーバーの AgentCore Runtime ARN に対してエージェントが使用している環境変数を追加する必要があり、次にエージェントに MCP サーバーを呼び出す権限を付与する必要があります。これは次のように実現できます:

    import { MyProjectAgent, MyProjectMcpServer } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const mcpServer = new MyProjectMcpServer(this, 'MyProjectMcpServer');
    const agent = new MyProjectAgent(this, 'MyProjectAgent', {
    environmentVariables: {
    MCP_AGENTCORE_RUNTIME_ARN: mcpServer.agentCoreRuntime.agentRuntimeArn,
    },
    });
    mcpServer.agentCoreRuntime.grantInvoke(agent.agentCoreRuntime);
    }
    }

    Strands エージェントの作成に関する詳細なガイドについては、Strands ドキュメントを参照してください。

    ジェネレーターは <your-agent-name>-serve という名前のターゲットを設定し、開発とテストのために Strands Agent をローカルで起動します。

    Terminal window
    pnpm nx run your-project:agent-serve

    このコマンドは tsx --watch を使用して、ファイルが変更されたときにサーバーを自動的に再起動します。エージェントは http://localhost:8081 (または複数のエージェントがある場合は割り当てられたポート) で利用可能になります。

    Strands Agent を Bedrock AgentCore Runtime にデプロイ

    Section titled “Strands Agent を Bedrock AgentCore Runtime にデプロイ”

    computeTypeBedrockAgentCoreRuntimeを選択した場合、関連するCDKまたはTerraformインフラストラクチャが生成され、Strands AgentをAmazon Bedrock AgentCore Runtimeにデプロイするために使用できます。

    エージェント用のCDKコンストラクトが生成されます。名前はジェネレーター実行時に選択したnameに基づくか、デフォルトでは<ProjectName>Agentになります。

    このCDKコンストラクトをCDKアプリケーションで使用できます:

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    // Add the agent to your stack
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    // Grant permissions to invoke the relevant models in bedrock
    agent.agentCoreRuntime.addToRolePolicy(
    new PolicyStatement({
    actions: [
    'bedrock:InvokeModel',
    'bedrock:InvokeModelWithResponseStream',
    ],
    // You can scope the below down to the specific models you use
    resources: [
    'arn:aws:bedrock:*:*:foundation-model/*',
    'arn:aws:bedrock:*:*:inference-profile/*',
    ],
    }),
    );
    }
    }

    デフォルトでは、Strands AgentはIAM認証を使用して保護されます。引数なしで単純にデプロイしてください:

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    new MyProjectAgent(this, 'MyProjectAgent');
    }
    }

    grantInvokeメソッドを使用して、Bedrock AgentCore Runtime上でエージェントを呼び出すアクセス権を付与できます。例:

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    const lambdaFunction = new Function(this, ...);
    agent.agentCoreRuntime.grantInvoke(lambdaFunction);
    }
    }

    以下は、エージェントのCognito認証を設定する方法を示しています。

    Cognitoを使用してJWT認証を設定するには、RuntimeAuthorizerConfiguration.usingCognito()ファクトリメソッドを使用します:

    import { MyProjectAgent } from ':my-scope/common-constructs';
    import { RuntimeAuthorizerConfiguration } from '@aws-cdk/aws-bedrock-agentcore-alpha';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const userPool = new UserPool(this, 'UserPool');
    const client = userPool.addClient('Client', {
    authFlows: {
    userPassword: true,
    },
    });
    new MyProjectAgent(this, 'MyProjectAgent', {
    authorizerConfiguration: RuntimeAuthorizerConfiguration.usingCognito(
    userPool,
    [client],
    ),
    });
    }
    }

    または、独自のOIDCプロバイダーを使用したカスタムJWT認証の場合は、RuntimeAuthorizerConfiguration.usingJWT()を使用します:

    import { MyProjectAgent } from ':my-scope/common-constructs';
    import { RuntimeAuthorizerConfiguration } from '@aws-cdk/aws-bedrock-agentcore-alpha';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    new MyProjectAgent(this, 'MyProjectAgent', {
    authorizerConfiguration: RuntimeAuthorizerConfiguration.usingJWT(
    'https://example.com/.well-known/openid-configuration',
    ['client1', 'client2'], // Allowed Client IDs (optional)
    ['audience1'], // Allowed Audiences (optional)
    ),
    });
    }
    }

    ジェネレーターは自動的に Rolldown を使用する bundle ターゲットを設定します。このターゲットはデプロイメントパッケージの作成に使用されます:

    Terminal window
    pnpm nx run <project-name>:bundle

    Rolldownの設定はrolldown.config.tsに記述され、生成するバンドルごとにエントリを定義します。Rolldownは定義された複数のバンドルを並行して作成する処理を管理します。

    bundle ターゲットは、Bedrock AgentCore Runtime でホストする WebSocket サーバーのエントリーポイントとして index.ts を使用します。

    ジェネレーターは <your-agent-name>-docker ターゲットを設定し、AgentCore ランタイムコントラクトに従ってポート 8080 でバンドルされた WebSocket サーバーを実行します。

    複数のエージェントが定義されている場合、すべてのエージェントに対して docker ビルドを実行する docker ターゲットも生成されます。

    エージェントは、Dockerfile で自動計装を設定することにより、AWS Distro for Open Telemetry (ADOT) を使用した可観測性で自動的に構成されます。

    CloudWatch AWS コンソールでトレースを見つけるには、メニューで “GenAI Observability” を選択します。トレースを入力するには、Transaction Search を有効にする必要があることに注意してください。

    詳細については、可観測性に関する AgentCore ドキュメントを参照してください。

    エージェント通信は、WebSocket 上の tRPC を介して送信されます。そのため、client.ts で生成された型安全なクライアントファクトリーを使用することをお勧めします。

    クライアントファクトリーの .local ファクトリーメソッドを使用して、ローカルで実行されているエージェントを呼び出すことができます。

    たとえば、ワークスペースに scripts/test.ts という名前のファイルを作成し、クライアントをインポートできます:

    scripts/test.ts
    import { AgentClient } from '../packages/<project>/src/agent/client.js';
    const client = AgentClient.local({ url: 'http://localhost:8081/ws' });
    client.invoke.subscribe({ message: 'what is 1 plus 1?' }, { onData: console.log });

    デプロイされたエージェントの呼び出し

    Section titled “デプロイされたエージェントの呼び出し”

    Bedrock AgentCore Runtimeにデプロイされたエージェントを呼び出すには、URLエンコードされたランタイムARNを使用して、Bedrock AgentCore RuntimeデータプレーンエンドポイントにPOSTリクエストを送信します。

    ランタイムARNは、以下のようにインフラストラクチャから取得できます:

    import { CfnOutput } from 'aws-cdk-lib';
    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    new CfnOutput(this, 'AgentArn', {
    value: agent.agentCoreRuntime.agentRuntimeArn,
    });
    }
    }

    ARNは次の形式になります: arn:aws:bedrock-agentcore:<region>:<account>:runtime/<agent-runtime-id>

    次に、:%3Aに、/%2Fに置き換えることで、ARNをURLエンコードできます。

    エージェントを呼び出すためのBedrock AgentCore RuntimeデータプレーンURLは次のとおりです:

    https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations

    このURLを呼び出す正確な方法は、使用する認証方法によって異なります。

    生成された client.ts ファイルには、デプロイされたエージェントを呼び出すために使用できる型安全なクライアントファクトリーが含まれています。

    withIamAuth ファクトリーメソッドに ARN を渡すことで、デプロイされたエージェントを呼び出すことができます:

    import { AgentClient } from './agent/client.js';
    const client = AgentClient.withIamAuth({
    agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent',
    });
    client.invoke.subscribe({ message: 'what is 1 plus 1?' }, {
    onData: (message) => console.log(message),
    onError: (error) => console.error(error),
    onComplete: () => console.log('Done'),
    });

    JWT / Cognito アクセストークンで認証するには、withJwtAuth ファクトリーメソッドを使用します。

    const client = AgentClient.withJwtAuth({
    agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent',
    accessTokenProvider: async () => `<access-token>`,
    });
    client.invoke.subscribe({ message: 'what is 1 plus 1?' }, {
    onData: console.log,
    });

    accessTokenProvider は、リクエストの認証に使用されるトークンを返す必要があります。たとえば、tRPC が WebSocket 接続を再起動するときに新しい認証情報が再利用されるように、このメソッド内でトークンを取得できます。以下は、AWS SDK を使用して Cognito からトークンを取得する方法を示しています:

    import { CognitoIdentityProvider } from "@aws-sdk/client-cognito-identity-provider";
    const cognito = new CognitoIdentityProvider();
    const jwtClient = AgentClient.withJwtAuth({
    agentRuntimeArn: 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent',
    accessTokenProvider: async () => {
    const response = await cognito.adminInitiateAuth({
    UserPoolId: '<user-pool-id>',
    ClientId: '<user-pool-client-id>',
    AuthFlow: 'ADMIN_NO_SRP_AUTH',
    AuthParameters: {
    USERNAME: '<username>',
    PASSWORD: '<password>',
    },
    });
    return response.AuthenticationResult!.AccessToken!;
    },
    });

    ブラウザの WebSocket は (Sec-WebSocket-Protocol 以外の) ヘッダーの指定をサポートしていないため、client.ts で生成されたクライアントファクトリーはブラウザでは使用できません (実際には、NodeJS のように WebSocket コンストラクターがヘッダーを受け入れないため、コンパイルエラーが発生します)。

    ブラウザからエージェントを呼び出すには、AWS SigV4 を使用して事前署名された WebSocket URL を作成する必要があります。

    以下の例は、認証情報の取得、事前署名された URL の作成、エージェントの呼び出しのエンドツーエンドフローを示しています:

    import { createTRPCClient, createWSClient, wsLink } from '@trpc/client';
    import { AwsClient } from 'aws4fetch';
    import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity';
    import { fromCognitoIdentityPool } from '@aws-sdk/credential-provider-cognito-identity';
    import type { AppRouter } from './your-agent/router';
    // 事前署名された WebSocket URL を構築
    async function buildSignedUrl(
    agentRuntimeArn: string,
    idToken: string,
    region: string = 'us-west-2'
    ): Promise<string> {
    // Cognito Identity Pool (または他のソース) から認証情報を取得
    const credentials = fromCognitoIdentityPool({
    client: new CognitoIdentityClient({ region }),
    identityPoolId: 'us-west-2:xxxxx',
    logins: {
    [`cognito-idp.${region}.amazonaws.com/us-west-2_xxxxx`]: idToken,
    },
    });
    const cognitoIdentity = new CognitoIdentityClient({ credentials });
    const credential = await cognitoIdentity.config.credentials();
    // AWS SigV4 クライアントを作成
    const awsClient = new AwsClient({
    ...credential,
    service: 'bedrock-agentcore',
    });
    // ARN から WebSocket URL を構築
    const wsUrl = `wss://bedrock-agentcore.${region}.amazonaws.com/runtimes/${agentRuntimeArn.replace(/:/g, '%3A').replace(/\//g, '%2F')}/ws`;
    // 事前署名された URL を作成
    const signedRequest = await awsClient.sign(wsUrl, {
    method: 'GET',
    aws: { signQuery: true },
    });
    return signedRequest.url;
    }
    // 事前署名された WebSocket URL で tRPC クライアントを作成
    const agentRuntimeArn = 'arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/my-agent';
    const idToken = '<your-id-token>';
    const wsClient = createWSClient({
    url: async () => buildSignedUrl(agentRuntimeArn, idToken),
    });
    const trpcClient = createTRPCClient<AppRouter>({
    links: [wsLink({ client: wsClient })],
    });
    // エージェントを呼び出す
    trpcClient.invoke.subscribe({ message: 'what is 1 plus 1?' }, {
    onData: (message) => console.log(message),
    });