microsoft / microsoft/agent-framework
Python: [Feature]: First-class background execution for workflows (parity with agent Background Responses)
@eavanvalkenburg is already working on this.
Since Sep 12, 2026.
- Dominant language
- Python
- Stars
- 13.6k
- Forks
- 2.3k
- Avg merge
- 2d 45m
- Merged PRs (30d)
- 358
Description
Description
Agents already have Background Responses: start a long run, get a continuation_token, poll or resume until the token is None.
response = await agent.run(
messages="...",
session=session,
options={"background": True},
)
while response.continuation_token is not None:
await asyncio.sleep(2)
response = await agent.run(
session=session,
options={"continuation_token": response.continuation_token},
)
We want the same submit → handle → poll to a terminal state experience for workflows, including when the workflow is exposed as an agent.
What we tried / observed:
workflow.run(..., options={"background": True})is not a supported API.workflow.as_agent().run(..., options={"background": True})also does not work.WorkflowAgent.run()does not acceptoptions, and internally callsworkflow.run()(checkpoint /responses/checkpoint_id), so the OpenAI/Azure Responsesbackground+continuation_tokenpath never applies.- Core workflows can persist and resume via checkpoint storage (
checkpoint_id+checkpoint_storage). That is pause/resume of the graph, not a first-class background run handle. - Foundry hosting can do protocol-level
background=truefor workflow agents whenResponsesServerOptions(resilient_background=True)is set. That is host/protocol recovery, not an in-processWorkflow.run/WorkflowAgent.runoption. Regular (non-workflow) agents cannot useresilient_background.
Related but broader: #1441 (timeouts, durable timers, executor polling). This issue is specifically about API parity with agent Background Responses for a whole workflow run.
What we are asking
- What is the recommended way today to start a workflow in the background and poll for completion / resume after disconnect or process restart?
- Should platforms treat this as:
- wrap
workflow.run(...)in our own task + persistcheckpoint_id, or - host the workflow as an agent and use Foundry/Responses
background=true, or - something else?
- wrap
- Is a first-class API planned, for example:
result = await workflow.run(
message="...",
checkpoint_storage=storage,
options={"background": True},
)
# result.continuation_token or result.run_id for polling
or the same shape on workflow.as_agent().run(...)?
Expected behavior we want: one stable handle for the workflow run, pollable status (running / completed / failed / paused), and resume after client disconnect without inventing a second job system.
Code Sample
from agent_framework import InMemoryCheckpointStorage
workflow = build_workflow() # WorkflowBuilder(...).build()
# Desired (does not exist today)
agent = workflow.as_agent(name="report-workflow")
response = await agent.run(
"Generate the weekly report",
options={"background": True},
)
while response.continuation_token is not None:
response = await agent.run(options={"continuation_token": response.continuation_token})
What actually happens: TypeError: WorkflowAgent.run() got an unexpected keyword argument 'options'.
Checkpoint-based alternative we know about:
storage = InMemoryCheckpointStorage()
# run until interrupted, then:
latest = await storage.get_latest(workflow_name=workflow.name)
await workflow.run(checkpoint_id=latest.checkpoint_id, checkpoint_storage=storage)
That works for resume, but it is not the same as submitting a background run and polling a framework-issued handle.
Language/SDK
Both (question is about the shared model; we are using Python)
Additional context
Docs that led us here:
- https://learn.microsoft.com/en-us/agent-framework/agents/background-responses
python/samples/02-agents/background_responses.pypython/samples/03-workflows/checkpoint/checkpoint_with_resume.pypython/samples/03-workflows/checkpoint/workflow_as_agent_checkpoint.pypython/samples/04-hosting/foundry-hosted-agents/responses/resilient_long_running_workflow/
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.