a2aproject / a2aproject/a2a-go
REST streaming stops at an unknown StreamResponse payload (v2.5.0)
- Lingua principale
- Go
- Stelle
- 460
- Fork
- 93
- Merge medio
- 2g 21h
- PR unite (30g)
- 9
Descrizione
Following [the request for SDK investigations in A2A #2129](https://github.com/a2aproject/A2A/pull/2129#discussion_r3805450070), here is a reproducible Go case for the already-reported unknown-event compatibility problem.
With **a2a-go v2.5.0**, a REST/SSE stream containing:
`Task → working status → unfamiliar payload → working status → completed status`
stops at the unfamiliar payload with `unknown stream response type`. The caller receives the first two events but neither later known update. The request explicitly sends `A2A-Version: 1.0`.
The synthetic `futureEvent` is valid JSON but is **not a defined A2A 1.0 event**. This demonstrates a constraint on future event additions; it does not assume the current specification already mandates accepting that variant.
### Reproduction
With Go 1.25+, save this as `main.go` in a fresh directory:
Self-contained loopback reproduction
```go
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"time"
"github.com/a2aproject/a2a-go/v2/a2a"
"github.com/a2aproject/a2a-go/v2/a2aclient"
)
func main() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream")
if _, err := fmt.Fprint(w, `data: {"task":{"id":"task-fixture","contextId":"context-fixture","status":{"state":"TASK_STATE_SUBMITTED"}}}
data: {"statusUpdate":{"taskId":"task-fixture","contextId":"context-fixture","status":{"state":"TASK_STATE_WORKING"}}}
data: {"futureEvent":{"taskId":"task-fixture","contextId":"context-fixture","text":"synthetic future event; not a defined A2A 1.0 variant"}}
data: {"statusUpdate":{"taskId":"task-fixture","contextId":"context-fixture","status":{"state":"TASK_STATE_WORKING"}}}
data: {"statusUpdate":{"taskId":"task-fixture","contextId":"context-fixture","status":{"state":"TASK_STATE_COMPLETED"}}}
`); err != nil {
panic(err)
}
}))
defer server.Close()
endpoint, err := url.Parse(server.URL)
if err != nil {
panic(err)
}
transport := a2aclient.NewRESTTransport(endpoint, &http.Client{Timeout: 5 * time.Second})
message := a2a.NewMessage(a2a.MessageRoleUser, a2a.NewTextPart("fixture request"))
message.ID = "message-fixture"
count := 0
for event, err := range transport.SendStreamingMessage(context.Background(), a2aclient.ServiceParams{"A2A-Version": {"1.0"}}, &a2a.SendMessageRequest{Message: message}) {
if err != nil {
fmt.Printf("after %d events: %v\n", count, err)
return
}
count++
fmt.Printf("event %d: %T\n", count, event)
}
}
```
```sh
go mod init example.com/a2a-unknown-event-repro
go get github.com/a2aproject/a2a-go/v2@v2.5.0
go mod tidy
go run .
```
Observed with the published module, without local SDK changes:
```text
event 1: *a2a.Task
event 2: *a2a.TaskStatusUpdateEvent
after 2 events: unknown stream response type
```
### Controls
Using the same public REST receive path and loopback fixture:
- Known events only, or an extra field inside a known status update: all four known events arrive, including completion.
- A malformed known update (`status: 42`) or two recognized payload members in one wrapper: parsing fails.
- An HTTP body shorter than its declared Content-Length: `SSE stream error: unexpected EOF`; no completion is delivered.
- An empty `{}` wrapper also produces `unknown stream response type`.
For comparison, Python a2a-sdk 1.1.3 stops at the same unfamiliar payload with a protobuf `ParseError`. Only HTTP+JSON/SSE was exercised; this report makes no claim about other bindings or high-level aggregation.
### Proposed next step
Would you prefer a narrow change that skips unfamiliar payloads with a diagnostic and continues to known events, an opaque-event representation, or keeping rejection with an explicit version-negotiation requirement? The handling should distinguish the intended future-event case from empty/malformed responses and keep real transport failures visible.
[Spec §5.7](https://github.com/a2aproject/A2A/blob/98853be376c88df25e1704771cd3ea9ef8823a96/docs/specification.md#57-field-presence-and-optionality) recommends ignoring unknown fields, but does not explicitly define the receive API behavior when no recognized payload remains. I can contribute the focused implementation and regression cases once that behavior is agreed.
Tested Go release: `9d95b95445f4208ba77f48a137a278067937adb7`. The relevant REST parser and transport are unchanged at inspected main `03b1f8483cc9cbdd3e95567100d95c5509687eb5` (static comparison). Existing `go test ./a2aclient ./internal/rest` checks pass.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.