Skip to content

feat(testing): SellerA2AClient — max_events constructor parameter for event-drain budget #698

@bokelley

Description

@bokelley

Follow-up to #678 / #694.

Gap

SellerA2AClient.invoke() drains the A2A event queue with a hardcoded budget:

for _ in range(32):
    event = await asyncio.wait_for(queue.dequeue_event(), timeout=timeout_seconds)
    ...

32 is documented as "bounded to a small number of intermediate state events." That's true for the current A2A executor surface, which produces at most a few status transitions before the terminal Task.

Why this matters later

The three deferred follow-ups in #694's PR body — push-notification capture, intermediate-state observer, cancel/resume harness — all increase the per-invoke event count:

  • Intermediate-state observer wants to capture working / input_required transitions over potentially many cycles.
  • Cancel/resume drives task lifecycle that may emit a dozen events for one logical invocation.
  • Push-notification interleaving with task transitions doubles the event count again.

Adding max_events later is a breaking API change for any adopter who has set timeout_seconds and relied on the implicit 32-event cap. Easier to add now.

Proposed

async def invoke(
    self,
    skill: str,
    payload: dict[str, Any] | None = None,
    *,
    timeout_seconds: float = 5.0,
    max_events: int = 32,
) -> ToolInvokeResult:
    ...

Acceptance

  • max_events kwarg on invoke(), default 32 (no behavior change for existing callers)
  • Error message on exhaustion calls out both bounds: "produced no terminal Task within {timeout_seconds}s × {max_events} events"
  • Test that exercises a handler emitting > 32 events with the default cap (raises) and with max_events=128 (succeeds)

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