Skip to content

Phase 2: Per-skill middleware hook in ADCPAgentExecutor (PR-P) #226

@bokelley

Description

@bokelley

Summary

Downstream (salesagent) runs audit logging + activity-feed hooks on every A2A skill dispatch today. Their 2,288 LOC custom A2A executor exists partly because ADCPAgentExecutor.execute() is a black box — there's no pre/post hook.

Proposed API

Two shapes to choose from; either solves the problem:

Option A — middleware list (async, ordered):

class SkillMiddleware(Protocol):
    async def __call__(
        self,
        skill_name: str,
        params: dict[str, Any],
        context: ToolContext,
        call_next: Callable[[], Awaitable[Any]],
    ) -> Any: ...

ADCPAgentExecutor(handler, ..., middleware=[AuditLogMiddleware(), ActivityFeedMiddleware()])

Option B — two callbacks (simpler, no recursion):

ADCPAgentExecutor(
    handler,
    ...,
    before_skill: Callable[[str, dict, ToolContext], Awaitable[None]] | None = None,
    after_skill: Callable[[str, dict, ToolContext, Any | Exception], Awaitable[None]] | None = None,
)

Option A is more expressive (middleware can short-circuit, transform result, wrap in retry). Option B is easier to compose at the callsite and doesn't require Protocol/abstract-class boilerplate downstream. Leaning toward A because audit requires exception-capture semantics.

Acceptance

  • Hook wired into ADCPAgentExecutor.execute().
  • Surfaced on create_a2a_server(middleware=...) pass-through.
  • Integration test exercising a logging middleware observing every skill dispatch (including error paths).
  • Section in docs/handler-authoring.md showing the audit-log recipe.

Context

Roadmap item PR-P (Phase 2) from .context/sdk-adoption-roadmap.md. Third of three blockers gating salesagent's A2A migration (with #224, #225).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions