mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
[BREAKING] Python: Merge send_responses into run method (#3720)
* Streamline workflow run api with send responses in one method * Fixes * Address copilot feedback
This commit is contained in:
committed by
GitHub
Unverified
parent
15256bb616
commit
a17f13598b
+1
-1
@@ -249,7 +249,7 @@ async def run_interactive_session(
|
||||
|
||||
while True:
|
||||
if responses:
|
||||
event_stream = workflow.send_responses_streaming(responses)
|
||||
event_stream = workflow.run(stream=True, responses=responses)
|
||||
requests.clear()
|
||||
responses = None
|
||||
else:
|
||||
|
||||
+19
-18
@@ -23,22 +23,24 @@ from azure.identity import AzureCliCredential
|
||||
"""
|
||||
Sample: Handoff Workflow with Tool Approvals + Checkpoint Resume
|
||||
|
||||
Demonstrates the two-step pattern for resuming a handoff workflow from a checkpoint
|
||||
while handling both HandoffAgentUserRequest prompts and function approval request Content
|
||||
for tool calls (e.g., submit_refund).
|
||||
Demonstrates resuming a handoff workflow from a checkpoint while handling both
|
||||
HandoffAgentUserRequest prompts and function approval request Content for tool calls
|
||||
(e.g., submit_refund).
|
||||
|
||||
Scenario:
|
||||
1. User starts a conversation with the workflow.
|
||||
2. Agents may emit user input requests or tool approval requests.
|
||||
3. Workflow writes a checkpoint capturing pending requests and pauses.
|
||||
4. Process can exit/restart.
|
||||
5. On resume: Load the checkpoint, surface pending approvals/user prompts, and provide responses.
|
||||
5. On resume: Restore checkpoint, inspect pending requests, then provide responses.
|
||||
6. Workflow continues from the saved state.
|
||||
|
||||
Pattern:
|
||||
- Step 1: workflow.run(checkpoint_id=..., stream=True) to restore checkpoint and pending requests.
|
||||
- Step 2: workflow.send_responses_streaming(responses) to supply human replies and approvals.
|
||||
- Two-step approach is required because send_responses_streaming does not accept checkpoint_id.
|
||||
- workflow.run(checkpoint_id=..., stream=True) to restore checkpoint and discover pending requests.
|
||||
- workflow.run(stream=True, responses=responses) to supply human replies and approvals.
|
||||
(Two steps are needed here because the sample must inspect request types before building responses.
|
||||
When response payloads are already known, use the single-call form:
|
||||
workflow.run(stream=True, checkpoint_id=..., responses=responses).)
|
||||
|
||||
Prerequisites:
|
||||
- Azure CLI authentication (az login).
|
||||
@@ -228,13 +230,13 @@ async def resume_with_responses(
|
||||
approve_tools: bool | None = None,
|
||||
) -> tuple[list[WorkflowEvent], str | None]:
|
||||
"""
|
||||
Two-step resume pattern (answers customer questions and tool approvals):
|
||||
Resume from checkpoint and send responses.
|
||||
|
||||
Step 1: Restore checkpoint to load pending requests into workflow state
|
||||
Step 2: Send user responses using send_responses_streaming
|
||||
Step 1: Restore checkpoint to discover pending request types.
|
||||
Step 2: Build typed responses and send via workflow.run(responses=...).
|
||||
|
||||
This is the current pattern required because send_responses_streaming
|
||||
doesn't accept a checkpoint_id parameter.
|
||||
When response payloads are already known, these can be combined into a single
|
||||
workflow.run(stream=True, checkpoint_id=..., responses=...) call.
|
||||
"""
|
||||
print(f"\n{'=' * 60}")
|
||||
print("RESUMING WORKFLOW WITH HUMAN INPUT")
|
||||
@@ -253,10 +255,9 @@ async def resume_with_responses(
|
||||
checkpoints.sort(key=lambda cp: cp.timestamp, reverse=True)
|
||||
latest_checkpoint = checkpoints[0]
|
||||
|
||||
print(f"Step 1: Restoring checkpoint {latest_checkpoint.checkpoint_id}")
|
||||
print(f"Restoring checkpoint {latest_checkpoint.checkpoint_id}")
|
||||
|
||||
# Step 1: Restore the checkpoint to load pending requests into memory
|
||||
# The checkpoint restoration re-emits pending request_info events
|
||||
# First, restore checkpoint to discover pending requests
|
||||
restored_requests: list[WorkflowEvent] = []
|
||||
async for event in workflow.run(checkpoint_id=latest_checkpoint.checkpoint_id, stream=True): # type: ignore[attr-defined]
|
||||
if event.type == "request_info":
|
||||
@@ -274,11 +275,11 @@ async def resume_with_responses(
|
||||
user_response=user_response,
|
||||
approve_tools=approve_tools,
|
||||
)
|
||||
print(f"Step 2: Sending responses for {len(responses)} request(s)")
|
||||
print(f"Sending responses for {len(responses)} request(s)")
|
||||
|
||||
new_pending_requests: list[WorkflowEvent] = []
|
||||
|
||||
async for event in workflow.send_responses_streaming(responses):
|
||||
async for event in workflow.run(stream=True, responses=responses):
|
||||
if event.type == "status":
|
||||
print(f"[Status] {event.state}")
|
||||
|
||||
@@ -309,7 +310,7 @@ async def main() -> None:
|
||||
This sample shows:
|
||||
1. Starting a workflow and getting a HandoffAgentUserRequest
|
||||
2. Pausing (checkpoint is saved automatically)
|
||||
3. Resuming from checkpoint with a user response or tool approval (two-step pattern)
|
||||
3. Resuming from checkpoint with a user response or tool approval
|
||||
4. Continuing the conversation until completion
|
||||
"""
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ async def main() -> None:
|
||||
|
||||
approval_response = "approve"
|
||||
output_event: WorkflowEvent | None = None
|
||||
async for event in workflow2.send_responses_streaming({request_info_event.request_id: approval_response}):
|
||||
async for event in workflow2.run(stream=True, responses={request_info_event.request_id: approval_response}):
|
||||
if event.type == "output":
|
||||
output_event = event
|
||||
|
||||
|
||||
Reference in New Issue
Block a user