Python: Foundry Hosted Agent Resiliency Support - #7670
Python: Foundry Hosted Agent Resiliency Support#7670Tao Chen (TaoChenOSU) wants to merge 19 commits into
Conversation
Python Test Coverage Report •
Python Unit Test Overview
|
|||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Pull request overview
Adds resilient background recovery for Python Foundry-hosted workflow agents and a countdown sample demonstrating the feature.
Changes:
- Adds workflow checkpoint and response-stream recovery integration.
- Refactors response handling and cancellation plumbing.
- Adds a resilient hosted-agent sample and deployment assets.
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
_responses.py |
Implements resilient workflow recovery and shared response handling. |
test_responses.py |
Updates tests for the refactored handler signature. |
foundry_hosting/README.md |
Minor formatting correction. |
Sample main.py |
Defines the resilient countdown workflow. |
Sample README.md |
Documents running and invoking the sample. |
Sample requirements.txt |
Declares framework dependencies. |
Sample Dockerfile |
Packages the sample container. |
Sample agent.yaml |
Configures the hosted agent. |
Sample agent.manifest.yaml |
Defines deployment metadata and resources. |
Sample .env.example |
Lists required environment variables. |
Sample .dockerignore |
Excludes local Python artifacts and secrets. |
Suppressed comments (1)
python/packages/foundry_hosting/agent_framework_foundry_hosting/_responses.py:643
- The previous implementation rejected an unknown
previous_response_id; this refactor silently starts a fresh workflow when no checkpoint is found. That breaks response chaining by returning an unrelated successful response instead of reporting the missing predecessor. Restore the missing-checkpoint validation.
latest_checkpoint = await restore_checkpoint_storage.get_latest(workflow_name=self._agent.workflow.name)
if latest_checkpoint is not None:
latest_checkpoint_id = latest_checkpoint.checkpoint_id
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| inner = self._handle_inner_workflow( | ||
| request, context, response_event_stream, tracker, cancellation_signal | ||
| ) | ||
| else: | ||
| inner = self._handle_inner_agent(request, context, response_event_stream, tracker, cancellation_signal) |
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: Findings reported
Scope: full PR (18 commit(s)): ff8450b9fe0f, 4cf73d533ca7, 14cf002f7a00, 3df40fd8b17f, 10ab3c334565, 8838c1ede111, 649443c48221, 19303b75a6f4, 95f0ac3181f5, 8d038e37f6c9, 828e5df4263c, 172a5289eef1, 6db0df3f6fc6, 7ac2a9bcf86b, df0d18152f5a, 8b5da3a5e724, b0ac69de72e0, d9e6d5a49eb8
Model: gpt-5.6-sol
Overview
The review found 6 verified inline finding(s).
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
6 verified findings remained after source verification (3 high, 3 medium) across 3 files. Details are attached to the affected lines below.
Affected areas: python/packages/foundry_hosting/agent_framework_foundry_hosting/_responses.py, python/samples/04-hosting/foundry-hosted-agents/responses/resilient_long_running_workflow/main.py, python/samples/04-hosting/foundry-hosted-agents/responses/resilient_long_running_workflow/requirements.txt
| # that fulfill them via :meth:`WorkflowAgent._process_pending_requests`. | ||
| if latest_checkpoint is not None: | ||
| async for _ in self._agent.run( | ||
| if latest_checkpoint is not None: |
There was a problem hiding this comment.
When a caller supplies previous_response_id but that scope has no checkpoint, this now falls through and starts a fresh workflow with the continuation input. The previous behavior failed explicitly; silently resetting state can repeat workflow side effects or interpret a continuation as a new run. Please retain the missing-checkpoint error for response chaining while still allowing genuinely new workflow requests.
|
|
||
| # Resiliency check | ||
| self._resilient_background = bool(options and options.resilient_background) | ||
| if self._resilient_background and not self._is_workflow_agent: |
There was a problem hiding this comment.
The public contract says resilient background mode is supported only for workflows, but this warning leaves the invalid configuration active. On recovery, the non-workflow path restarts the original request, which can duplicate tool calls or other external side effects. Please reject this combination during server construction rather than executing an unsupported recovery mode.
| """Ask the model for a target and forward valid positive integers.""" | ||
| response = await self._agent.run(messages, options={"response_format": CounterTarget}) | ||
| extraction = response.value | ||
| if not isinstance(extraction, CounterTarget) or extraction.target is None or extraction.target <= 0: |
There was a problem hiding this comment.
This accepts an unbounded attacker-controlled counter, while each iteration sleeps and self-enqueues on the server's singleton workflow instance. A very large value keeps that instance active, causes every concurrent request to fail the core single-run guard, and resilient recovery carries the monopolizing run across restarts. Please enforce a bounded execution budget or maximum counter before starting the workflow.
|
An issue discovered while working on this feature: #7677 |
Motivation & Context
Add support for resilient tasks in Foundry Hosted Agent.
Description & Review Guide
resilient_background=TrueinResponsesHostServerContribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.