create_a2a_server() constructs DefaultRequestHandler internally and offers no way to supply a different one, so an adopter with an existing a2a.server.request_handlers.RequestHandler implementation cannot use the factory at all — it is all-or-nothing.
The value is already a local variable that gets threaded into the JSON-RPC routes, so exposing it is additive:
# adcp/server/a2a_server.py (6.6.0 and v7.0.0-rc, identical)
1182: request_handler = DefaultRequestHandler(
1188: jsonrpc_kwargs["request_handler"] = request_handler
1227: request_handler = DefaultRequestHandler( # v0.3 compat branch
1233: jsonrpc_kwargs["request_handler"] = request_handler
Proposed change — add a keyword-only parameter, default None, preserving today's behavior:
def create_a2a_server(
handler: ADCPHandler[Any],
*,
...,
request_handler: RequestHandler | None = None,
) -> Any:
When supplied, use it for both the 1.0 and v0.3 compat branches instead of constructing DefaultRequestHandler. When None, behavior is unchanged.
Why it matters. task_store= and push_config_store= already let adopters own persistence, but some request-level semantics live in the handler rather than the store — most visibly tasks/cancel, which DefaultRequestHandler resolves against its in-process active-task registry and therefore cannot cancel a task issued by a previous process or a sibling worker. Multi-worker deployments cannot express durable cancel through any currently-exposed seam.
Concretely, this blocks incremental adoption. We maintain a seller agent with a mature RequestHandler implementation and would like to adopt the SDK's executor, middleware chain, error translation, and validation while keeping our request-handler layer during migration. Today the only options are "adopt everything" or "adopt nothing"; this kwarg makes a staged migration possible.
Compatibility: additive, keyword-only, default preserves current behavior.
We are happy to open the PR if the direction is acceptable.
create_a2a_server()constructsDefaultRequestHandlerinternally and offers no way to supply a different one, so an adopter with an existinga2a.server.request_handlers.RequestHandlerimplementation cannot use the factory at all — it is all-or-nothing.The value is already a local variable that gets threaded into the JSON-RPC routes, so exposing it is additive:
Proposed change — add a keyword-only parameter, default
None, preserving today's behavior:When supplied, use it for both the 1.0 and v0.3 compat branches instead of constructing
DefaultRequestHandler. WhenNone, behavior is unchanged.Why it matters.
task_store=andpush_config_store=already let adopters own persistence, but some request-level semantics live in the handler rather than the store — most visiblytasks/cancel, whichDefaultRequestHandlerresolves against its in-process active-task registry and therefore cannot cancel a task issued by a previous process or a sibling worker. Multi-worker deployments cannot express durable cancel through any currently-exposed seam.Concretely, this blocks incremental adoption. We maintain a seller agent with a mature
RequestHandlerimplementation and would like to adopt the SDK's executor, middleware chain, error translation, and validation while keeping our request-handler layer during migration. Today the only options are "adopt everything" or "adopt nothing"; this kwarg makes a staged migration possible.Compatibility: additive, keyword-only, default preserves current behavior.
We are happy to open the PR if the direction is acceptable.