Python Agent to A2A Agent
The connection generator can connect your Python Agent to a remote A2A agent — either TypeScript or Python — so your agent can delegate to another agent as a tool.
The generator sets up all the necessary wiring so your agent can discover and invoke the remote A2A agent, both when deployed to AWS (via Bedrock AgentCore) and when running locally.
Prerequisites
Section titled “Prerequisites”Before using this generator, ensure you have:
- A Python project with a Python Agent component (Strands or LangChain)
- A project with an Agent component generated with
--protocol=A2Aand--auth=IAM(eitherts#agentorpy#agent) - Both components created with
infra: agentcore
Run the Generator
Section titled “Run the Generator”- Install the Nx Console VSCode Plugin if you haven't already
- Open the Nx Console in VSCode
- Click
Generate (UI)in the "Common Nx Commands" section - Search for
@aws/nx-plugin - connection - Fill in the required parameters
- Click
Generate
pnpm nx g @aws/nx-plugin:connectionyarn nx g @aws/nx-plugin:connectionnpx nx g @aws/nx-plugin:connectionbunx nx g @aws/nx-plugin:connectionYou can also perform a dry-run to see what files would be changed
pnpm nx g @aws/nx-plugin:connection --dry-runyarn nx g @aws/nx-plugin:connection --dry-runnpx nx g @aws/nx-plugin:connection --dry-runbunx nx g @aws/nx-plugin:connection --dry-runSelect your host agent project as the source and your A2A agent project as the target. If your projects contain multiple components, specify the sourceComponent and targetComponent options to disambiguate.
Options
Section titled “Options”| Parameter | Type | Default | Description |
|---|---|---|---|
| sourceProject Required | string | - | The source project |
| targetProject Required | string | - | The target project to connect to |
| sourceComponent | string | - | The source component to connect from (component name, path relative to source project root, or generator id). Use '.' to explicitly select the project as the source. |
| targetComponent | string | - | The target component to connect to (component name, path relative to target project root, or generator id). Use '.' to explicitly select the project as the target. |
| preferInstallDependencies | boolean | true | Whether to prefer installing dependencies after the generator runs. Set to false to defer installing when batching multiple generators (an install still runs if needed so subsequent generators can compute the Nx project graph); install once at the end. |
Generator Output
Section titled “Generator Output”The generator creates a shared agent_connection Python project at packages/common/agent_connection/ (if it doesn’t already exist). Per-connection client modules are generated into this shared project:
Directorypackages/common/agent_connection
Directory<scope>_agent_connection
- __init__.py Re-exports per-connection clients
Directorycore
- agentcore_endpoints.py Framework-agnostic ARN/URL resolution
- agentcore_a2a_client_config.py Framework-agnostic A2A client config (signed
ClientConfig) - agentcore_a2a_client_<framework>.py A2A client wrapping the config for your agent’s framework
Directoryauth/ Framework-agnostic SigV4 / session-forwarding
httpx.Auth- …
Directoryapp
- <target_agent_name>_client_<framework>.py Per-connection A2A client for each A2A agent
The client suffix matches your agent’s framework (_strands or _langchain). Both wrap the same framework-agnostic signed ClientConfig: the Strands client wraps a Strands A2AAgent, while the LangChain client drives the a2a SDK directly.
Additionally, the generator:
- Transforms your agent’s
agent.pyto register the remote A2A agent as a tool using@tool - Adds the
agent_connectionproject as a workspace dependency of your agent project - Updates the agent’s
devtarget to depend on the target agent’sdevtarget
Using the Connected A2A Agent
Section titled “Using the Connected A2A Agent”The generator transforms your agent’s agent.py to wrap the remote A2A agent as a tool. The remote agent is registered with a @tool-decorated delegate — the decorator’s import and the agent constructor differ by framework:
from contextlib import contextmanagerfrom strands import Agent, tool
from my_scope_agent_connection import RemoteAgentClientStrands
@contextmanagerdef get_agent(): remote_agent = RemoteAgentClientStrands.create()
@tool def ask_remote_agent(prompt: str) -> str: """Delegate a question to the remote RemoteAgent A2A agent and return its reply.""" return str(remote_agent(prompt))
yield Agent( system_prompt="...", tools=[ask_remote_agent], )from langchain.agents import create_agentfrom langchain_aws import ChatBedrockConversefrom langchain_core.tools import tool
from my_scope_agent_connection import RemoteAgentClientLangChain
def get_agent(): remote_agent = RemoteAgentClientLangChain.create()
@tool def ask_remote_agent(prompt: str) -> str: """Delegate a question to the remote RemoteAgent A2A agent and return its reply.""" return str(remote_agent(prompt))
return create_agent( model=ChatBedrockConverse(model=MODEL_ID, region_name=REGION), system_prompt="...", tools=[ask_remote_agent], )Both clients are directly callable, returning the remote agent’s reply, and wrap an httpx.AsyncClient that signs requests with SigV4 when deployed to AWS and uses a plain http://localhost:<port>/ endpoint when LOCAL_DEV=true. The Strands client wraps a Strands A2AAgent; the LangChain client drives the a2a SDK directly.
The AgentCore session ID is propagated to the remote agent automatically via the X-Amzn-Bedrock-AgentCore-Runtime-Session-Id header, regardless of framework: the agent server binds the inbound request’s session into an async context, and the connection client’s signed httpx.Auth stamps it on every outbound call — ensuring consistency for Bedrock AgentCore Observability.
Infrastructure
Section titled “Infrastructure”After running the connection generator, you need to grant the host agent permission to invoke the remote A2A agent.
const remoteAgent = new RemoteAgent(this, 'RemoteAgent');const myAgent = new MyAgent(this, 'MyAgent');
// Grant the host agent permission to invoke the remote A2A agentremoteAgent.grantInvokeAccess(myAgent);grantInvokeAccess on an A2A agent wires up both bedrock-agentcore:InvokeAgentRuntime and bedrock-agentcore:GetAgentCard — the A2A client needs both to fetch the agent card and send messages.
The remote agent’s AgentCore runtime ARN is automatically registered in the agentcore namespace of Runtime Configuration by the generated CDK construct, so the host agent can discover it at runtime.
module "remote_agent" { source = "../../common/terraform/src/app/agents/remote-agent"
appconfig_application_id = module.runtime_config_appconfig.application_id appconfig_application_arn = module.runtime_config_appconfig.application_arn}
module "my_agent" { source = "../../common/terraform/src/app/agents/my-agent"
appconfig_application_id = module.runtime_config_appconfig.application_id appconfig_application_arn = module.runtime_config_appconfig.application_arn}
# Grant the host agent permission to invoke the remote A2A agentresource "aws_iam_policy" "agent_invoke_a2a" { name = "AgentInvokeA2aPolicy" policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = [ "bedrock-agentcore:InvokeAgentRuntime", "bedrock-agentcore:GetAgentCard", ] Resource = module.remote_agent.agent_core_runtime_arn }] })}
resource "aws_iam_role_policy_attachment" "agent_invoke_a2a" { role = module.my_agent.agent_core_runtime_role_arn policy_arn = aws_iam_policy.agent_invoke_a2a.arn}The remote agent’s AgentCore runtime ARN is automatically registered in the agentcore namespace of Runtime Configuration by the generated Terraform module, so the host agent can discover it at runtime.
Local Development
Section titled “Local Development”The generator configures the host agent’s dev target to:
- Start the connected A2A agent(s) automatically
- Set
LOCAL_DEV=trueso the generated client connects directly tohttp://localhost:<port>/instead of AgentCore
Run the agent locally with:
pnpm nx <agent-name>-dev <project-name>yarn nx <agent-name>-dev <project-name>npx nx <agent-name>-dev <project-name>bunx nx <agent-name>-dev <project-name>This will start both the host agent and all connected A2A agents, with the host agent calling the remote agents over plain HTTP on their assigned local ports.