Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ workdir-tmp/

# Bun
bun.lock

.agentreview
63 changes: 45 additions & 18 deletions src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ exports[`Assets Directory Snapshots > File listing > should match the expected f
"cdk/package.json",
"cdk/test/cdk.test.ts",
"cdk/tsconfig.json",
"container/python/Dockerfile",
"container/python/dockerignore.template",
"mcp/python-lambda/README.md",
"mcp/python-lambda/handler.py",
"mcp/python-lambda/pyproject.toml",
Expand Down Expand Up @@ -1553,12 +1555,18 @@ def add_numbers(a: int, b: int) -> int:
return a + b


# Set environment variables for model authentication
load_model()

# Get MCP Toolset
mcp_toolset = [get_streamable_http_mcp_client()]

_credentials_loaded = False

def ensure_credentials_loaded():
global _credentials_loaded
if not _credentials_loaded:
load_model()
_credentials_loaded = True


# Agent Definition
agent = Agent(
model=MODEL_ID,
Expand All @@ -1571,6 +1579,7 @@ agent = Agent(

# Session and Runner
async def setup_session_and_runner(user_id, session_id):
ensure_credentials_loaded()
session_service = InMemorySessionService()
session = await session_service.create_session(
app_name=APP_NAME, user_id=user_id, session_id=session_id
Expand Down Expand Up @@ -1806,8 +1815,13 @@ from mcp_client.client import get_streamable_http_mcp_client
app = BedrockAgentCoreApp()
log = app.logger

# Instantiate model
llm = load_model()
_llm = None

def get_or_create_model():
global _llm
if _llm is None:
_llm = load_model()
return _llm


# Define a simple function tool
Expand All @@ -1832,7 +1846,7 @@ async def invoke(payload, context):
mcp_tools = await mcp_client.get_tools()

# Define the agent using create_react_agent
graph = create_react_agent(llm, tools=mcp_tools + tools)
graph = create_react_agent(get_or_create_model(), tools=mcp_tools + tools)

# Process the user prompt
prompt = payload.get("prompt", "What can you help me with?")
Expand Down Expand Up @@ -2137,12 +2151,17 @@ from mcp_client.client import get_streamable_http_mcp_client
app = BedrockAgentCoreApp()
log = app.logger

# Set environment variables for model authentication
load_model()

# Get MCP Server
mcp_server = get_streamable_http_mcp_client()

_credentials_loaded = False

def ensure_credentials_loaded():
global _credentials_loaded
if not _credentials_loaded:
load_model()
_credentials_loaded = True


# Define a simple function tool
@function_tool
Expand All @@ -2153,6 +2172,7 @@ def add_numbers(a: int, b: int) -> int:

# Define the agent execution
async def main(query):
ensure_credentials_loaded()
try:
async with mcp_server as server:
active_servers = [server] if server else []
Expand Down Expand Up @@ -2404,14 +2424,19 @@ def agent_factory():
return get_or_create_agent
get_or_create_agent = agent_factory()
{{else}}
# Create agent
agent = Agent(
model=load_model(),
system_prompt="""
You are a helpful assistant. Use tools when appropriate.
""",
tools=tools+[mcp_client]
)
_agent = None

def get_or_create_agent():
global _agent
if _agent is None:
_agent = Agent(
model=load_model(),
system_prompt="""
You are a helpful assistant. Use tools when appropriate.
""",
tools=tools+[mcp_client]
)
return _agent
{{/if}}


Expand All @@ -2423,8 +2448,10 @@ async def invoke(payload, context):
session_id = getattr(context, 'session_id', 'default-session')
user_id = getattr(context, 'user_id', 'default-user')
agent = get_or_create_agent(session_id, user_id)

{{else}}
agent = get_or_create_agent()
{{/if}}

# Execute and format response
stream = agent.stream_async(payload.get("prompt"))

Expand Down
24 changes: 24 additions & 0 deletions src/assets/container/python/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim

WORKDIR /app

ENV UV_SYSTEM_PYTHON=1 \
UV_COMPILE_BYTECODE=1 \
UV_NO_PROGRESS=1 \
PYTHONUNBUFFERED=1 \
DOCKER_CONTAINER=1

COPY pyproject.toml uv.lock* ./
RUN uv pip install -r pyproject.toml

RUN useradd -m -u 1000 bedrock_agentcore
USER bedrock_agentcore

COPY . .

# 8080: AgentCore runtime endpoint
# 8000: Local dev server (uvicorn)
# 9000: OpenTelemetry collector
EXPOSE 8080 8000 9000

CMD ["opentelemetry-instrument", "python", "-m", "{{entrypoint}}"]
20 changes: 20 additions & 0 deletions src/assets/container/python/dockerignore.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Python
__pycache__/
*.py[cod]
*.egg-info/
.venv/
dist/
build/

# IDE
.vscode/
.idea/

# Testing
.pytest_cache/
.coverage
htmlcov/

# AgentCore build artifacts
.agentcore/artifacts/
*.zip
13 changes: 10 additions & 3 deletions src/assets/python/googleadk/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ def add_numbers(a: int, b: int) -> int:
return a + b


# Set environment variables for model authentication
load_model()

# Get MCP Toolset
mcp_toolset = [get_streamable_http_mcp_client()]

_credentials_loaded = False

def ensure_credentials_loaded():
global _credentials_loaded
if not _credentials_loaded:
load_model()
_credentials_loaded = True


# Agent Definition
agent = Agent(
model=MODEL_ID,
Expand All @@ -40,6 +46,7 @@ def add_numbers(a: int, b: int) -> int:

# Session and Runner
async def setup_session_and_runner(user_id, session_id):
ensure_credentials_loaded()
session_service = InMemorySessionService()
session = await session_service.create_session(
app_name=APP_NAME, user_id=user_id, session_id=session_id
Expand Down
11 changes: 8 additions & 3 deletions src/assets/python/langchain_langgraph/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@
app = BedrockAgentCoreApp()
log = app.logger

# Instantiate model
llm = load_model()
_llm = None

def get_or_create_model():
global _llm
if _llm is None:
_llm = load_model()
return _llm


# Define a simple function tool
Expand All @@ -35,7 +40,7 @@ async def invoke(payload, context):
mcp_tools = await mcp_client.get_tools()

# Define the agent using create_react_agent
graph = create_react_agent(llm, tools=mcp_tools + tools)
graph = create_react_agent(get_or_create_model(), tools=mcp_tools + tools)

# Process the user prompt
prompt = payload.get("prompt", "What can you help me with?")
Expand Down
12 changes: 9 additions & 3 deletions src/assets/python/openaiagents/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
app = BedrockAgentCoreApp()
log = app.logger

# Set environment variables for model authentication
load_model()

# Get MCP Server
mcp_server = get_streamable_http_mcp_client()

_credentials_loaded = False

def ensure_credentials_loaded():
global _credentials_loaded
if not _credentials_loaded:
load_model()
_credentials_loaded = True


# Define a simple function tool
@function_tool
Expand All @@ -23,6 +28,7 @@ def add_numbers(a: int, b: int) -> int:

# Define the agent execution
async def main(query):
ensure_credentials_loaded()
try:
async with mcp_server as server:
active_servers = [server] if server else []
Expand Down
25 changes: 16 additions & 9 deletions src/assets/python/strands/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,19 @@ def get_or_create_agent(session_id, user_id):
return get_or_create_agent
get_or_create_agent = agent_factory()
{{else}}
# Create agent
agent = Agent(
model=load_model(),
system_prompt="""
You are a helpful assistant. Use tools when appropriate.
""",
tools=tools+[mcp_client]
)
_agent = None

def get_or_create_agent():
global _agent
if _agent is None:
_agent = Agent(
model=load_model(),
system_prompt="""
You are a helpful assistant. Use tools when appropriate.
""",
tools=tools+[mcp_client]
)
return _agent
{{/if}}


Expand All @@ -61,8 +66,10 @@ async def invoke(payload, context):
session_id = getattr(context, 'session_id', 'default-session')
user_id = getattr(context, 'user_id', 'default-user')
agent = get_or_create_agent(session_id, user_id)

{{else}}
agent = get_or_create_agent()
{{/if}}

# Execute and format response
stream = agent.stream_async(payload.get("prompt"))

Expand Down
7 changes: 7 additions & 0 deletions src/cli/aws/agentcore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ export interface SSELogger {
logSSEEvent(rawLine: string): void;
}

/** Default user ID sent with invocations. Container agents require this to obtain workload access tokens. */
export const DEFAULT_RUNTIME_USER_ID = 'default-user';

export interface InvokeAgentRuntimeOptions {
region: string;
runtimeArn: string;
payload: string;
sessionId?: string;
/** User ID for the runtime invocation. Defaults to 'default-user'. Required for Container agents using identity providers. */
userId?: string;
/** Optional logger for SSE event debugging */
logger?: SSELogger;
}
Expand Down Expand Up @@ -112,6 +117,7 @@ export async function invokeAgentRuntimeStreaming(options: InvokeAgentRuntimeOpt
contentType: 'application/json',
accept: 'application/json',
runtimeSessionId: options.sessionId,
runtimeUserId: options.userId ?? DEFAULT_RUNTIME_USER_ID,
});

const response = await client.send(command);
Expand Down Expand Up @@ -207,6 +213,7 @@ export async function invokeAgentRuntime(options: InvokeAgentRuntimeOptions): Pr
contentType: 'application/json',
accept: 'application/json',
runtimeSessionId: options.sessionId,
runtimeUserId: options.userId ?? DEFAULT_RUNTIME_USER_ID,
});

const response = await client.send(command);
Expand Down
1 change: 1 addition & 0 deletions src/cli/aws/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export {
type GetAgentRuntimeStatusOptions,
} from './agentcore-control';
export {
DEFAULT_RUNTIME_USER_ID,
invokeAgentRuntime,
invokeAgentRuntimeStreaming,
stopRuntimeSession,
Expand Down
5 changes: 4 additions & 1 deletion src/cli/commands/add/actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { APP_DIR, ConfigIO, MCP_APP_SUBDIR, NoProjectError, findConfigRoot, setEnvVar } from '../../../lib';
import type {
AgentEnvSpec,
BuildType,
DirectoryPath,
FilePath,
GatewayAuthorizerType,
Expand Down Expand Up @@ -36,6 +37,7 @@ import { dirname, join } from 'path';
export interface ValidatedAddAgentOptions {
name: string;
type: 'create' | 'byo';
buildType: BuildType;
language: TargetLanguage;
framework: SDKFramework;
modelProvider: ModelProvider;
Expand Down Expand Up @@ -113,6 +115,7 @@ async function handleCreatePath(options: ValidatedAddAgentOptions, configBaseDir

const generateConfig = {
projectName: options.name,
buildType: options.buildType,
sdk: options.framework,
modelProvider: options.modelProvider,
memory: options.memory!,
Expand Down Expand Up @@ -186,7 +189,7 @@ async function handleByoPath(
const agent: AgentEnvSpec = {
type: 'AgentCoreRuntime',
name: options.name,
build: 'CodeZip',
build: options.buildType,
entrypoint: (options.entrypoint ?? 'main.py') as FilePath,
codeLocation: codeLocation as DirectoryPath,
runtimeVersion: 'PYTHON_3_12',
Expand Down
2 changes: 2 additions & 0 deletions src/cli/commands/add/command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ async function handleAddAgentCLI(options: AddAgentOptions): Promise<void> {
const result = await handleAddAgent({
name: options.name!,
type: options.type! ?? 'create',
buildType: (options.build as 'CodeZip' | 'Container') ?? 'CodeZip',
language: options.language!,
framework: options.framework!,
modelProvider: options.modelProvider!,
Expand Down Expand Up @@ -217,6 +218,7 @@ export function registerAdd(program: Command) {
.description('Add an agent to the project')
.option('--name <name>', 'Agent name (start with letter, alphanumeric only, max 64 chars) [non-interactive]')
.option('--type <type>', 'Agent type: create or byo [non-interactive]', 'create')
.option('--build <type>', 'Build type: CodeZip or Container (default: CodeZip) [non-interactive]')
.option('--language <lang>', 'Language: Python (create), or Python/TypeScript/Other (BYO) [non-interactive]')
.option(
'--framework <fw>',
Expand Down
Loading
Loading