# Deploy Mastra to Amazon Bedrock AgentCore

Deploy your Mastra application to [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/) using the [AgentCore CLI](https://github.com/aws/agentcore-cli). The CLI scaffolds a bring-your-own-code (BYO) TypeScript project, builds the container with AWS CodeBuild, and provisions the runtime. A local Docker daemon is not required for deployment.

This guide follows the [official AgentCore TypeScript walkthrough](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-get-started-cli-typescript.html) and adapts it to call a Mastra agent from the invocation handler.

> **Info:** For a Lambda-based deployment of the full Mastra server, see the [AWS Lambda guide](https://mastra.ai/guides/deployment/aws-lambda). For a long-lived virtual machine, see the [Amazon EC2 guide](https://mastra.ai/guides/deployment/amazon-ec2).

## Before you begin

You'll need:

- An [AWS account](https://aws.amazon.com/) with permissions for Amazon Bedrock AgentCore, AWS CodeBuild, Amazon ECR, and AWS IAM
- [AWS CLI](https://aws.amazon.com/cli/) installed and authenticated (`aws configure` or `aws sso login`)
- Node.js `v22.13.0` or later installed
- [Docker](https://www.docker.com/), [Podman](https://podman.io/), or [Finch](https://runfinch.com/) for local testing with `agentcore dev` (not required for `agentcore deploy`)

Amazon Bedrock AgentCore Runtime is available in [a subset of AWS Regions](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agentcore-regions.html). Use a region where AgentCore is available and where the foundation models you plan to call are enabled.

## Create a new AgentCore project

Run the following command to create a new AgentCore project:

**npm**:

```bash
npx @aws/agentcore create --name MastraOnAgentCore --no-agent
```

**pnpm**:

```bash
pnpm dlx @aws/agentcore create --name MastraOnAgentCore --no-agent
```

**Yarn**:

```bash
yarn dlx @aws/agentcore create --name MastraOnAgentCore --no-agent
```

**Bun**:

```bash
bun x @aws/agentcore create --name MastraOnAgentCore --no-agent
```

Navigate to the newly created `MastraOnAgentCore` directory:

```bash
cd MastraOnAgentCore
```

Initialize a BYO TypeScript agent that will be created inside `app/MastraAgent`:

**npm**:

```bash
npx @aws/agentcore add agent --name MastraAgent --type byo --build Container --language TypeScript --framework Strands --model-provider Bedrock --code-location app/MastraAgent
```

**pnpm**:

```bash
pnpm dlx @aws/agentcore add agent --name MastraAgent --type byo --build Container --language TypeScript --framework Strands --model-provider Bedrock --code-location app/MastraAgent
```

**Yarn**:

```bash
yarn dlx @aws/agentcore add agent --name MastraAgent --type byo --build Container --language TypeScript --framework Strands --model-provider Bedrock --code-location app/MastraAgent
```

**Bun**:

```bash
bun x @aws/agentcore add agent --name MastraAgent --type byo --build Container --language TypeScript --framework Strands --model-provider Bedrock --code-location app/MastraAgent
```

The CLI will modify the `agentcore/agentcore.json` file and create an empty `app/MastraAgent` directory.

## Set up the agent project

Navigate to the `app/MastraAgent` directory and initialize a new Node.js project:

```bash
cd app/MastraAgent
npm init --init-type=module -y
```

Install the required dependencies. The `bedrock-agentcore` package provides the `BedrockAgentCoreApp` HTTP server that implements the [AgentCore Runtime service contract](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-service-contract.html). The `@ai-sdk/amazon-bedrock` and `@aws-sdk/credential-providers` packages let the Mastra agent call Bedrock through the AgentCore Runtime execution role:

**npm**:

```bash
npm install bedrock-agentcore @opentelemetry/auto-instrumentations-node @ai-sdk/amazon-bedrock @aws-sdk/credential-providers --legacy-peer-deps
```

**pnpm**:

```bash
pnpm add bedrock-agentcore @opentelemetry/auto-instrumentations-node @ai-sdk/amazon-bedrock @aws-sdk/credential-providers --legacy-peer-deps
```

**Yarn**:

```bash
yarn add bedrock-agentcore @opentelemetry/auto-instrumentations-node @ai-sdk/amazon-bedrock @aws-sdk/credential-providers --legacy-peer-deps
```

**Bun**:

```bash
bun add bedrock-agentcore @opentelemetry/auto-instrumentations-node @ai-sdk/amazon-bedrock @aws-sdk/credential-providers --legacy-peer-deps
```

Also install TypeScript and related dev dependencies:

**npm**:

```bash
npm install --save-dev typescript @types/node tsx
```

**pnpm**:

```bash
pnpm add --save-dev typescript @types/node tsx
```

**Yarn**:

```bash
yarn add --dev typescript @types/node tsx
```

**Bun**:

```bash
bun add --dev typescript @types/node tsx
```

Run [`mastra init`](https://mastra.ai/reference/cli/mastra) to set up a new Mastra project. The provider you choose at the prompt is overwritten in the next step, so any value works:

**npm**:

```bash
npx mastra@latest init
```

**pnpm**:

```bash
pnpm dlx mastra@latest init
```

**Yarn**:

```bash
yarn dlx mastra@latest init
```

**Bun**:

```bash
bun x mastra@latest init
```

Replace the generated `src/mastra/agents/weather-agent.ts` to use Amazon Bedrock. The original `memory: new Memory()` is removed because the storage layer is removed in the next step:

```ts
import { Agent } from '@mastra/core/agent'
import { createAmazonBedrock } from '@ai-sdk/amazon-bedrock'
import { fromNodeProviderChain } from '@aws-sdk/credential-providers'
import { weatherTool } from '../tools/weather-tool.js'

const bedrock = createAmazonBedrock({
  credentialProvider: fromNodeProviderChain(),
})

export const weatherAgent = new Agent({
  id: 'weather-agent',
  name: 'Weather Agent',
  instructions:
    'You are a helpful weather assistant. Use the weatherTool to fetch current weather data.',
  model: bedrock('us.anthropic.claude-sonnet-4-6'),
  tools: { weatherTool },
})
```

> **Note:** `fromNodeProviderChain()` lets the agent pick up AWS credentials through the standard SDK resolution chain (environment variables, shared config files, SSO, and container or EC2 roles) instead of environment variables only.

Replace the generated `src/mastra/index.ts` to remove the default file-based storage and observability config. AgentCore Runtime containers run as a non-root user with a read-only application directory, so the default `LibSQLStore` cannot open `./mastra.db` and the runtime fails at startup:

```ts
import { Mastra } from '@mastra/core/mastra'
import { PinoLogger } from '@mastra/loggers'
import { weatherWorkflow } from './workflows/weather-workflow.js'
import { weatherAgent } from './agents/weather-agent.js'

export const mastra = new Mastra({
  workflows: { weatherWorkflow },
  agents: { weatherAgent },
  logger: new PinoLogger({
    name: 'Mastra',
    level: 'info',
  }),
})
```

Create a `tsconfig.json` file with the following content:

```json
{
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": ".",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true,
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "forceConsistentCasingInFileNames": true
  },
  "include": ["*.ts", "src/**/*"],
  "exclude": ["node_modules", "dist"]
}
```

> **Note:** After adding the `tsconfig.json` file your editor will show errors inside the generated `src/mastra` project. This is expected since the configuration now requires file extensions on imports. You can fix these by adding `.js`, for example:
>
> ```ts
> // Before
> import { weatherWorkflow } from './workflows/weather-workflow'
> // After
> import { weatherWorkflow } from './workflows/weather-workflow.js'
> ```

Update your `package.json` to set the entry point and build scripts. Using `npm pkg set` preserves the dependencies that `mastra init` added:

```bash
npm pkg set main=dist/agent.js scripts.build=tsc scripts.start="node dist/agent.js" scripts.dev="npx tsx --watch agent.ts"
```

## Initialize the agent

Create an `agent.ts` file. This handler is called for every `POST /invocations` request. Resolve the Mastra agent and call it inside the handler:

```ts
import { BedrockAgentCoreApp } from 'bedrock-agentcore/runtime'
import { mastra } from './src/mastra/index.js'

const app = new BedrockAgentCoreApp({
  invocationHandler: {
    process: async (payload, context) => {
      const { prompt } = payload as { prompt: string }

      const agent = mastra.getAgentById('weather-agent')
      const response = await agent.generate(prompt, {
        runId: context.sessionId,
      })

      return response.text
    },
  },
})

app.run()
```

Run `npm run build` to verify that your project compiles successfully.

## Create a Dockerfile

Create a `Dockerfile` in the `app/MastraAgent` directory. Container-based deployment uses a multi-stage Docker build: the builder stage compiles TypeScript to JavaScript, and the production stage runs only the compiled output. The image runs as a non-root user for security, and exposes port 8080 (HTTP), port 8000 (MCP), and port 9000 (A2A). OpenTelemetry instrumentation is included automatically at startup.

```dockerfile
FROM node:22-slim AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-slim
WORKDIR /app
ENV AWS_REGION=us-east-1
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./

RUN useradd -m bedrock_agentcore
USER bedrock_agentcore

EXPOSE 8080 8000 9000
CMD ["node", "--require", "@opentelemetry/auto-instrumentations-node/register", "dist/agent.js"]
```

> **Note:** Pick an `AWS_REGION` that pairs with your Bedrock model ID prefix (`us.`, `jp.`, `eu.`, or `global.`).

Also create a `.dockerignore` file to exclude unnecessary files from the Docker build context:

```bash
node_modules
dist
.git
*.log
```

## Test your agent

Return to the project root:

```bash
cd ../..
```

Test your agent locally:

**npm**:

```bash
npx @aws/agentcore dev --runtime MastraAgent
```

**pnpm**:

```bash
pnpm dlx @aws/agentcore dev --runtime MastraAgent
```

**Yarn**:

```bash
yarn dlx @aws/agentcore dev --runtime MastraAgent
```

**Bun**:

```bash
bun x @aws/agentcore dev --runtime MastraAgent
```

In a separate terminal, send a test request:

**npm**:

```bash
npx @aws/agentcore dev "What is the weather in Tokyo?"
```

**pnpm**:

```bash
pnpm dlx @aws/agentcore dev "What is the weather in Tokyo?"
```

**Yarn**:

```bash
yarn dlx @aws/agentcore dev "What is the weather in Tokyo?"
```

**Bun**:

```bash
bun x @aws/agentcore dev "What is the weather in Tokyo?"
```

## Deploy your agent

Set the AWS account and region in `agentcore/aws-targets.json`:

```json
[
  {
    "name": "default",
    "account": "123456789012",
    "region": "us-east-1"
  }
]
```

Deploy to AgentCore Runtime. The CLI builds the image with AWS CodeBuild, pushes it to Amazon ECR, and creates the runtime and a `DEFAULT` endpoint:

**npm**:

```bash
npx @aws/agentcore deploy
```

**pnpm**:

```bash
pnpm dlx @aws/agentcore deploy
```

**Yarn**:

```bash
yarn dlx @aws/agentcore deploy
```

**Bun**:

```bash
bun x @aws/agentcore deploy
```

> **Note:** Set provider API keys and other secrets in `agentcore/agentcore.json` under the agent's `environmentVariables` field before deploying.

## Verify your deployment

Run `agentcore status` to view the runtime ARN, endpoint, and recent invocations. Then call the deployed agent from the CLI:

```bash
npx @aws/agentcore invoke "What is the weather in Tokyo?"
```

To stream tokens as they are generated, use `--stream`:

```bash
npx @aws/agentcore invoke --stream "Plan a 3-day trip to Tokyo"
```

## Related

- [Amazon Bedrock AgentCore documentation](https://docs.aws.amazon.com/bedrock-agentcore/)
- [AgentCore CLI on GitHub](https://github.com/aws/agentcore-cli)