Skip to content

TypeScript Quickstart

Experimental SDK

The TypeScript SDK is currently experimental. It does not yet support all features available in the Python SDK, and breaking changes are expected as development continues. Use with caution in production environments.

This quickstart guide shows you how to create your first basic Strands agent with TypeScript, add built-in and custom tools to your agent, use different model providers, emit debug logs, and run the agent locally.

After completing this guide you can integrate your agent with a web server or browser, evaluate and improve your agent, along with deploying to production and running at scale.

Install the SDK

First, ensure that you have Node.js 20+ and npm installed. See the npm documentation for installation instructions.

Create a new directory for your project and initialize it:

mkdir my-agent
cd my-agent
npm init -y

Learn more about the npm init command and its options.

Next, install the @strands-agents/sdk package:

npm install @strands-agents/sdk

The Strands Agents SDK includes optional vended tools that are built-in and production-ready for your agents to use. These tools can be imported directly as follows:

import { bash } from '@strands-agents/sdk/vended_tools/bash'

Configuring Credentials

Strands supports many different model providers. By default, agents use the Amazon Bedrock model provider with the Claude 4 model.

To use the examples in this guide, you'll need to configure your environment with AWS credentials that have permissions to invoke the Claude 4 model. You can set up your credentials in several ways:

  1. Environment variables: Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and optionally AWS_SESSION_TOKEN
  2. AWS credentials file: Configure credentials using aws configure CLI command
  3. IAM roles: If running on AWS services like EC2, ECS, or Lambda, use IAM roles
  4. Bedrock API keys: Set the AWS_BEARER_TOKEN_BEDROCK environment variable

Make sure your AWS credentials have the necessary permissions to access Amazon Bedrock and invoke the Claude 4 model.

Project Setup

Now we'll continuing building out the nodejs project by adding TypeScript to the project where our agent will reside. We'll use this directory structure:

my-agent/
├── src/
│   └── agent.ts
├── package.json
└── README.md

Create the directory: mkdir src

Install the dev dependencies:

npm install --save-dev @types/node typescript

And finally our src/agent.ts file where the goodies are:

// 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)

This basic quickstart agent can now count letters in words. The agent automatically determines when to use tools based on the input query and context.

flowchart LR
    A[Input & Context] --> Loop

    subgraph Loop[" "]
        direction TB
        B["Reasoning (LLM)"] --> C["Tool Selection"]
        C --> D["Tool Execution"]
        D --> B
    end

    Loop --> E[Response]

More details can be found in the Agent Loop documentation.

Running Agents

Our agent is just TypeScript, so we can run it using Node.js, Bun, Deno, or any TypeScript runtime!

To test our agent, we'll use tsx to run the file on Node.js:

npx tsx src/agent.ts

And that's it! We now have a running agent with powerful tools and abilities in just a few lines of code 🥳.

Understanding What Agents Did

After running an agent, you can understand what happened during execution by examining the agent's messages and through traces and metrics. Every agent invocation returns an AgentResult object that contains the data the agent used along with (comming soon) comprehensive observability data.

// Access the agent's message array
const result = await agent.invoke('What is the square root of 144?')
console.log(agent.messages)

Console Output

Agents display their reasoning and responses in real-time to the console by default. You can disable this output by setting printer: false when creating your agent:

const quietAgent = new Agent({
  tools: [letterCounter],
  printer: false, // Disable console output
})

Model Providers

Identifying a configured model

Strands defaults to the Bedrock model provider using Claude 4 Sonnet. The model your agent is using can be retrieved by accessing model.config:

// Check the model configuration
const myAgent = new Agent()
console.log(myAgent['model'].getConfig().modelId)
// Output: { modelId: 'global.anthropic.claude-sonnet-4-5-20250929-v1:0' }

You can specify a different model by creating a model provider instance with specific configurations

Amazon Bedrock (Default)

For more control over model configuration, you can create a model provider instance:

import { BedrockModel } from '@strands-agents/sdk'

// Create a BedrockModel with custom configuration
const bedrockModel = new BedrockModel({
  modelId: 'anthropic.claude-sonnet-4-20250514-v1:0',
  region: 'us-west-2',
  temperature: 0.3,
})

const bedrockAgent = new Agent({ model: bedrockModel })

For the Amazon Bedrock model provider, AWS credentials are typically defined in AWS_ prefixed environment variables or configured with the aws configure CLI command.

You will also need to enable model access in Amazon Bedrock for the models that you choose to use with your agents, following the AWS documentation to enable access.

More details in the Amazon Bedrock Model Provider documentation.

Additional Model Providers

Strands Agents supports several other model providers beyond Amazon Bedrock:

  • OpenAI - Access to OpenAI or OpenAI-compatible models

Capturing Streamed Data & Events

Strands provides two main approaches to capture streaming events from an agent: async iterators and callback functions.

Async Iterators

For asynchronous applications (like web servers or APIs), Strands provides an async iterator approach using stream(). This is particularly useful with async frameworks like Express, Fastify, or NestJS.

// Async function that iterates over streamed agent events
async function processStreamingResponse() {
  const prompt = 'What is 25 * 48 and explain the calculation'

  // Stream the response as it's generated from the agent:
  for await (const event of agent.stream(prompt)) {
    console.log('Event:', event.type)
  }
}

// Run the streaming example
await processStreamingResponse()

The async iterator yields the same event types as the callback handler callbacks, including text generation events, tool events, and lifecycle events. This approach is ideal for integrating Strands agents with async web frameworks.

See the Async Iterators documentation for full details.

Next Steps

Ready to learn more? Check out these resources: