-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Python: Testing agent-framework WorkflowAgent with Checkpoint and HITL #3245
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WorkflowContext, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handler, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response_handler, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| InMemoryCheckpointStorage, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from getting_started.workflows.agents.workflow_as_agent_reflection_pattern import ( # noqa: E402 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ReviewRequest, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -124,14 +125,46 @@ async def main() -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print("Query: 'Write code for parallel reading 1 million files on disk and write to a sorted output file.'") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print("-" * 50) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_repo = {} # cache for checkpoints | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_storage_1 = InMemoryCheckpointStorage() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_repo["conv1"] = checkpoint_storage_1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+128
to
+131
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Run the agent with an initial query. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response = await agent.run( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Write code for parallel reading 1 million Files on disk and write to a sorted output file." | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response1 = await agent.run( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Write code for parallel reading 1 million Files on disk and write to a sorted output file.", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_storage=checkpoint_storage_1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print("\n\nconversation 1 completed, waiting for human in the loop response...\n\n") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # A new conversation with blank checkpoint storage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_storage_2 = InMemoryCheckpointStorage() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_repo["conv2"] = checkpoint_storage_2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| response2 = await agent.run( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "A new conversation after human in the loop", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkpoint_storage=checkpoint_storage_2, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lusu-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| the workflow fails here with the following error: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Traceback (most recent call last): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ......... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 157, in run | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async for update in self._run_stream_impl( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 246, in _run_stream_impl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function_responses = self._extract_function_responses(input_messages) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 426, in _extract_function_responses | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise AgentExecutionException("Unexpected content type while awaiting request info responses.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| agent_framework.exceptions.AgentExecutionException: Unexpected content type while awaiting request info responses. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+140
to
+160
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # A new conversation with blank checkpoint storage | |
| checkpoint_storage_2 = InMemoryCheckpointStorage() | |
| checkpoint_repo["conv2"] = checkpoint_storage_2 | |
| response2 = await agent.run( | |
| "A new conversation after human in the loop", | |
| checkpoint_storage=checkpoint_storage_2, | |
| ) | |
| """ | |
| the workflow fails here with the following error: | |
| Traceback (most recent call last): | |
| ......... | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 157, in run | |
| async for update in self._run_stream_impl( | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 246, in _run_stream_impl | |
| function_responses = self._extract_function_responses(input_messages) | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 426, in _extract_function_responses | |
| raise AgentExecutionException("Unexpected content type while awaiting request info responses.") | |
| agent_framework.exceptions.AgentExecutionException: Unexpected content type while awaiting request info responses. | |
| """ | |
| # NOTE: | |
| # Starting a new conversation with a separate checkpoint storage while the | |
| # first conversation has pending `request_info` (human-in-the-loop) responses | |
| # is not currently supported by the agent framework. | |
| # | |
| # Attempting to call `agent.run` again at this point with a different | |
| # `checkpoint_storage` instance will result in: | |
| # AgentExecutionException("Unexpected content type while awaiting request info responses.") | |
| # | |
| # If you need to run multiple conversations, ensure that all human-in-the-loop | |
| # interactions for the first conversation are fully completed before starting | |
| # another conversation, or serialize the conversations so that only one has | |
| # pending `request_info` responses at any given time. |
Copilot
AI
Jan 15, 2026
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.
This multi-line comment documenting a known failure should not be included in a sample file. Sample code should demonstrate working functionality, not document failing test cases. If this is intended as a bug report or investigation, it should be tracked in an issue, not committed to a sample file. Consider removing the second conversation test entirely or fixing the underlying issue before including it in the samples.
| """ | |
| the workflow fails here with the following error: | |
| Traceback (most recent call last): | |
| ......... | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 157, in run | |
| async for update in self._run_stream_impl( | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 246, in _run_stream_impl | |
| function_responses = self._extract_function_responses(input_messages) | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 426, in _extract_function_responses | |
| raise AgentExecutionException("Unexpected content type while awaiting request info responses.") | |
| agent_framework.exceptions.AgentExecutionException: Unexpected content type while awaiting request info responses. | |
| """ |
Copilot
AI
Jan 15, 2026
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.
This code is unreachable because the execution fails at line 143-146 as documented in the comment above. This unreachable code should be removed along with the failed test case.
| checkpoint_storage_2 = InMemoryCheckpointStorage() | |
| checkpoint_repo["conv2"] = checkpoint_storage_2 | |
| response2 = await agent.run( | |
| "A new conversation after human in the loop", | |
| checkpoint_storage=checkpoint_storage_2, | |
| ) | |
| """ | |
| the workflow fails here with the following error: | |
| Traceback (most recent call last): | |
| ......... | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 157, in run | |
| async for update in self._run_stream_impl( | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 246, in _run_stream_impl | |
| function_responses = self._extract_function_responses(input_messages) | |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| File "....\site-packages\agent_framework\_workflows\_agent.py", line 426, in _extract_function_responses | |
| raise AgentExecutionException("Unexpected content type while awaiting request info responses.") | |
| agent_framework.exceptions.AgentExecutionException: Unexpected content type while awaiting request info responses. | |
| """ | |
| print("\n\nconversation 2 completed") | |
| print(f"📤 Agent Response: {response2}") | |
| # Note: a second conversation example that previously attempted to continue | |
| # after human-in-the-loop has been removed due to a known AgentExecutionException | |
| # in the underlying agent framework, which caused the code below to be unreachable. |
Copilot
AI
Jan 15, 2026
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.
This assignment to 'response' is unnecessary as it is redefined before this value is used.
| response = await agent.run( | |
| await agent.run( |
Copilot
AI
Jan 15, 2026
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.
Loading the checkpoint before sending the human review response appears unnecessary. The checkpoint should already contain the pending request state. This extra call to agent.run() doesn't pass any new messages or responses, so it may not serve a clear purpose. Consider clarifying why this step is needed or removing it if it's redundant.
| if last_checkpoint: | |
| # load checkpoint before sending back human review | |
| response = await agent.run( | |
| checkpoint_id=last_checkpoint.checkpoint_id, | |
| checkpoint_storage=checkpoint_storage, | |
| ) |
Uh oh!
There was an error while loading. Please reload this page.