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
40 changes: 26 additions & 14 deletions src/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,7 @@ from google.adk.agents import Agent
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from a2a.types import AgentCapabilities, AgentCard, AgentSkill
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill
from bedrock_agentcore.runtime import serve_a2a
from model.load import load_model

Expand Down Expand Up @@ -1405,7 +1405,6 @@ runner = Runner(
card = AgentCard(
name=agent.name,
description=agent.description,
url="http://localhost:9000/",
version="0.1.0",
capabilities=AgentCapabilities(streaming=True),
skills=[
Expand All @@ -1418,6 +1417,13 @@ card = AgentCard(
],
default_input_modes=["text"],
default_output_modes=["text"],
supported_interfaces=[
AgentInterface(
protocol_binding="JSONRPC",
protocol_version="1.0",
url="http://localhost:9000/",
)
],
)

if __name__ == "__main__":
Expand Down Expand Up @@ -1487,11 +1493,11 @@ description = "AgentCore A2A Agent using Google ADK"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"a2a-sdk >= 0.2.0, < 1.0.0",
"a2a-sdk[http-server] >= 1.0.1, < 2.0.0",
"aws-opentelemetry-distro",
"bedrock-agentcore[a2a] >= 1.0.3",
"google-adk >= 1.0.0, < 2.0.0",
"google-genai >= 1.0.0, < 2.0.0",
"bedrock-agentcore[a2a-v1] >= 1.19.0",
"google-adk[a2a] >= 2.5.0, < 3.0.0",
"google-genai >= 2.9.0, < 3.0.0",
# 1.13.0 was yanked for broken imports.
"opentelemetry-resourcedetector-gcp >= 1.9.0a0, < 2.0.0, != 1.13.0",
]
Expand Down Expand Up @@ -1579,11 +1585,11 @@ import os
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
from opentelemetry.instrumentation.langchain import LangchainInstrumentor
from a2a.helpers import new_task_from_user_message
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.server.tasks import TaskUpdater
from a2a.types import AgentCapabilities, AgentCard, AgentSkill, Part, TextPart
from a2a.utils import new_task
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, Part
from bedrock_agentcore.runtime import serve_a2a
from model.load import load_model

Expand Down Expand Up @@ -1675,7 +1681,7 @@ class LangGraphA2AExecutor(AgentExecutor):
self.graph = graph

async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
task = context.current_task or new_task(context.message)
task = context.current_task or new_task_from_user_message(context.message)
if not context.current_task:
await event_queue.enqueue_event(task)
updater = TaskUpdater(event_queue, task.id, task.context_id)
Expand All @@ -1684,7 +1690,7 @@ class LangGraphA2AExecutor(AgentExecutor):
result = await self.graph.ainvoke({"messages": [("user", user_text)]})
response = result["messages"][-1].content

await updater.add_artifact([Part(root=TextPart(text=response))])
await updater.add_artifact([Part(text=response)])
await updater.complete()

async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
Expand All @@ -1694,7 +1700,6 @@ class LangGraphA2AExecutor(AgentExecutor):
card = AgentCard(
name="{{ name }}",
description="A LangGraph agent on Bedrock AgentCore",
url="http://localhost:9000/",
version="0.1.0",
capabilities=AgentCapabilities(streaming=True),
skills=[
Expand All @@ -1707,6 +1712,13 @@ card = AgentCard(
],
default_input_modes=["text"],
default_output_modes=["text"],
supported_interfaces=[
AgentInterface(
protocol_binding="JSONRPC",
protocol_version="1.0",
url="http://localhost:9000/",
)
],
)

if __name__ == "__main__":
Expand Down Expand Up @@ -1858,15 +1870,15 @@ description = "AgentCore A2A Agent using LangChain + LangGraph"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"a2a-sdk >= 0.2.0, < 1.0.0",
"a2a-sdk[http-server] >= 1.0.1, < 2.0.0",
{{#if (eq modelProvider "Anthropic")}}"langchain-anthropic >= 0.3.0",
{{/if}}{{#if (eq modelProvider "Bedrock")}}"langchain-aws >= 0.2.0",
{{/if}}{{#if (eq modelProvider "Gemini")}}"langchain-google-genai >= 2.0.0",
"google-genai >= 1.0.0, < 2.0.0",
{{/if}}{{#if (eq modelProvider "OpenAI")}}"langchain-openai >= 0.2.0",
{{/if}}"aws-opentelemetry-distro",
"opentelemetry-instrumentation-langchain >= 0.59.0",
"bedrock-agentcore[a2a] >= 1.8.0",
"bedrock-agentcore[a2a-v1] >= 1.19.0",
"botocore[crt] >= 1.35.0",
"langgraph >= 0.2.0",
]
Expand Down Expand Up @@ -2209,7 +2221,7 @@ readme = "README.md"
requires-python = ">=3.10"
dependencies = [
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
{{/if}}"a2a-sdk[all] >= 0.2.0, < 1.0.0",
{{/if}}"a2a-sdk[all] >= 0.3.0, < 0.4.0",
"aws-opentelemetry-distro",
"bedrock-agentcore[a2a] >= 1.9.1",
"botocore[crt] >= 1.35.0",
Expand Down
10 changes: 8 additions & 2 deletions src/assets/python/a2a/googleadk/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from a2a.types import AgentCapabilities, AgentCard, AgentSkill
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill
from bedrock_agentcore.runtime import serve_a2a
from model.load import load_model

Expand Down Expand Up @@ -99,7 +99,6 @@ def list_files(path: str) -> str:
card = AgentCard(
name=agent.name,
description=agent.description,
url="http://localhost:9000/",
version="0.1.0",
capabilities=AgentCapabilities(streaming=True),
skills=[
Expand All @@ -112,6 +111,13 @@ def list_files(path: str) -> str:
],
default_input_modes=["text"],
default_output_modes=["text"],
supported_interfaces=[
AgentInterface(
protocol_binding="JSONRPC",
protocol_version="1.0",
url="http://localhost:9000/",
)
],
)

if __name__ == "__main__":
Expand Down
8 changes: 4 additions & 4 deletions src/assets/python/a2a/googleadk/base/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ description = "AgentCore A2A Agent using Google ADK"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"a2a-sdk >= 0.2.0, < 1.0.0",
"a2a-sdk[http-server] >= 1.0.1, < 2.0.0",
"aws-opentelemetry-distro",
"bedrock-agentcore[a2a] >= 1.0.3",
"google-adk >= 1.0.0, < 2.0.0",
"google-genai >= 1.0.0, < 2.0.0",
"bedrock-agentcore[a2a-v1] >= 1.19.0",
"google-adk[a2a] >= 2.5.0, < 3.0.0",
Comment thread
notgitika marked this conversation as resolved.
"google-genai >= 2.9.0, < 3.0.0",
# 1.13.0 was yanked for broken imports.
"opentelemetry-resourcedetector-gcp >= 1.9.0a0, < 2.0.0, != 1.13.0",
]
Expand Down
16 changes: 11 additions & 5 deletions src/assets/python/a2a/langchain_langgraph/base/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent
from opentelemetry.instrumentation.langchain import LangchainInstrumentor
from a2a.helpers import new_task_from_user_message
from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.server.tasks import TaskUpdater
from a2a.types import AgentCapabilities, AgentCard, AgentSkill, Part, TextPart
from a2a.utils import new_task
from a2a.types import AgentCapabilities, AgentCard, AgentInterface, AgentSkill, Part
from bedrock_agentcore.runtime import serve_a2a
from model.load import load_model

Expand Down Expand Up @@ -100,7 +100,7 @@ def __init__(self, graph):
self.graph = graph

async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
task = context.current_task or new_task(context.message)
task = context.current_task or new_task_from_user_message(context.message)
if not context.current_task:
await event_queue.enqueue_event(task)
updater = TaskUpdater(event_queue, task.id, task.context_id)
Expand All @@ -109,7 +109,7 @@ async def execute(self, context: RequestContext, event_queue: EventQueue) -> Non
result = await self.graph.ainvoke({"messages": [("user", user_text)]})
response = result["messages"][-1].content

await updater.add_artifact([Part(root=TextPart(text=response))])
await updater.add_artifact([Part(text=response)])
await updater.complete()

async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
Expand All @@ -119,7 +119,6 @@ async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None
card = AgentCard(
name="{{ name }}",
description="A LangGraph agent on Bedrock AgentCore",
url="http://localhost:9000/",
version="0.1.0",
capabilities=AgentCapabilities(streaming=True),
skills=[
Expand All @@ -132,6 +131,13 @@ async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None
],
default_input_modes=["text"],
default_output_modes=["text"],
supported_interfaces=[
AgentInterface(
protocol_binding="JSONRPC",
protocol_version="1.0",
url="http://localhost:9000/",
)
],
)

if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions src/assets/python/a2a/langchain_langgraph/base/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ description = "AgentCore A2A Agent using LangChain + LangGraph"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"a2a-sdk >= 0.2.0, < 1.0.0",
"a2a-sdk[http-server] >= 1.0.1, < 2.0.0",
{{#if (eq modelProvider "Anthropic")}}"langchain-anthropic >= 0.3.0",
{{/if}}{{#if (eq modelProvider "Bedrock")}}"langchain-aws >= 0.2.0",
{{/if}}{{#if (eq modelProvider "Gemini")}}"langchain-google-genai >= 2.0.0",
"google-genai >= 1.0.0, < 2.0.0",
{{/if}}{{#if (eq modelProvider "OpenAI")}}"langchain-openai >= 0.2.0",
{{/if}}"aws-opentelemetry-distro",
"opentelemetry-instrumentation-langchain >= 0.59.0",
"bedrock-agentcore[a2a] >= 1.8.0",
"bedrock-agentcore[a2a-v1] >= 1.19.0",
"botocore[crt] >= 1.35.0",
"langgraph >= 0.2.0",
]
Expand Down
2 changes: 1 addition & 1 deletion src/assets/python/a2a/strands/base/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ readme = "README.md"
requires-python = ">=3.10"
dependencies = [
{{#if (eq modelProvider "Anthropic")}}"anthropic >= 0.30.0",
{{/if}}"a2a-sdk[all] >= 0.2.0, < 1.0.0",
{{/if}}"a2a-sdk[all] >= 0.3.0, < 0.4.0",
"aws-opentelemetry-distro",
"bedrock-agentcore[a2a] >= 1.9.1",
"botocore[crt] >= 1.35.0",
Expand Down
34 changes: 33 additions & 1 deletion src/cli/operations/dev/__tests__/invoke-a2a.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DevServerError } from '../../../../lib/errors/types';
import { invokeA2AStreaming } from '../invoke-a2a';
import { fetchA2AAgentCard, invokeA2AStreaming } from '../invoke-a2a';
import { beforeEach, describe, expect, it, vi } from 'vitest';

const mockFetch = vi.fn();
Expand Down Expand Up @@ -210,3 +210,35 @@ describe('invokeA2AStreaming', () => {
expect(chunks.length).toBeGreaterThan(0);
});
});

describe('fetchA2AAgentCard', () => {
beforeEach(() => {
mockFetch.mockReset();
});

it('uses the v1 agent card endpoint', async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
status: 200,
json: () => Promise.resolve({ name: 'v1-agent' }),
});

const card = await fetchA2AAgentCard(9000);

expect(card?.name).toBe('v1-agent');
expect(mockFetch.mock.calls[0]![0]).toBe('http://localhost:9000/.well-known/agent-card.json');
});

it('falls back to the v0.3 agent card endpoint', async () => {
mockFetch.mockResolvedValueOnce({ ok: false, status: 404 }).mockResolvedValueOnce({
ok: true,
status: 200,
json: () => Promise.resolve({ name: 'legacy-agent' }),
});

const card = await fetchA2AAgentCard(9000);

expect(card?.name).toBe('legacy-agent');
expect(mockFetch.mock.calls[1]![0]).toBe('http://localhost:9000/.well-known/agent.json');
});
});
28 changes: 16 additions & 12 deletions src/cli/operations/dev/invoke-a2a.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ export interface A2AAgentCard {
description?: string;
version?: string;
url?: string;
supportedInterfaces?: { protocolBinding?: string; protocolVersion?: string; url?: string }[];
skills?: { id?: string; name?: string; description?: string; tags?: string[] }[];
capabilities?: { streaming?: boolean };
defaultInputModes?: string[];
defaultOutputModes?: string[];
}

/**
* Fetch the A2A agent card from /.well-known/agent.json.
* Fetch the A2A agent card, falling back to the v0.3 endpoint.
* Returns null if not available (retries on connection errors).
*/
export async function fetchA2AAgentCard(port: number, logger?: SSELogger): Promise<A2AAgentCard | null> {
Expand All @@ -26,19 +27,22 @@ export async function fetchA2AAgentCard(port: number, logger?: SSELogger): Promi

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const res = await fetch(`http://localhost:${port}/.well-known/agent.json`, {
method: 'GET',
headers: { Accept: 'application/json' },
});
for (const path of ['/.well-known/agent-card.json', '/.well-known/agent.json']) {
const res = await fetch(`http://localhost:${port}${path}`, {
method: 'GET',
headers: { Accept: 'application/json' },
});

if (!res.ok) {
if (res.status === 404 && path === '/.well-known/agent-card.json') continue;
logger?.log?.('warn', `Agent card not available (${res.status})`);
return null;
}

if (!res.ok) {
logger?.log?.('warn', `Agent card not available (${res.status})`);
return null;
const card = (await res.json()) as A2AAgentCard;
logger?.log?.('system', `A2A agent card: ${card.name ?? 'unnamed'}`);
return card;
}

const card = (await res.json()) as A2AAgentCard;
logger?.log?.('system', `A2A agent card: ${card.name ?? 'unnamed'}`);
return card;
} catch (err) {
const error = err instanceof Error ? err : new Error(String(err));
if (isConnectionError(error) && attempt < maxRetries - 1) {
Expand Down
Loading
Loading