mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Add reset to hosted workflow
This commit is contained in:
@@ -649,6 +649,12 @@ class ResponsesHostServer(ResponsesAgentServerHost):
|
||||
checkpoint_id=latest_checkpoint_id,
|
||||
checkpoint_storage=restore_storage,
|
||||
)
|
||||
else:
|
||||
# We reset the workflow if neither conversation_id nor previous_response_id
|
||||
# was supplied, because this implies there's no prior state to restore and
|
||||
# we want to ensure a clean slate. Workflow may contain in-memory state that
|
||||
# needs to be cleared on new conversations.
|
||||
await self._agent.workflow.reset_for_new_run()
|
||||
|
||||
# Now run the agent with the latest input
|
||||
response_event_stream = ResponseEventStream(response_id=context.response_id, model=request.model)
|
||||
|
||||
@@ -3971,5 +3971,80 @@ class TestWorkflowAgentHosting:
|
||||
assert len(approval_responses) == 1
|
||||
assert approval_responses[0].approved is False # type: ignore[attr-defined]
|
||||
|
||||
async def test_workflow_is_reset_when_no_prior_conversation(self) -> None:
|
||||
"""Without ``previous_response_id`` or ``conversation_id`` the host must
|
||||
reset the workflow so any in-memory state from a previous request is
|
||||
cleared before the new turn runs."""
|
||||
workflow_agent = _build_text_workflow_agent("fresh")
|
||||
server = _make_server(workflow_agent)
|
||||
|
||||
with patch.object(
|
||||
workflow_agent.workflow,
|
||||
"reset_for_new_run",
|
||||
new=AsyncMock(wraps=workflow_agent.workflow.reset_for_new_run),
|
||||
) as reset_spy:
|
||||
resp = await _post(server, input_text="hi", stream=False)
|
||||
|
||||
assert resp.status_code == 200
|
||||
assert reset_spy.await_count == 1
|
||||
|
||||
async def test_workflow_is_reset_across_independent_requests(self) -> None:
|
||||
"""Two consecutive requests without a chaining context id must each
|
||||
reset the workflow."""
|
||||
workflow_agent = _build_text_workflow_agent("again")
|
||||
server = _make_server(workflow_agent)
|
||||
|
||||
with patch.object(
|
||||
workflow_agent.workflow,
|
||||
"reset_for_new_run",
|
||||
new=AsyncMock(wraps=workflow_agent.workflow.reset_for_new_run),
|
||||
) as reset_spy:
|
||||
first = await _post(server, input_text="hi", stream=False)
|
||||
second = await _post(server, input_text="hi again", stream=False)
|
||||
|
||||
assert first.status_code == 200
|
||||
assert second.status_code == 200
|
||||
assert reset_spy.await_count == 2
|
||||
|
||||
async def test_workflow_is_not_reset_when_resuming_from_checkpoint(self) -> None:
|
||||
"""When ``previous_response_id`` resolves to an existing workflow
|
||||
checkpoint the host restores the checkpoint instead of resetting
|
||||
the workflow."""
|
||||
workflow_agent, _ = _build_approval_workflow_agent(
|
||||
approval_request_id="apr_no_reset",
|
||||
final_text="resumed",
|
||||
)
|
||||
server = _make_server(workflow_agent)
|
||||
|
||||
first = await _post(server, stream=False)
|
||||
assert first.status_code == 200
|
||||
first_body = first.json()
|
||||
first_response_id = first_body["id"]
|
||||
approval_request_id = next(it["id"] for it in first_body["output"] if it["type"] == "mcp_approval_request")
|
||||
|
||||
with patch.object(
|
||||
workflow_agent.workflow,
|
||||
"reset_for_new_run",
|
||||
new=AsyncMock(wraps=workflow_agent.workflow.reset_for_new_run),
|
||||
) as reset_spy:
|
||||
second = await _post_json(
|
||||
server,
|
||||
{
|
||||
"model": "test-model",
|
||||
"input": [
|
||||
{
|
||||
"type": "mcp_approval_response",
|
||||
"approval_request_id": approval_request_id,
|
||||
"approve": True,
|
||||
}
|
||||
],
|
||||
"stream": False,
|
||||
"previous_response_id": first_response_id,
|
||||
},
|
||||
)
|
||||
|
||||
assert second.status_code == 200
|
||||
assert reset_spy.await_count == 0
|
||||
|
||||
|
||||
# endregion
|
||||
|
||||
Reference in New Issue
Block a user