TypeScript Quickstart
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
Section titled “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-agentcd my-agentnpm init -yLearn more about the npm init command and its options.
Next, install the @strands-agents/sdk package:
npm install @strands-agents/sdkThe 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
Section titled “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:
- Environment variables: Set
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionallyAWS_SESSION_TOKEN - AWS credentials file: Configure credentials using
aws configureCLI command - IAM roles: If running on AWS services like EC2, ECS, or Lambda, use IAM roles
- Bedrock API keys: Set the
AWS_BEARER_TOKEN_BEDROCKenvironment variable
Make sure your AWS credentials have the necessary permissions to access Amazon Bedrock and invoke the Claude 4 model.
Project Setup
Section titled “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.mdCreate the directory: mkdir src
Install the dev dependencies:
npm install --save-dev @types/node typescriptAnd finally our src/agent.ts file where the goodies are:
// Define a custom tool as a TypeScript functionimport { 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 toolconst agent = new Agent({ tools: [letterCounter],})
// Ask the agent a question that uses the available toolsconst 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
Section titled “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.tsAnd 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
Section titled “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 arrayconst result = await agent.invoke('What is the square root of 144?')console.log(agent.messages)Console Output
Section titled “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
Section titled “Model Providers”Identifying a configured model
Section titled “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 configurationconst 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)
Section titled “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 configurationconst 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
Section titled “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
Section titled “Capturing Streamed Data & Events”Strands provides two main approaches to capture streaming events from an agent: async iterators and callback functions.
Async Iterators
Section titled “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 eventsasync 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 exampleawait 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
Section titled “Next Steps”Ready to learn more? Check out these resources:
- Examples - Examples for many use cases
- TypeScript SDK Repository - Explore the TypeScript SDK source code and contribute
- Agent Loop - Learn how Strands agents work under the hood
- State - Understand how agents maintain context and state across a conversation
- Operating Agents in Production - Taking agents from development to production, operating them responsibly at scale