-
Notifications
You must be signed in to change notification settings - Fork 246
fix(a2a): persist context_id and task_id for multi-turn conversations #358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(a2a): persist context_id and task_id for multi-turn conversations #358
Conversation
This commit adds context_id and task_id persistence to the A2A client tool, enabling proper multi-turn conversations with A2A-compliant agents. Changes: - Add context_id and task_id parameters to a2a_send_message - Automatically persist context_id from server responses - Track active tasks and auto-continue single active tasks - Remove tasks from tracking when they reach terminal states - Add a2a_get_conversation_state tool for debugging - Add a2a_clear_conversation_state tool to reset conversations The implementation follows the solution proposed in issue strands-agents#349: 1. Persist context_id per conversation/session 2. Track task_id per agent until terminal state 3. Include IDs in subsequent requests automatically 4. Allow explicit override of IDs when needed Fixes strands-agents#349
| @tool | ||
| async def a2a_send_message( | ||
| self, message_text: str, target_agent_url: str, message_id: str | None = None | ||
| self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this tool is LLM-invoked, how do you envision callers supplying explicit context_id / task_id without relying on the LLM? And if IDs are passed by the LLM, should we validate them against stored state to avoid hallucinations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If want to hardcode any parameter for a tool, consumer of tool can wrap into another tool and hardcode their logic there safely.
Having persistent keys available to LLM allows switch between sessions on the flip side ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved from my end. One check is currently failing — FYI. Happy to re-review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a failing test in integ due to function signature change, my autonomous agent probably will pick and work on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix PR for integ is here: #359
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, we have implemented this functionality a little differently on an internal library that extends this strands_tools library.
We pass a session_id in the constructor of a custom A2AClientToolProvider class. Then inside the _send_message() function we set context_id to be self.session_id. We did this because we want our A2A client to set the session_id (context_id) vs. the downstream A2A agent generating it. This enables the agent serving as the A2A client to receive the session_id from its upstream calling app (e.g. a web chat UI) and restore prior sessions, verify user ownership of the session, etc. All of that we want to do in deterministic (non LLM) code.
The solution proposed here moves that responsibility out of the client and puts it with the downstream A2A agent to generate the initial session ID (context_id). How might that impact the session restoration and authorization checks we've implemented in the agent with the A2A client?
Description
This PR fixes #349 by implementing conversation state persistence in the A2A client.
Problem
The current implementation of
a2a_send_messagedoes not persistcontext_idortask_idreturned by the server. This means:Solution
Implemented conversation state tracking following the A2A protocol specification:
context_id persistence: Store the
context_idfrom the first server response and automatically include it in all subsequent requests within the same session.task_id tracking per agent: Track active tasks per agent URL and automatically reuse the
task_idwhile tasks are in non-terminal states (submitted,working,input-required).Terminal state cleanup: Clear stored
task_idwhen tasks reach terminal states (completed,canceled,failed,rejected) to allow new tasks to be created.Explicit overrides: Allow callers to explicitly provide
context_idortask_idto override automatic behavior.New Features
context_idandtask_idparameters toa2a_send_messagefor explicit controla2a_get_conversation_statetool for debugging/inspectiona2a_clear_conversation_statetool to reset conversation stateRelated Issues
Closes #349
Type of Change
Testing
Checklist
Automated by strands-coder 🦆