[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:
Evan Mattson
2026-02-07 07:32:38 +09:00
committed by GitHub
Unverified
parent 15256bb616
commit a17f13598b
39 changed files with 561 additions and 335 deletions
@@ -208,9 +208,9 @@ async def _run_workflow(workflow: Workflow, user_inputs: list[str]) -> None:
responses = {req.request_id: HandoffAgentUserRequest.terminate() for req in pending_requests}
# Send responses and get new events
# We use send_responses_streaming() to get events as they occur, allowing us to
# display agent responses in real-time and handle new requests as they arrive
workflow_result = await workflow.send_responses(responses)
# We use run(responses=...) to get events, allowing us to
# display agent responses and handle new requests as they arrive
workflow_result = await workflow.run(responses=responses)
pending_requests = _handle_events(workflow_result)
@@ -255,9 +255,9 @@ async def main() -> None:
}
# Send responses and get new events
# We use send_responses() to get events from the workflow, allowing us to
# We use run(responses=...) to get events from the workflow, allowing us to
# display agent responses and handle new requests as they arrive
events = await workflow.send_responses(responses)
events = await workflow.run(responses=responses)
pending_requests = _handle_events(events)
"""
@@ -191,7 +191,7 @@ async def main() -> None:
print(f"\nUser: {user_input}")
responses = {request.request_id: HandoffAgentUserRequest.create_response(user_input)}
events = await _drain(workflow.send_responses_streaming(responses))
events = await _drain(workflow.run(stream=True, responses=responses))
requests, file_ids = _handle_events(events)
all_file_ids.extend(file_ids)
input_index += 1
@@ -29,7 +29,7 @@ Concepts highlighted here:
must keep stable IDs so the checkpoint state aligns when we rebuild the graph.
2. **Executor snapshotting** - checkpoints capture the pending plan-review request
map, at superstep boundaries.
3. **Resume with responses** - `Workflow.send_responses_streaming` accepts a
3. **Resume with responses** - `Workflow.run(responses=...)` accepts a
`responses` mapping so we can inject the stored human reply during restoration.
Prerequisites:
@@ -157,7 +157,7 @@ async def main() -> None:
# Supply the approval and continue to run to completion.
final_event: WorkflowEvent | None = None
async for event in resumed_workflow.send_responses_streaming({request_info_event.request_id: approval}):
async for event in resumed_workflow.run(stream=True, responses={request_info_event.request_id: approval}):
if event.type == "output":
final_event = event
@@ -139,14 +139,14 @@ async def main() -> None:
print("=" * 60)
# Initiate the first run of the workflow.
# Runs are not isolated; state is preserved across multiple calls to run or send_responses_streaming.
# Runs are not isolated; state is preserved across multiple calls to run.
stream = workflow.run(task, stream=True)
pending_responses = await process_event_stream(stream)
while pending_responses is not None:
# Run the workflow until there is no more human feedback to provide,
# in which case this workflow completes.
stream = workflow.send_responses_streaming(pending_responses)
stream = workflow.run(stream=True, responses=pending_responses)
pending_responses = await process_event_stream(stream)