Skip to content

A2A-native clients: Submitted envelopes don't set A2A Task state #877

Description

@bokelley

Context

When a handler returns (or the framework narrows to) an AdCP Submitted envelope via `createAdcpServer`, the payload lands on the wire as:

```json
{
"content": [{ "type": "text", "text": "Task tk_xyz submitted" }],
"structuredContent": { "status": "submitted", "task_id": "tk_xyz", "message": "..." }
}
```

MCP-based clients detect async by reading `structuredContent.status === 'submitted'` per the AdCP `protocol-envelope.json` contract — that works today.

Gap

A2A-native clients (anything consuming the agent over A2A's JSON-RPC transport rather than MCP) expect async work to be signaled via A2A's own `Task` state model — `state: 'submitted' | 'working' | 'input-required' | 'completed' | 'failed' | ...`. They poll on A2A's `tasks/get` using the A2A `Task.id`, not on AdCP's `task_id` field.

Right now `src/lib/server/create-adcp-server.ts`'s `wrapSubmittedEnvelope` only mirrors the AdCP payload onto `structuredContent`; there's no A2A adapter path that also emits a `TaskStatusUpdateEvent` (or picks `state: 'submitted'` on the A2A `Task` artifact) so A2A-native clients can discover this is async and needs polling. A2A clients currently get a `completed` `Task` whose artifact carries `status: 'submitted'` in-band — they'd need AdCP-aware parsing to realize the work isn't actually done.

Scope

Flagged during ad-tech-protocol-expert review on #874. Out of scope for that PR (which widened handler return types but didn't touch transport). Needs a coordinated change across:

  • `src/lib/server/create-adcp-server.ts` dispatcher (ideally emits a protocol-neutral signal)
  • `src/lib/server/serve.ts` / `express-adapter.ts` (MCP-side, unchanged)
  • Whatever A2A adapter sits alongside `createAdcpServer` (out-of-tree today — likely lives in `scope3data/agentic-adapters` or similar downstream consumers; check whether `@adcp/client` should own a first-party A2A serve adapter)

Related

Acceptance

An A2A-native client calling a tool whose handler returns `{ status: 'submitted', task_id }` should observe A2A `Task.state === 'submitted'` (not `'completed'`) on the response, and be able to poll the same A2A `Task.id` to completion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Fields

    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