Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
75ccc4c
feat: add complete AgentCore integration example with weather agent
steditt Oct 10, 2025
06e9268
add working simple agent with GAITK, CDK deployment and CloudWatch Lo…
steditt Oct 15, 2025
ed8188e
code clean up, bug fixing
steditt Oct 15, 2025
78090bf
fix test
steditt Oct 15, 2025
cee01a7
code cleanup
steditt Oct 15, 2025
6732135
implement basic MCP server, fix agent tests
steditt Oct 16, 2025
24b1011
feat: add OAuth authentication and testing infrastructure for AgentCore
steditt Oct 16, 2025
33db61f
fix MCP server implementation, OAuth tests passed
steditt Oct 17, 2025
a5dc89f
clean up MCP server tests, full test suite passed
steditt Oct 18, 2025
9e8f076
simplify agent code
steditt Oct 18, 2025
b476fe5
add MCP server support to agent
steditt Oct 18, 2025
44edd09
refactor(agentcore): migrate tests to environment variables and fix M…
steditt Oct 18, 2025
f504350
refactor(agentcore): implement Pydantic models for MCP server with co…
steditt Oct 18, 2025
19c98be
refactor tool registration
steditt Oct 19, 2025
92e37ee
fix MCP tool registration with GAITK, all tests passed
steditt Oct 19, 2025
9dee32e
Refactor agent invocation function
steditt Oct 19, 2025
635c990
update README
steditt Oct 20, 2025
cfce1c5
update README
steditt Oct 20, 2025
070d377
add CDK nag, address cdk nag findings
steditt Oct 20, 2025
e7b4edd
address Protoshield findings
steditt Oct 21, 2025
ddc6f07
Merge pull request #1 from steditt/main
steditt Oct 21, 2025
0003aed
update main README with reference to AgentCore example, fix B104 band…
steditt Oct 21, 2025
5badb96
fix MCP client re-connection behaviour, add example for testing with …
steditt Oct 21, 2025
7cd6291
fix bandit and ruff findings
steditt Oct 21, 2025
049ab32
Merge branch 'agentcore-example'
steditt Oct 21, 2025
472a650
feat: add JWT OAuth authentication to AgentCore runtime
steditt Oct 24, 2025
cc48601
fix failing concurrent MCP tool calls
steditt Oct 26, 2025
f0e14e4
add logging of agent start
steditt Oct 26, 2025
1e63be6
fix typo, all tests passed
steditt Oct 26, 2025
2dedb92
feat: implement JWT passthrough authentication, remove AgentUser
steditt Oct 26, 2025
c186e8a
fix tests to include the jwt_token parameter
steditt Oct 26, 2025
29231de
feat: implement lazy MCP tool registration with JWT tokens
steditt Oct 26, 2025
0ecb214
Merge branch 'agentcore-example'
steditt Oct 26, 2025
6cdf66a
Merge branch 'awslabs:main' into main
steditt Oct 26, 2025
a7d1c7e
Merge branch 'main' into agentcore-example
steditt Oct 26, 2025
bf0ded7
Merge branch 'agentcore-example'
steditt Oct 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,12 @@ node_modules/
*.log
*.swp

# Shell configurations
.zshrc

# Amazon Q Developer settings and rules
.amazonq

# Kiro settings and rules
.kiro

32 changes: 26 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ To fully utilize the Generative AI Toolkit, it’s essential to understand the f
2.6 [Generating Traces: Running Cases in Bulk](#26-generating-traces-running-cases-in-bulk)
2.7 [CloudWatch Custom Metrics](#27-cloudwatch-custom-metrics)
2.8 [Deploying and Invoking the BedrockConverseAgent](#28-deploying-and-invoking-the-bedrockconverseagent)
2.8.1 [General Deployment Patterns](#281-general-deployment-patterns)
2.8.2 [Amazon Bedrock AgentCore Integration](#282-amazon-bedrock-agentcore-integration)
2.9 [Web UI for Conversation Debugging](#29-web-ui-for-conversation-debugging)
2.10 [Mocking and Testing](#210-mocking-and-testing)
2.11 [Model Context Protocol (MCP) Client](#211-model-context-protocol-mcp-client)
Expand Down Expand Up @@ -1703,6 +1705,8 @@ In your Lambda function definition, if the above file is stored as `index.py`, y

### 2.8 Deploying and Invoking the `BedrockConverseAgent`

#### 2.8.1 General Deployment Patterns

> Also see our **sample notebook [deploying_on_aws.ipynb](/examples/deploying_on_aws.ipynb)**.

A typical deployment of an agent using the Generative AI Toolkit would be, per the [reference architecture](#reference-architecture) mentioned above:
Expand All @@ -1711,7 +1715,7 @@ A typical deployment of an agent using the Generative AI Toolkit would be, per t
2. An Amazon DynamoDB table to store conversation history and traces. This table has a stream enabled. The AWS Lambda function, your agent, would write its traces to this table. Additionally (using the `TeeTracer` and the `OtlpTracer`) the agent would send the traces to AWS X-Ray for developer inspection.
3. An AWS Lambda Function, that is attached to the DynamoDB table stream, to run `GenerativeAIToolkit.eval()` on the collected traces. This Lambda function would write the collected measurements to stdout in EMF format (see above), to make the measurements available in Amazon CloudWatch Metrics.

#### Using the `Runner` to run your agent as Lambda function
##### Using the `Runner` to run your agent as Lambda function

The following code shows how you can implement your Generative AI Toolkit based agent as Lambda function, per the description above.

Expand Down Expand Up @@ -1747,7 +1751,7 @@ In your Lambda function definition, if the above file is stored as `index.py`, y

Note that you must use the [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter) to run the `Runner` on AWS Lambda.

#### Invoking the AWS Lambda Function URL with the `IamAuthInvoker`
##### Invoking the AWS Lambda Function URL with the `IamAuthInvoker`

If you use the `Runner` just explained, you would deploy your agent as an AWS Lambda Function that is exposed as Function URL. You should enable IAM Auth, in which case you must [sign all requests with AWS Signature V4 as explained here](https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html).

Expand Down Expand Up @@ -1778,7 +1782,7 @@ for tokens in response2:
print(tokens, end="", flush=True)
```

#### Invoking the AWS Lambda Function URL with `curl`
##### Invoking the AWS Lambda Function URL with `curl`

Using `curl` works too because `curl` supports SigV4 out of the box:

Expand All @@ -1794,7 +1798,7 @@ curl -v \
--aws-sigv4 "aws:amz:$AWS_REGION:lambda"
```

#### Deployments outside AWS Lambda e.g. containerized as a pod on EKS
##### Deployments outside AWS Lambda e.g. containerized as a pod on EKS

The `Runner` is a WSGI application and can be run with any compatible server, such as `gunicorn`.

Expand Down Expand Up @@ -1837,7 +1841,7 @@ Make sure to tune concurrency. By default `gunicorn` runs with 1 worker (process
gunicorn --workers 4 --threads 5 "path.to.agent:Runner()"
```

#### Security: ensure users access their own conversation history only
##### Security: ensure users access their own conversation history only

You must make sure that users can only set the conversation ID to an ID of one of their own conversations, or they would be able to read conversations from other users (unless you want that of course). To make this work securely with the out-of-the-box `DynamoDbConversationHistory`, you need to set the right auth context on the agent for each conversation with a user.

Expand Down Expand Up @@ -1881,7 +1885,7 @@ Runner.configure(agent=my_agent, auth_context_fn=extract_x_user_id_from_request)

> The `Runner` uses, by default, the AWS IAM `userId` as auth context. The actual value of this `userId` depends on how you've acquired AWS credentials to sign the AWS Lambda Function URL request with. For example, if you've assumed an AWS IAM Role it will simply be the concatenation of your assumed role ID with your chosen session ID. You'll likely want to customize the auth context as explained in this paragraph!

#### Security: ensure your tools operate with the right privileges
##### Security: ensure your tools operate with the right privileges

Where relevant, your tools should use the `auth_context` within the `AgentContext` to determine the identity of the user (e.g. for authorization):

Expand Down Expand Up @@ -2002,6 +2006,22 @@ INSERT INTO customer_orders (customer_id, order_details, amount) VALUES
('user123', 'Order for mouse', 25.99);
```

#### 2.8.2 Amazon Bedrock AgentCore Integration

The Generative AI Toolkit integrates with Amazon Bedrock AgentCore Runtime for agent deployments. AgentCore provides managed infrastructure, automatic scaling, and enterprise security features.

The `examples/agentcore/` directory contains a complete weather agent implementation that demonstrates:

- **Containerized Architecture**: Separate containers for agent and MCP server components
- **Model Context Protocol (MCP)**: Tool communication between agent and server containers
- **Pydantic-Based Tools**: Type-safe tool definitions with automatic schema generation
- **CDK Infrastructure**: Automated deployment templates
- **Comprehensive Testing**: Test suite with evaluation framework integration

This example showcases building scalable, maintainable AI agents with proper separation of concerns and automated deployment patterns.

> **See the complete example**: [examples/agentcore/README.md](/examples/agentcore/README.md)

### 2.9 Web UI for Conversation Debugging

The Generative AI Toolkit provides a local, web-based user interface (UI) to help you inspect and debug conversations, view evaluation results, and analyze agent behavior. This UI is particularly useful during development and testing phases, allowing you to quickly identify issues, review traces, and understand how your agent processes user queries and responds.
Expand Down
149 changes: 149 additions & 0 deletions examples/agentcore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# AgentCore Integration Example

This example demonstrates how to build a weather agent with the Generative AI Toolkit and deploy it on Amazon Bedrock AgentCore Runtime. It showcases AI agent architecture with separate containerized components communicating via the Model Context Protocol (MCP).

## What is AgentCore?

Amazon Bedrock AgentCore Runtime provides a managed, serverless environment for deploying AI agents and their supporting services. Key advantages for this example:

- **Containerized Deployment**: Both agent and MCP server run in separate, scalable containers
- **Managed Infrastructure**: No server management, automatic scaling, and built-in monitoring
- **Enterprise Security**: IAM-based access control, Cognito authentication, and JWT token validation
- **Service Isolation**: Agent and tools run independently, enabling better reliability and scaling
- **Observability**: Built-in logging, tracing, and health monitoring

## Architecture

### Separated Components

**Agent Container** (`agent/`):
- Weather assistant using `BedrockConverseAgent`
- Connects to MCP server for tool access
- Handles user interactions and conversation flow

**MCP Server Container** (`mcp-server/`):
- Provides weather tools via Model Context Protocol
- Modular tool architecture with separate modules per tool
- Independent scaling and deployment lifecycle

### Pydantic-Based Tools

This example demonstrates best practices for tool development:

- **Type Safety**: Pydantic models ensure robust input validation
- **Rich Documentation**: Model docstrings become tool descriptions for the LLM
- **JSON Schema Generation**: Automatic schema creation for tool parameters
- **Modular Design**: Each tool (`get_weather_tool.py`, `get_forecast_tool.py`) is self-contained
- **Maintainable Code**: Clear separation between models, business logic, and MCP registration

## Directory Structure

```
examples/agentcore/
├── agent/ # Weather agent implementation
│ ├── agent.py # Main agent with BedrockConverseAgent
│ ├── mcp_tool_manager.py # MCP client integration
│ └── simple_mcp_client.py # AgentCore MCP client
├── mcp-server/ # Modular MCP tools server
│ ├── get_weather_tool.py # Current weather tool + models
│ ├── get_forecast_tool.py # Forecast tool + models
│ └── mcp_server.py # FastMCP server setup
├── infrastructure/ # CDK deployment stack
├── tests/ # Comprehensive test suite
└── docker-compose.yml # Local development environment
```

## Deployment Instructions

### Prerequisites

1. **AWS CLI configured** with appropriate permissions
2. **Node.js and npm** installed for CDK
3. **Docker** installed for container builds
4. **Python 3.13+** for local development

### Step-by-Step Deployment

#### 1. Install Dependencies

```bash
# Install CDK dependencies
cd infrastructure
npm install

# Install Python dependencies (optional, for local testing)
cd ../
pip install -r requirements.txt
```

#### 2. Configure Environment

```bash
# Set your AWS region
export AWS_REGION=us-east-1

# Choose a Bedrock model (ensure it's available in your region)
export BEDROCK_MODEL_ID=anthropic.claude-3-5-sonnet-20241022-v2:0
```

#### 3. Deploy Infrastructure

```bash
cd infrastructure

# Bootstrap CDK (first time only)
npx cdk bootstrap

# Optional: Set custom stack name (defaults to "{username}-agentcore-stack")
export CDK_STACK_NAME=MyWeatherAgent

# Deploy the stack
npx cdk deploy --all
```

This will create:
- Two AgentCore Runtime environments (agent and MCP server)
- ECR repositories for container images
- IAM roles and policies
- Cognito User Pool for authentication

#### 4. Build and Push Container Images

The CDK deployment automatically builds and pushes the Docker images to ECR. Monitor the deployment output for any build failures.

#### 5. Test the Deployment

```bash
# Run the test suite to verify deployment
cd ../tests

# Test agent deployment
python -m pytest agent/test_agent_deployment.py -v

# Test MCP server deployment
python -m pytest mcp_server/test_mcp_server_deployment.py -v
```

### Local Development

For local testing without AgentCore:

```bash
# Start MCP server
cd mcp-server
python mcp_server.py

# In another terminal, test the agent locally
cd ../tests
python -m pytest test_agent_local.py -v
```

## Getting Started

See `examples/agentcore/tests/` for comprehensive examples of:
- Local development and testing
- AgentCore deployment validation
- Tool schema verification
- End-to-end agent evaluation

The test suite demonstrates both local development workflows and deployment patterns, making it the best starting point for understanding how to use this example.
73 changes: 73 additions & 0 deletions examples/agentcore/agent/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Docker ignore file for weather agent

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Virtual environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Logs
*.log
logs/

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/

# Documentation
docs/
*.md
!README.md

# Git
.git/
.gitignore

# Docker
Dockerfile*
.dockerignore
docker-compose*.yml
30 changes: 30 additions & 0 deletions examples/agentcore/agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# syntax=docker/dockerfile:1
FROM python:3.13-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Create non-root user
RUN useradd -m -u 1000 agentcore

# Copy application files (copy all Python files for the module)
COPY --chown=agentcore:agentcore *.py ./

# Switch to non-root user
USER agentcore

EXPOSE 8080

# Health check endpoint (AgentCore provides /ping and /health endpoints)
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD curl -f http://localhost:8080/ping || exit 1

CMD ["python", "agent.py"]
Loading