[Update] TypeScript support in Strands Agents (preview) has been announced #AWSreInvent

[Update] TypeScript support in Strands Agents (preview) has been announced #AWSreInvent

2025.12.05

This page has been translated by machine translation. View original

Hello, this is Kakei (@takaakikakei).

Strands Agents is an agent framework provided by AWS. While Python development has been mainstream until now, with the announcement at AWS re:Invent 2025, development in TypeScript is now supported as a preview version. It enables TypeScript-native development with complete type safety, support for async/await, and utilizing the latest patterns. This is a welcome update for developers who regularly use TypeScript. In this article, I will create and run a simple agent using this new TypeScript SDK.

Official Documentation

The official documentation related to this update is as follows:

https://aws.amazon.com/jp/about-aws/whats-new/2025/12/typescript-strands-agents-preview/

https://github.com/strands-agents/sdk-typescript

Let's Try It

Project Creation

For this project, I'll use pnpm for package management.

pnpm init

To enable workspaces, create a pnpm-workspace.yaml file.

touch pnpm-workspace.yaml

The content of pnpm-workspace.yaml is as follows. minimumReleaseAge specifies the minimum elapsed time from package publication to installation in minutes. Here it's set to 5 days (7200 minutes). This helps mitigate supply chain attacks, but it means you won't be able to use the latest packages immediately, so adjust as needed.

packages:
  - 'apps/*'

minimumReleaseAge: 7200

For Linter and Formatter, I'll use Biome.

pnpm add -D -E @biomejs/biome
pnpm exec biome init

Add the following scripts to package.json. This allows you to run Biome checks and auto-fixes with the pnpm run check:fix command.

package.json
"scripts": {
  "check:fix": "biome check --write"
}

Adding Strands Agents

Install the Strands Agents TypeScript SDK and related libraries. Since the TypeScript SDK has just been released, adjust the minimumReleaseAge setting as needed.

pnpm add @strands-agents/sdk zod
pnpm add -D @types/node typescript tsx

Create apps/agent.ts.

mkdir apps
touch apps/agent.ts

The current folder structure is as follows:

.
├── apps
│   └── agent.ts
├── biome.json
├── node_modules
├── package.json
├── pnpm-lock.yaml
└── pnpm-workspace.yaml

Referencing the implementation in the official documentation, write the following code in apps/agent.ts.

apps/agent.ts
// Define a custom tool as a TypeScript function
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. Performs case-insensitive matching.',
  // Zod schema for letter counter input validation
  inputSchema: z
    .object({
      word: z.string().describe('The input word to search in'),
      letter: z.string().describe('The specific letter to count'),
    })
    .refine((data) => data.letter.length === 1, {
      message: "The 'letter' parameter must be a single character",
    }),
  callback: (input) => {
    const { word, letter } = input

    // Convert both to lowercase for case-insensitive comparison
    const lowerWord = word.toLowerCase()
    const lowerLetter = letter.toLowerCase()

    // Count occurrences
    let count = 0
    for (const char of lowerWord) {
      if (char === lowerLetter) {
        count++
      }
    }

    // Return result as string (following the pattern of other tools in this project)
    return `The letter '${letter}' appears ${count} time(s) in '${word}'`
  },
})

// Create an agent with tools with our custom letterCounter tool
const agent = new Agent({
  tools: [letterCounter],
})

// Ask the agent a question that uses the available tools
const message = `Tell me how many letter R's are in the word "strawberry" 🍓`
const result = await agent.invoke(message)
console.log(result.lastMessage)

https://strandsagents.com/latest/documentation/docs/user-guide/quickstart/typescript/#project-setup

Add a script to package.json to run the development server locally. This allows you to execute apps/agent.ts with the pnpm run dev command.

package.json
"scripts": {
  "dev": "tsx apps/agent.ts",
}

Also, the code above uses top-level await which is not supported in CommonJS format projects. Add "type": "module" to package.json to treat it as ESM.

package.json
{
  "type": "module",
}

Running Strands Agents

After switching to the appropriate AWS profile, run the agent with the following command:

pnpm run dev

If you see output like the following, it was successful. Although we didn't specify a model in the code, currently Global Anthropic Claude Sonnet 4.5 is used by default.

🔧 Tool #1: letter_counter
✓ Tool completed
Auto-detected includeToolResultStatus=true for model: global.anthropic.claude-sonnet-4-5-20250929-v1:0
There are **3** letter R's in the word "strawberry" 🍓

They appear in these positions:
- st**r**awberry (position 3)
- strawbe**rr**y (positions 8 and 9)Message {
  type: 'message',
  role: 'assistant',
  content: [
    TextBlock {
      type: 'textBlock',
      text: `There are **3** letter R's in the word "strawberry" 🍓\n` +
        '\n' +
        'They appear in these positions:\n' +
        '- st**r**awberry (position 3)\n' +
        '- strawbe**rr**y (positions 8 and 9)'
    }
  ]
}

You can check all these changes in the GitHub repository below:

https://github.com/takaakikakei/try-ts-strands/releases/tag/1.0.0

Specifying a Model

You can also explicitly specify a model using BedrockModel from @strands-agents/sdk. Add the model option to the Agent constructor as follows. This time, let's specify the newly introduced Amazon Nova 2 Lite for cross-region inference in Japan.

apps/agent.ts
import { BedrockModel } from '@strands-agents/sdk'

// ..snip..

const bedrockModel = new BedrockModel({
  modelId: "jp.amazon.nova-2-lite-v1:0",
  region: "ap-northeast-1",
});

// Create an agent with tools with our custom letterCounter tool
const agent = new Agent({
  model: bedrockModel,
  tools: [letterCounter],
});

Running pnpm run dev again shows that Nova 2 Lite is being used.

🔧 Tool #1: letter_counter
✓ Tool completed
Auto-detected includeToolResultStatus=false for model: jp.amazon.nova-2-lite-v1:0
The letter **R** appears **3 time(s)** in the word **"strawberry"**. 🍓Message {
  type: 'message',
  role: 'assistant',
  content: [
    TextBlock {
      type: 'textBlock',
      text: 'The letter **R** appears **3 time(s)** in the word **"strawberry"**. 🍓'
    }
  ]
}

You can check these changes in the GitHub repository below:

https://github.com/takaakikakei/try-ts-strands/releases/tag/1.0.1

Adding MCP

Let's also add a feature using MCP (Model Context Protocol) as a Tool. We'll use the AWS Knowledge MCP Server to retrieve the latest AWS documentation information.

https://awslabs.github.io/mcp/servers/aws-knowledge-mcp-server

First, install the MCP SDK:

pnpm add @modelcontextprotocol/sdk

Next, add and modify the following code in apps/agent.ts:

apps/agent.ts
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { McpClient } from "@strands-agents/sdk";

// ..snip..

const awsKnowledgeMcpClient = new McpClient({
  transport: new StreamableHTTPClientTransport(
    new URL("https://knowledge-mcp.global.api.aws"),
  ),
});

// ..snip..

const agent = new Agent({
  model: bedrockModel,
  tools: [letterCounter, awsKnowledgeMcpClient],
});

const message = `AgentCore Policyとは何ですか?`;

Running pnpm run dev again shows that the response is generated based on information from the AWS Knowledge MCP Server in the Tool call at the beginning.

🔧 Tool #1: aws___search_documentation
✓ Tool completed
Auto-detected includeToolResultStatus=false for model: jp.amazon.nova-2-lite-v1:0
### AgentCore Policyとは?

**AgentCore Policy**は、AWS Bedrock AgentCoreで提供されるセキュリティソリューションであり、AIエージェントがツールとやり取りする際のセキュリティコントロールを定義し、施行するためのものです。これは、AIエージェントの柔軟性によってもたらされる新しいセキュリティ課題に対処するために、エージェントの操作周囲に保護バリアを設けることを目的としています。

#### 主な特徴と機能

1. **保護バリアの作成**
   - エージェント操作周囲に保護バリアを設け、セキュリティリスクを軽減します。

2. **ポリシーエンジンによる評価**
   - Amazon Bedrock AgentCore Gatewayを介してエージェントトラフィックをインターセプトし、各リクエストを定義されたポリシーに対して評価します。

3. **Cedar言語または自然言語プロンプトによるポリシーの定義**
   - エージェントのアクションを正確に指定し、きめ細かい制御が可能になります。

4. **細かなアクセス制御**
   - エージェントのアクションに対する細かな制御が可能で、決定的な施行と強い保証を提供します。

5. **単純でアクセスしやすい著述**
   - 組織全体で一貫性のあるポリシーの作成が容易になります。

#### 主要な機能

- **ポリシーに基づくガバナンス**
  - ポリシーの施行、アクセス制御、ポリシーの著述、ポリシーの監視、インフラストラクチャ統合、オーディットログなどを提供します。

- **Cedarポリシー言語**
  - ポリシーはCedar言語または自然言語プロンプトを使用して作成され、具体的なアクションと条件を指定できます。

- **エージェントへの適用**
  - エージェントがGatewayを介してツールにアクセスする際に、ポリシーを評価し、許可または拒否を決定します。

- **監視とログ記録**
  - ポリシーの実行状況を監視し、オーディットログを記録してセキュリティイベントを追跡します。

#### 適用例

- **リファンダ処理ツールの制限**
  - リファンダ金額が特定の限度以下の場合にのみ、リファンダを処理するようポリシーを設定できます。

- **ユーザーのロールベースのアクセス制御**
  - 特定のユーザーロールだけが特定のツールにアクセスできるように制限できます。

#### 利点

- **細かな制御**
  - エージェントのアクションを正確に制御できます。

- **決定的な施行**
  - ポリシーは確実に施行され、セキュリティリスクを軽減します。

- **アクセスしやすい著述**
  - 自然言語プロンプトを使用してポリシーを簡単に作成できます。

- **組織全体での一貫性**
  - 組織全体のセキュリティポリシーが一貫して適用されます。

#### 使用方法の概要

1. **ポリシーの作成**
   - Cedar言語または自然言語プロンプトを使用してポリシーを定義します。

2. **ポリシーエンジンの設定**
   - ポリシーエンジンをGatewayにアタッチし、ENFORCEモードで設定します。

3. **エージェントのテスト**
   - エージェントがGatewayを介してツールにアクセスする際のポリシーをテストします。

4. **監視とログ記録**
   - ポリシーの実行状況を監視し、オーディットログを記録します。

AgentCore Policyは、AIエージェントのセキュリティを強化し、組織のセキュリティポリシーを確実に適用するための強力なツールです。

You can check these changes in the GitHub repository below:

https://github.com/takaakikakei/try-ts-strands/releases/tag/1.0.2

Conclusion

Thank you for reading to the end.

Since it's still a preview version, caution is needed when using it in production environments, but this update must be welcome news for TypeScript users. I hope this article has been helpful to you.

See you next time!

https://strandsagents.com/latest/documentation/docs/user-guide/quickstart/typescript/

https://strandsagents.com/latest/documentation/docs/api-reference/typescript/

Share this article

FacebookHatena blogX

Related articles