Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4f5c782
feat: add AG-UI (AGUI) as fourth first-class protocol mode
aidandaly24 Apr 9, 2026
f03c367
fix: address review findings for AGUI protocol implementation
aidandaly24 Apr 9, 2026
9ba6e73
fix: add AGUI to TUI protocol picker and dev mode dispatch
aidandaly24 Apr 9, 2026
acffb7d
fix: A2A GoogleADK template passes model=None to Agent constructor
aidandaly24 Apr 9, 2026
831a38f
chore: update protocol references to include AGUI across CLI
aidandaly24 Apr 9, 2026
a08095b
fix: add InvokeLogger to AGUI CLI path and improve UX polish
aidandaly24 Apr 9, 2026
4376be0
fix: template bugs found during deployment testing
aidandaly24 Apr 10, 2026
a08725c
fix: add ToolNode + ReAct loop to AGUI LangGraph template
aidandaly24 Apr 16, 2026
d9df6af
fix: address all review findings from AG-UI protocol code review
aidandaly24 Apr 17, 2026
3c1d061
fix: add AGUI to JSON schema protocol enum
aidandaly24 Apr 17, 2026
633d534
fix: restore MemorySaver in AGUI LangGraph template
aidandaly24 Apr 17, 2026
447fd33
fix: address final review findings in AGUI parser
aidandaly24 Apr 20, 2026
e76770a
fix: use toolCallId for TOOL_CALL_RESULT matching in dev client
aidandaly24 Apr 20, 2026
32604e9
revert: remove manual JSON schema edit (auto-generated during release)
aidandaly24 Apr 20, 2026
76c5c1d
fix: add configurable PORT env var to AGUI templates + update snapshots
aidandaly24 Apr 20, 2026
c8c275f
fix: use AG-UI in user-facing strings instead of AGUI
aidandaly24 Apr 21, 2026
9ffd847
fix: restore credential wiring in AGUI GoogleADK template
aidandaly24 Apr 21, 2026
a8b3948
fix: convert AGUI dynamic import to static in invokeForProtocol
aidandaly24 Apr 22, 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
859 changes: 858 additions & 1 deletion src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions src/assets/__tests__/__snapshots__/dockerfile-render.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Dockerfile enableOtel rendering > renders opentelemetry-instrument CMD when enableOtel is true > Dockerfile-enableOtel-true 1`] = `
"FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim

ARG UV_DEFAULT_INDEX
ARG UV_INDEX

WORKDIR /app

ENV UV_SYSTEM_PYTHON=1 \\
UV_COMPILE_BYTECODE=1 \\
UV_NO_PROGRESS=1 \\
PYTHONUNBUFFERED=1 \\
DOCKER_CONTAINER=1 \\
UV_DEFAULT_INDEX=\${UV_DEFAULT_INDEX} \\
UV_INDEX=\${UV_INDEX} \\
PATH="/app/.venv/bin:$PATH"

RUN useradd -m -u 1000 bedrock_agentcore

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project

COPY --chown=bedrock_agentcore:bedrock_agentcore . .
RUN uv sync --frozen --no-dev

USER bedrock_agentcore

# AgentCore Runtime service contract ports
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-service-contract.html
# 8080: HTTP Mode
# 8000: MCP Mode
# 9000: A2A Mode
EXPOSE 8080 8000 9000

CMD ["opentelemetry-instrument", "python", "-m", "main"]
"
`;

exports[`Dockerfile enableOtel rendering > renders plain python CMD when enableOtel is false > Dockerfile-enableOtel-false 1`] = `
"FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim

ARG UV_DEFAULT_INDEX
ARG UV_INDEX

WORKDIR /app

ENV UV_SYSTEM_PYTHON=1 \\
UV_COMPILE_BYTECODE=1 \\
UV_NO_PROGRESS=1 \\
PYTHONUNBUFFERED=1 \\
DOCKER_CONTAINER=1 \\
UV_DEFAULT_INDEX=\${UV_DEFAULT_INDEX} \\
UV_INDEX=\${UV_INDEX} \\
PATH="/app/.venv/bin:$PATH"

RUN useradd -m -u 1000 bedrock_agentcore

COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project

COPY --chown=bedrock_agentcore:bedrock_agentcore . .
RUN uv sync --frozen --no-dev

USER bedrock_agentcore

# AgentCore Runtime service contract ports
# https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-service-contract.html
# 8080: HTTP Mode
# 8000: MCP Mode
# 9000: A2A Mode
EXPOSE 8080 8000 9000

CMD ["python", "-m", "main"]
"
`;
24 changes: 24 additions & 0 deletions src/assets/__tests__/dockerfile-render.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as fs from 'fs';
import Handlebars from 'handlebars';
import * as path from 'path';
import { describe, expect, it } from 'vitest';

const DOCKERFILE_PATH = path.resolve(__dirname, '..', 'container', 'python', 'Dockerfile');

describe('Dockerfile enableOtel rendering', () => {
const template = Handlebars.compile(fs.readFileSync(DOCKERFILE_PATH, 'utf-8'));

it('renders opentelemetry-instrument CMD when enableOtel is true', () => {
const rendered = template({ entrypoint: 'main', enableOtel: true });
expect(rendered).toMatchSnapshot('Dockerfile-enableOtel-true');
expect(rendered).toContain('opentelemetry-instrument');
expect(rendered).not.toContain('CMD ["python", "-m"');
});

it('renders plain python CMD when enableOtel is false', () => {
const rendered = template({ entrypoint: 'main', enableOtel: false });
expect(rendered).toMatchSnapshot('Dockerfile-enableOtel-false');
expect(rendered).toContain('CMD ["python", "-m"');
expect(rendered).not.toContain('opentelemetry-instrument');
});
});
4 changes: 4 additions & 0 deletions src/assets/container/python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ USER bedrock_agentcore
# 9000: A2A Mode
EXPOSE 8080 8000 9000

{{#if enableOtel}}
CMD ["opentelemetry-instrument", "python", "-m", "{{entrypoint}}"]
{{else}}
CMD ["python", "-m", "{{entrypoint}}"]
{{/if}}
4 changes: 3 additions & 1 deletion src/assets/python/a2a/googleadk/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from bedrock_agentcore.runtime import serve_a2a
from model.load import load_model

load_model() # Sets GOOGLE_API_KEY env var (returns None)


def add_numbers(a: int, b: int) -> int:
"""Return the sum of two numbers."""
Expand Down Expand Up @@ -73,7 +75,7 @@ def list_files(directory: str = "") -> str:
"""

agent = Agent(
model=load_model(),
model="gemini-2.5-flash",
Comment thread
aidandaly24 marked this conversation as resolved.
name="{{ name }}",
description="A helpful assistant that can use tools.",
instruction=AGENT_INSTRUCTION,
Expand Down
30 changes: 30 additions & 0 deletions src/assets/python/agui/googleadk/base/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# {{ name }}

An AG-UI agent deployed on Amazon Bedrock AgentCore using Google ADK.

## Overview

This agent implements the AG-UI protocol using Google's Agent Development Kit, enabling rich agent-user interaction via the AG-UI event stream.

## Local Development

```bash
uv sync
uv run python main.py
```

The agent starts on port 8080 and serves requests at `/invocations`.

## Health Check

```
GET /ping
```

Returns `{"status": "healthy"}`.

## Deploy

```bash
agentcore deploy
```
41 changes: 41 additions & 0 deletions src/assets/python/agui/googleadk/base/gitignore.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Environment variables
.env

# 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

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

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

# OS
.DS_Store
Thumbs.db
31 changes: 31 additions & 0 deletions src/assets/python/agui/googleadk/base/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import uvicorn
from google.adk.agents import LlmAgent
from ag_ui_adk import ADKAgent, AGUIToolset, create_adk_app
from model.load import load_model

load_model()

agent = LlmAgent(
name="{{ name }}",
model="gemini-2.5-flash",
instruction="You are a helpful assistant.",
tools=[AGUIToolset()],
)

adk_agent = ADKAgent(
adk_agent=agent,
app_name="{{ name }}",
use_in_memory_services=True,
)

app = create_adk_app(adk_agent, path="/invocations")


@app.get("/ping")
async def ping():
return {"status": "healthy"}


if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", "8080")))
1 change: 1 addition & 0 deletions src/assets/python/agui/googleadk/base/model/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Package marker
41 changes: 41 additions & 0 deletions src/assets/python/agui/googleadk/base/model/load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import os
from bedrock_agentcore.identity.auth import requires_api_key

IDENTITY_PROVIDER_NAME = "{{identityProviders.[0].name}}"
IDENTITY_ENV_VAR = "{{identityProviders.[0].envVarName}}"


@requires_api_key(provider_name=IDENTITY_PROVIDER_NAME)
def _agentcore_identity_api_key_provider(api_key: str) -> str:
"""Fetch API key from AgentCore Identity."""
return api_key


def _get_api_key() -> str:
"""
Uses AgentCore Identity for API key management in deployed environments.
For local development, run via 'agentcore dev' which loads agentcore/.env.
"""
if os.getenv("LOCAL_DEV") == "1":
api_key = os.getenv(IDENTITY_ENV_VAR)
if not api_key:
raise RuntimeError(
f"{IDENTITY_ENV_VAR} not found. Add {IDENTITY_ENV_VAR}=your-key to .env.local"
)
return api_key
return _agentcore_identity_api_key_provider()


def load_model() -> None:
"""
Set up Gemini API key authentication.
Uses AgentCore Identity for API key management in deployed environments,
and falls back to .env file for local development.
Sets the GOOGLE_API_KEY environment variable for the Google ADK.
"""
api_key = _get_api_key()
# Use Google AI Studios API Key Authentication.
# https://google.github.io/adk-docs/agents/models/#google-ai-studio
os.environ["GOOGLE_API_KEY"] = api_key
# Set to TRUE is using Google Vertex AI, Set to FALSE for Google AI Studio
os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "FALSE"
24 changes: 24 additions & 0 deletions src/assets/python/agui/googleadk/base/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "{{ name }}"
version = "0.1.0"
description = "AgentCore AG-UI Agent using Google ADK"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"ag-ui-adk >= 0.6.0",
"ag-ui-protocol >= 0.1.10",
"bedrock-agentcore >= 1.0.3",
"fastapi >= 0.115.12",
"google-adk >= 1.16.0",
"google-genai >= 1.0.0",
"opentelemetry-distro",
"opentelemetry-exporter-otlp",
"uvicorn >= 0.34.3",
]

[tool.hatch.build.targets.wheel]
packages = ["."]
22 changes: 22 additions & 0 deletions src/assets/python/agui/langchain_langgraph/base/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# {{ name }}

An AG-UI agent deployed on Amazon Bedrock AgentCore using LangChain + LangGraph.

## Overview

This agent implements the AG-UI protocol using LangGraph, enabling seamless frontend-to-agent communication with support for streaming, tool calls, and frontend-injected tools.

## Local Development

```bash
uv sync
uv run python main.py
```

The agent starts on port 8080.

## Deploy

```bash
agentcore deploy
```
41 changes: 41 additions & 0 deletions src/assets/python/agui/langchain_langgraph/base/gitignore.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Environment variables
.env

# 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

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

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

# OS
.DS_Store
Thumbs.db
Loading
Loading