Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d098d6f
Add strands agent tools to work with knowledge base
JOrjales-gds May 13, 2026
3957034
Adding knowledge base capability to agent and passing as a tool
JOrjales-gds May 13, 2026
a7e5f40
Made agentcore runtime role available cross stack so we can pass perm…
JOrjales-gds May 13, 2026
b39f6db
Added an extra bit of docstring for the knowledge base for when using…
JOrjales-gds May 13, 2026
d7aa541
ruff formatting applied
JOrjales-gds May 13, 2026
aac8592
version bump
JOrjales-gds May 13, 2026
da47652
Added example folder - simple app deployment with agentcore and knowl…
JOrjales-gds May 18, 2026
bb32f72
Expose agentcore runtime arn to other stacks for transfer between the…
JOrjales-gds May 18, 2026
9cf0c45
Added retain on delete = false to avoid example kb agent issues later
JOrjales-gds May 18, 2026
095429e
docstring fix
JOrjales-gds May 18, 2026
896f5bc
Set up pyproject for example webapp with knowledge base and agentcore…
JOrjales-gds May 18, 2026
6212dc6
Set up webapp to be run locally with smoke test
JOrjales-gds May 18, 2026
cd8859b
Readme for how to deploy with actual webapp and just deploying agentc…
JOrjales-gds May 18, 2026
569f912
Create a readme to talk through how to set up a knowledge-base linked…
JOrjales-gds May 18, 2026
ee6f539
Reimport OS
JOrjales-gds May 19, 2026
2d5222a
Tidied agent template in agent core to remove a carried across logger…
JOrjales-gds May 19, 2026
faeaa2b
Added auto_delete_object setting to allow clean destruction of s3 buc…
JOrjales-gds May 19, 2026
58fee51
Added test to check auto delete object when s3 bucket not retaining data
JOrjales-gds May 19, 2026
6022d9f
Amended readme for auto_delete_objects
JOrjales-gds May 19, 2026
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
84 changes: 84 additions & 0 deletions examples/agent_with_kbase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""Example: AgentCore runtime with a Knowledge Base attached.

Usage:
cdk synth # Verify CloudFormation templates
cdk deploy --all # Deploy both stacks to AWS

After deployment:
1. Upload documents to the KB data bucket (see DataBucketName output)
2. Wait for auto-sync to ingest (default 5 min batch window)
3. Invoke the AgentCore runtime and ask questions about your documents

Deploy/Test with:
cdk deploy --all --require-approval broadening \
--app "python agent_with_kb.app.py"

Testing it:
1) Set up a small knowledge base file in terminal for the dev account:

echo "The team standup is every day at 9:30am." > test-doc.txt
aws s3 cp test-doc.txt s3://my-agent-kb1-kb-data-development/

2) Run from the terminal with bedrock-agentcore cli
(assuming deployed in dev account, runtime arn from deploy output):

aws bedrock-agentcore invoke-agent-runtime \
--agent-runtime-arn <RUNTIME-ARN> \
--payload "$(echo -n '{"prompt":"When is standup?"}' | base64)" \
--region eu-west-2 \
outfile.json
"""

import aws_cdk as cdk

from gds_idea_cdk_constructs import DeploymentConfig
from gds_idea_cdk_constructs.agent_core import (
DEFAULT_AGENT_CODE_DIR,
AgentCore,
AgentCoreProperties,
CustomAgent,
MemoryConfig,
)
from gds_idea_cdk_constructs.knowledge_base import (
ChunkingConfig,
KnowledgeBase,
KnowledgeBaseProps,
)

app = cdk.App()
# --- Environment ---
cdk_env = cdk.Environment(
account="992382722318",
region="eu-west-2",
)
# --- Shared config (resolves from Secrets Manager) ---
config = DeploymentConfig(cdk_env)
# --- Knowledge Base ---
kb = KnowledgeBase(
app,
deployment_config=config,
app_config="my-agent-kb1",
kb_props=KnowledgeBaseProps(
chunking=ChunkingConfig.fixed_size(max_tokens=500, overlap_percentage=10),
description="Knowledge base for the agent demo",
retain_on_delete=False,
),
)
# --- AgentCore Runtime (with KB attached) ---
agent = AgentCore(
app,
"MyAgentStack",
props=AgentCoreProperties(
runtime_name="my_kb_agent",
memory=MemoryConfig(name="my_kb_agent_session_store"),
agent=CustomAgent(
agent_code_directory=DEFAULT_AGENT_CODE_DIR,
environment_variables=kb.environment_variables,
),
),
env=cdk_env,
)
# --- Cross-stack: grant the agent permission to query the KB ---
kb.grant_retrieve(agent.runtime_role)

app.synth()
53 changes: 53 additions & 0 deletions examples/webapp_with_agent/.devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# ============================================================================
# DOCKER COMPOSE CONFIGURATION
# ============================================================================
# Used by:
# - VS Code dev containers (.devcontainer/devcontainer.json)
# - Smoke test (idea-app smoke-test)
#
# Prerequisites:
# 1. Deploy AgentCore + KB using examples/agent_with_kbase.py
# 2. Set AGENTCORE_RUNTIME_ARN (from the RuntimeArn CloudFormation output)
# 3. Run: AWS_PROFILE=<profile> idea-app provide-role
# 4. Run: idea-app smoke-test --wait
# 5. Open: http://localhost:8080
# ============================================================================

services:
app:
build:
context: ..
dockerfile: app_src/Dockerfile
target: ${DOCKER_TARGET:-development}

volumes:
# Mount app source for live editing and auto-reload
- ../app_src:/app

# Preserve container's .venv (prevents host .venv overwriting it)
- /app/.venv

# Mount dev mock files directory
- ../dev_mocks:/app/dev_mocks

# Mount AWS credentials (generated by: idea-app provide-role)
- ../.aws-dev:/home/appuser/.aws:ro

environment:
# ---------------------------------------------------------------
# AgentCore Runtime ARN
# ---------------------------------------------------------------
# In production (CDK deploy), this is injected automatically by:
# WebAppContainerProperties(
# environment_variables=agent.environment_variables,
# )
# agent.grant_invoke(webapp.task_role)
#
# Locally, set from the AgentCore RuntimeArn CloudFormation output:
# export AGENTCORE_RUNTIME_ARN="arn:aws:bedrock-agentcore:eu-west-2:..."
# ---------------------------------------------------------------
- AGENTCORE_RUNTIME_ARN=${AGENTCORE_RUNTIME_ARN:-}
- AWS_DEFAULT_REGION=eu-west-2

ports:
- "8080:8080"
176 changes: 176 additions & 0 deletions examples/webapp_with_agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# WebApp with AgentCore Runtime

This example demonstrates how to connect a web application to a deployed
AgentCore runtime with a Knowledge Base attached. All you need is a single environment variable: `AGENTCORE_RUNTIME_ARN`.

## Using with a Deployed WebApp (CDK)

When deploying a WebApp to AWS via CDK, the pattern would be:
Knowledge Base → AgentCore → WebApp, with grants wiring them together.

```python
import aws_cdk as cdk
from gds_idea_cdk_constructs import AppConfig, DeploymentConfig
from gds_idea_cdk_constructs.agent_core import (
DEFAULT_AGENT_CODE_DIR,
AgentCore,
AgentCoreProperties,
CustomAgent,
MemoryConfig,
)
from gds_idea_cdk_constructs.knowledge_base import (
ChunkingConfig,
KnowledgeBase,
KnowledgeBaseProps,
)
from gds_idea_cdk_constructs.web_app import WebApp, WebAppContainerProperties

app = cdk.App()
cdk_env = cdk.Environment(account="...", region="eu-west-2")
config = DeploymentConfig(cdk_env)
app_config = AppConfig(app_name="my-app", framework="streamlit")

# 1. Knowledge Base
kb = KnowledgeBase(
app,
deployment_config=config,
app_config="my-app",
kb_props=KnowledgeBaseProps(
chunking=ChunkingConfig.fixed_size(max_tokens=500, overlap_percentage=10),
description="Documents for the agent",
),
)

# 2. AgentCore Runtime (with KB attached)
agent = AgentCore(
app,
"AgentStack",
props=AgentCoreProperties(
runtime_name="my_agent",
agent=CustomAgent(
agent_code_directory=DEFAULT_AGENT_CODE_DIR,
environment_variables=kb.environment_variables,
),
),
env=cdk_env,
)
kb.grant_retrieve(agent.runtime_role)

# 3. WebApp — pass the runtime ARN and grant invoke permissions
webapp = WebApp(
app,
deployment_config=config,
app_config=app_config,
container_props=WebAppContainerProperties(
environment_variables=agent.environment_variables,
),
)
agent.grant_invoke(webapp.task_role)

app.synth()
```

This:

- Passes `AGENTCORE_RUNTIME_ARN` into the Fargate container automatically
- Grants the task role `bedrock-agentcore:InvokeAgentRuntime` permission
- Grants the AgentCore runtime role `bedrock:Retrieve` on the Knowledge Base

## Application Code

The integration in an app is straightforward (see `app_src/streamlit_app.py`):

```python
import boto3
import json
import os

client = boto3.client("bedrock-agentcore", region_name="eu-west-2")

payload = json.dumps({
"prompt": user_input,
"session_id": session_id,
})

response = client.invoke_agent_runtime(
agentRuntimeArn=os.environ["AGENTCORE_RUNTIME_ARN"],
payload=payload.encode(),
)

# Parse the streaming response (Server-Sent Events)
body = response["response"].read().decode("utf-8")

output = ""
for line in body.splitlines():
if not line.startswith("data: "):
continue
event = json.loads(line[6:])
if event.get("type") == "text":
output += event.get("data", "")
elif event.get("type") == "done" and not output:
output = event.get("response", "")
```

## Running Locally (Smoke Test)

This directory is structured as an idea-app project so you can run the app
locally with `idea-app smoke-test` against a deployed AgentCore runtime.

### Prerequisites

- `idea-app` CLI installed
- Docker running
- AWS credentials (via `aws sso login` or similar)
- AgentCore + KB deployed (see `examples/agent_with_kbase.py`)

### Steps

1. **Deploy the AgentCore + Knowledge Base** (from the repo root):

```bash
cdk deploy --all --require-approval broadening \
--app "python examples/agent_with_kbase.py"
```

Note the `RuntimeArn` from the stack outputs.

2. **Upload a test document** to the KB data bucket:

```bash
echo "The team standup is every day at 9:30am. The retrospective is on Fridays at 2pm." > test-doc.txt
aws s3 cp test-doc.txt s3://<DataBucketName-output>/
```

Wait ~5 minutes for auto-sync to ingest.

3. **Set the runtime ARN**:

```bash
export AGENTCORE_RUNTIME_ARN="arn:aws:bedrock-agentcore:eu-west-2:992382722318:runtime/..."
```

4. **Provide credentials to the container**:

```bash
cd examples/webapp_with_agent
AWS_PROFILE=your-profile idea-app provide-role
```

5. **Run the app**:

```bash
idea-app smoke-test --wait
```

6. **Open http://localhost:8080** and ask a question (e.g. "When is the team standup?").

Press Enter in the terminal to stop and clean up.

7. **Destroy the example AgentCore and Knowledge base stacks** (from the repo root):

Note: It may throw an error during deletion of the S3 bucket and you will need to delete manually in Cloudformation as versioning information may stop deletion of the bucket
and cause a failed stack state. The knowledge base stack implements auto_delete_objects by default when retain_on_delete is set to False.

```bash
cdk destroy --all --app "python examples/agent_with_kbase.py"
```
74 changes: 74 additions & 0 deletions examples/webapp_with_agent/app_src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# ============================================================================
# Multi-stage Dockerfile for Streamlit Application
# ============================================================================
# Production build (default): docker build -t app .
# Dev container build: docker build --target development -t app:dev .
# ============================================================================

# Base stage - common setup
FROM python:3.12-slim AS base

WORKDIR /app

ARG USERNAME=appuser
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Install UV (pinned to major version)
COPY --from=ghcr.io/astral-sh/uv:0.9 /uv /usr/local/bin/uv

# Create non-root user and set ownership of /app
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& chown -R $USERNAME:$USERNAME /app

# Copy dependency files with correct ownership
COPY --chown=$USERNAME:$USERNAME app_src/pyproject.toml ./
COPY --chown=$USERNAME:$USERNAME app_src/uv.loc[k] ./

# Install minimal base packages
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*

# Switch to non-root user for dependency installation
USER $USERNAME

# Install dependencies (as non-root user)
RUN uv sync

# Copy application code
COPY --chown=$USERNAME:$USERNAME app_src/ .

EXPOSE 8080

CMD ["uv", "run", "streamlit", "run", "streamlit_app.py", \
"--server.port", "8080", \
"--server.address", "0.0.0.0", \
"--server.headless", "true", \
"--server.enableCORS", "false", \
"--browser.gatherUsageStats", "false"]

# ============================================================================
# Development stage - for dev containers (NOT DEFAULT)
# ============================================================================
FROM base AS development

# Switch back to root to install dev-only packages
USER root

# Grant passwordless sudo for development flexibility
RUN apt-get update \
&& apt-get install -y --no-install-recommends sudo \
&& rm -rf /var/lib/apt/lists/* \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME

USER $USERNAME

# ============================================================================
# Production stage - secure, minimal, non-root (DEFAULT)
# ============================================================================
FROM base AS production
Loading