Repository navigation
feat(a2a): add deterministic multi-turn conversations - #591
Merged
jpr5 merged 19 commits intoOct 29, 2026
Merged
Conversation
commit: |
A send with message.taskId was routed to the conversation store even when no conversation created that task. Mocks without conversations returned -32001/-32004 where they previously served the matching legacy fixture, which broke A2A clients that send taskId on follow-ups. Track the task IDs a conversation creates and route by task ID only for those. Every other send keeps the legacy path, including the dispatcher SendStreamingMessage handler, which again selects legacy fixtures with findMatch unless a conversation is the streaming match.
The streaming request check began requiring jsonrpc "2.0" and an id. Requests without them stopped streaming: a missing jsonrpc field got -32600 and a notification got an empty response. Restore the previous check so these requests use the SSE transport again.
The conversation store built its error envelope inline, which the A8 common-envelope inventory in response-adoption.test.ts reports as an unclassified runtime error object. Export errorResponse from jsonrpc.ts and use it. The wire output is unchanged.
Clone the caller's turns first and validate the clone, so an accessor or proxy cannot return valid values to the validator and different ones to the copy.
A part needs exactly one content field with a value: a string text, url or raw, or non-null data. Fixture parts with null or undefined data or two content fields fail registration, and matching sends with such parts get -32602.
A null or empty taskId, contextId or messageId counts as absent, as an empty context already did. A first send with taskId "" or null starts the conversation, and an absent messageId is generated and never retained.
Stored user messages and agent replies carry the task's taskId and contextId, not the raw values the client sent.
A turn that leaves the task in TASK_STATE_INPUT_REQUIRED sets status.message to the agent reply, so A2A clients that read the prompt from the status see it.
…ssages Run a conversation through batched SendStreamingMessage, test the message-parts guard, a legacy task ID sent with conversation text, JSON error bodies on the streaming route and non-string artifact fields, and assert the specific registration error messages instead of any thrown error.
Contributor
|
Thanks again for this. Multi-turn conversations are a genuinely useful addition, and we'd like to get it in. We pushed some fixes on top of your branch so it's safe for people who don't use conversations: requests with a |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A2A mocks currently answer each message independently. This adds
onConversation()for deterministic multi-turn tasks: intermediate turns request more input, continuation uses the existing task/context IDs, and the final turn completes or fails the task. JSON-RPC and SSE share the same state, including mounted agents and reset behavior.Optional bounded message-ID retention replays the exact accepted response without advancing the conversation; conflicting reuse is rejected. Configuration-file registration and usage documentation are included.
Validation: 339 tests pass across the conversation, A2A, JSON-RPC, configuration, mounting and suite tests. Type checks, build, ESLint, formatting and package export checks pass. Updated API reports are included; please apply
public-api-additionfor compatibility review.