-
Notifications
You must be signed in to change notification settings - Fork 448
Description
Problem Statement
When deploying multiple A2A agents behind an Application Load Balancer (ALB) with path-based routing, the current A2A Server implementation doesn't natively support path prefixes. This requires custom middleware implementation to strip path prefixes from incoming requests, as ALBs don't provide a mechanism to rewrite URL paths.
Currently, users must create a custom PathAwareA2AServer
class that extends A2AServer
and implements middleware to handle path prefixes:
class PathAwareA2AServer(A2AServer):
"""A2A Server that can handle path prefixes using middleware."""
def init(self, agent: SAAgent, path_prefix: str = "", kwargs):
super().init__(agent, kwargs)
self.path_prefix = path_prefix.rstrip('/')
def to_starlette_app(self) -> Starlette:
"""Create a Starlette application with path handling middleware."""
app = super().to_starlette_app()
if self.path_prefix:
# Wrap the app with path handling middleware
app.add_middleware(PathHandlingMiddleware, path_prefix=self.path_prefix)
return app
The PathHandlingMiddleware setup is as follows:
class PathHandlingMiddleware(BaseHTTPMiddleware):
"""Middleware that handles path prefixes by stripping them before processing."""
def __init__(self, app, path_prefix: str = ""):
super().__init__(app)
self.path_prefix = path_prefix.rstrip('/')
async def dispatch(self, request: Request, call_next):
# If we have a path prefix and the request path starts with it, strip it
if self.path_prefix and request.url.path.startswith(self.path_prefix):
# Create a new request with the stripped path
stripped_path = request.url.path[len(self.path_prefix):]
if not stripped_path:
stripped_path = "/"
# Modify the request's path_info for downstream processing
request.scope["path"] = stripped_path
request.scope["raw_path"] = stripped_path.encode()
response = await call_next(request)
return response
Proposed Solution
Add native path prefix support to the A2AServer
class with the following changes:
- Add a
path_prefix
parameter to theA2AServer
constructor:
def init(self, agent: SAAgent, port: int = 8080, host: str = "0.0.0.0", path_prefix: str = "", kwargs):
self.path_prefix = path_prefix.rstrip('/')
# existing initialization code
- Modify the to_starlette_app() method to automatically add path handling middleware when a prefix is specified:
def to_starlette_app(self) -> Starlette:
app = super().to_starlette_app()
if self.path_prefix:
# Add path handling middleware
app.add_middleware(PathHandlingMiddleware, path_prefix=self.path_prefix)
return app
- Include a PathHandlingMiddleware
class in the Strands library that handles path prefix stripping.
Use Case
This feature would provide a standardized way of handling path prefixes and support a common deployment process for containerized A2A agents.
# Create A2A server with path prefix support
a2a_agent = A2AServer(
agent=agent,
port=8080,
host="0.0.0.0",
path_prefix="/basic" # Path prefix for ALB routing
)
This would allow the agent to correctly handle requests to both /basic/chat
and /basic/.well-known/agent.json
by internally routing them to /chat
and /.well-known/agent.json
respectively.
Alternatives Solutions
No response
Additional Context
No response