Skip to content

A2A Server Configuration

Once you have an A2A server running (see Agent-to-Agent (A2A) Protocol), this page is the reference for tuning it: every constructor option, the custom task stores and request-handler components you can plug in, and path-based mounting for deployments behind a load balancer.

The A2AServer constructor accepts several configuration options:

  • agent_factory: Callable that takes a context_id and returns a fresh agent per context (recommended)
  • agent: A single Strands agent reused across contexts (deprecated; prefer agent_factory)
  • max_contexts: Maximum number of per context agents to retain concurrently (default: 1000, must be at least 1)
  • host: Hostname or IP address to bind to (default: “127.0.0.1”)
  • port: Port to bind to (default: 9000)
  • version: Version of the agent (default: “0.0.1”)
  • skills: Custom list of agent skills (default: auto-generated from tools)
  • http_url: Public HTTP URL where this agent will be accessible (optional, enables path-based mounting)
  • serve_at_root: Forces server to serve at root path regardless of http_url path (default: False)
  • task_store: Custom task storage implementation (defaults to InMemoryTaskStore)
  • queue_manager: Custom message queue management (optional)
  • push_config_store: Custom push notification configuration storage (optional)
  • push_sender: Custom push notification sender implementation (optional)
  • enable_a2a_compliant_streaming: Streams responses as A2A artifact updates when True (default: False). The default uses legacy status-update streaming and emits a warning; set this to True to conform to the A2A spec. It becomes the default in the next major version.

Provide exactly one of agent_factory or agent, recommend agent_factory.

The A2AServer provides access to the underlying FastAPI or Starlette application objects allowing you to further customize server behavior.

from contextlib import asynccontextmanager
from strands import Agent
from strands.multiagent.a2a import A2AServer
import uvicorn
# Create your agent factory and A2A server
def create_agent(context_id: str) -> Agent:
return Agent(name="My Agent", description="A customizable agent", callback_handler=None)
a2a_server = A2AServer(agent_factory=create_agent)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Manage application lifespan with proper error handling."""
# Startup tasks
yield # Application runs here
# Shutdown tasks
# Access the underlying FastAPI app
# Allows passing keyword arguments to FastAPI constructor for further customization
fastapi_app = a2a_server.to_fastapi_app(app_kwargs={"lifespan": lifespan})
# Add custom middleware, routes, or configuration
fastapi_app.add_middleware(...)
# Or access the Starlette app
# Allows passing keyword arguments to FastAPI constructor for further customization
starlette_app = a2a_server.to_starlette_app(app_kwargs={"lifespan": lifespan})
# Customize as needed
# You can then serve the customized app directly
uvicorn.run(fastapi_app, host="127.0.0.1", port=9000)

The A2AServer supports configurable request handler components for advanced customization:

from strands import Agent
from strands.multiagent.a2a import A2AServer
from a2a.server.tasks import TaskStore, PushNotificationConfigStore, PushNotificationSender
from a2a.server.events import QueueManager
# Custom task storage implementation
class CustomTaskStore(TaskStore):
# Implementation details...
pass
# Custom queue manager
class CustomQueueManager(QueueManager):
# Implementation details...
pass
# Create an agent factory with custom components
def create_agent(context_id: str) -> Agent:
return Agent(name="My Agent", description="A customizable agent", callback_handler=None)
a2a_server = A2AServer(
agent_factory=create_agent,
task_store=CustomTaskStore(),
queue_manager=CustomQueueManager(),
push_config_store=MyPushConfigStore(),
push_sender=MyPushSender()
)

Interface Requirements:

Custom implementations must follow these interfaces:

  • task_store: Must implement TaskStore interface from a2a.server.tasks
  • queue_manager: Must implement QueueManager interface from a2a.server.events
  • push_config_store: Must implement PushNotificationConfigStore interface from a2a.server.tasks
  • push_sender: Must implement PushNotificationSender interface from a2a.server.tasks

Path-Based Mounting for Containerized Deployments

Section titled “Path-Based Mounting for Containerized Deployments”

The A2AServer supports automatic path-based mounting for deployment scenarios involving load balancers or reverse proxies. This allows you to deploy agents behind load balancers with different path prefixes.

from strands import Agent
from strands.multiagent.a2a import A2AServer
# Create an agent factory
def create_agent(context_id: str) -> Agent:
return Agent(
name="Calculator Agent",
description="A calculator agent",
callback_handler=None
)
# Deploy with path-based mounting
# The agent will be accessible at http://my-alb.amazonaws.com/calculator/
a2a_server = A2AServer(
agent_factory=create_agent,
http_url="http://my-alb.amazonaws.com/calculator"
)
# For load balancers that strip path prefixes, use serve_at_root=True
a2a_server_with_root = A2AServer(
agent_factory=create_agent,
http_url="http://my-alb.amazonaws.com/calculator",
serve_at_root=True # Serves at root even though URL has /calculator path
)