Skip to content

Python: [BREAKING] Split Foundry agent and native workflow hosts - #10224

Open
Eduard van Valkenburg (eavanvalkenburg) wants to merge 2 commits into
python-foundry-hosting-rcfrom
split-foundry-hosts
Open

Eduard van Valkenburg (eavanvalkenburg) wants to merge 2 commits into
python-foundry-hosting-rcfrom
split-foundry-hosts

Conversation

@eavanvalkenburg

Copy link
Copy Markdown
Member

Motivation & Context

Agent and native workflow hosting have different construction, history, and persistence contracts. Separate host classes make the supported execution model and its required inputs explicit instead of exposing mode-dependent settings through a combined constructor.

This targets the coordinated python-foundry-hosting-rc feature branch. It implements the agreed host split and the parser/request and source naming choices approved by Eduard during implementation. At his request, it also consolidates the #10015/#10018 work from the now-closed #10187 so those changes do not need to be reapplied across moved modules.

Description & Review Guide

  • What are the major changes? Keep ResponsesHostServer and InvocationsHostServer for agents; add ResponsesWorkflowHostServer and InvocationsWorkflowHostServer for native workflows. Require request-aware native workflow factories and explicit parse_input callbacks. Support request-aware agent factories while retaining zero-argument factories. Rename HostedResponseRequest to ResponsesRequest, align history/background source literals, and remove the constructor store= alias. Group implementation into _responses_agent, _responses_workflow, _responses_shared, equivalent Invocations modules, and a cross-protocol _shared. Update exports, regression tests, maintained samples, migration guidance, consumer documentation, and proposed ADR 0055.
  • What is the impact of these changes? This is a coordinated breaking constructor/import migration with no combined-host or old-name aliases. Agent hosts reject WorkflowAgent instances and factory results; workflow hosts reject agents and built workflow instances. Workflow hosts expose checkpoint storage instead of agent-session/history settings. Factory construction retains the existing shared-execution-resource guard: a fresh graph around shared executors is not sufficient. Defaults retain their meaning, and wire formats, option precedence, agent approval-store APIs, checkpoint-owned workflow pending authority, ownership, and supported agent inference-service background behavior remain unchanged. The supported response_store= backend and wire-level per-request store flag are preserved. Responses remains the initial stable-surface target; Invocations and Toolbox stay experimental in one package.
  • What do you want reviewers to focus on? Check public construction and imports, agent/workflow rejection before dispatch, request-aware factory timing and cleanup, graph-resource isolation, and preservation of streaming/non-streaming continuation and background behavior. Most protocol-engine changes are moves or extraction; obsolete WorkflowAgent host paths and their tests are removed rather than retained as compatibility layers.

Before:

from agent_framework_foundry_hosting import HostedResponseRequest, ResponsesHostServer

async def parse_response(request: HostedResponseRequest):
    return await parse_workflow_turn(request)

server = ResponsesHostServer(workflow=build_workflow, parse_response=parse_response)

After:

from agent_framework_foundry_hosting import ResponsesRequest, ResponsesWorkflowHostServer, WorkflowTurn

async def parse_input(request: ResponsesRequest) -> WorkflowTurn:
    return await parse_workflow_turn(request)

# Build fresh workflows, executors, agents, clients, and mutable tools per request.
# Keep workflow names and executor IDs stable for checkpoint restoration.
server = ResponsesWorkflowHostServer(workflow=build_workflow, parse_input=parse_input)

The application supplies build_workflow and parse_workflow_turn. Parsers still return either typed start input or complete validated pending replies. Invocations agent and workflow parser keywords also become parse_input; agent parsers return InvocationRun, while workflow parsers return WorkflowTurn.

Responses agent construction still uses agent=, with history_source="host_managed" (default), "agent_managed", or "inference_service" instead of "agent_server", "agent", or "service". Background sources become "host_managed" (default) and "inference_service" instead of "agent_server" and "provider". agent_managed retains developer-owned provider or service storage. Use response_store=backend, not the removed constructor store=backend; even store=None is rejected before SDK construction.

Responses factories receive ResponsesRequest before prepare_options; Invocations factories receive the Starlette Request after parsing and option preparation. When both request and zero-argument call shapes bind, the request form wins. Factory-body exceptions do not trigger a retry with another call shape. Factory-owned context-managed agents are entered and closed per request.

Agent foreground/background execution remains separate from recovery permission. Supported inference-service agent background still requires inference-service history. Outer workflow background does not enable provider background on workflow agents. Native workflow state and pending replies remain checkpoint-owned. This does not redesign concurrency, checkpoints, retries, approvals, consent, routing, dependencies, or the SDK options surface, and the identity guard is not a proof of arbitrary global-state isolation.

Checks completed locally:

  • uv run --directory python poe test -P foundry_hosting — passed: 1,137 tests, 36 integration tests deselected, 91% coverage.
  • uv run --directory python poe syntax -P foundry_hosting — passed.
  • uv run --directory python poe pyright -P foundry_hosting — passed, no errors or warnings.
  • uv run --directory python poe test-typing -P foundry_hosting — passed all five configured test checkers.
  • uv run --directory python/packages/foundry_hosting pytest -q --import-mode=prepend -m integration --runxfail tests/test_responses_int.py::TestWorkflowResilientRecoveryRealCrash — passed all eight model-free real-process crash/recovery cases. prepend avoids an existing installed Core test-namespace collision; the existing readiness xfail marker is otherwise unchanged.
  • uv run --directory python pytest -q -c packages/core/pyproject.toml packages/core/tests/core/test_foundry_namespace.py — passed both tests.
  • uv run --directory python -m scripts.check_md_code_blocks packages/foundry_hosting/README.md --no-glob — passed. The same checker also passed for all 20 changed Python Markdown documents.
  • Configured Ruff and relaxed Pyright checks on the 24 changed samples — passed. Pyrefly passed with the harness excluded by existing configuration. Ty passed for the other 23 samples; including the harness reports its pre-existing asynccontextmanager/AsyncIterator deprecation at hosted.py:163, verified in the base revision and left outside this change.
  • git diff --check — passed.

Credentialed integration tests, live Foundry deployment, and a distribution build were not run.

Related Issue

Fixes #10010
Fixes #10014
Fixes #10015
Fixes #10018

Relates to #7688: includes only the narrowly coupled factory construction and existing resource-isolation guard coverage, not the broader workflow roadmap.

Supersedes closed #10187 at Eduard's request, including both its source-literal changes and constructor-alias removal. No competing open PR was found for these issues. The host split has explicit maintainer agreement in #10010; the final public names, migration, and consolidation were approved during the dedicated implementation session.

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: Copilot assisted with implementation, module restructuring, regression tests, samples, migration documentation, validation, and this PR description.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

@agent-framework-automation agent-framework-automation Bot added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python breaking change Usage: [PRs], Target: all PRs that introduce changes that are not backward compatible labels Nov 10, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAF Automated Review — Iteration 1

Result: No findings
Scope: full PR (1 commit(s)): a696e1ebfc72
Model: gpt-5.6-sol

Overview

The PR cleanly separates agent and native-workflow hosts while preserving protocol behavior through explicit constructor validation, request-aware factories, checkpoint-owned workflow state, and synchronized runtime/type exports. Fresh-graph identity checks, strict pending-reply validation, bounded Invocations snapshots, cancellation-shielded cleanup, and extensive lifecycle tests address the highest-risk migration paths. The review found no Critical, High, or Medium defect introduced by this change.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAF Automated Review — Iteration 2

Result: No findings
Scope: 1 net-new commit(s): 5a6635104e1e
Model: gpt-5.6-sol

Overview

This increment replaces ambiguous agent-factory dispatch with an explicit named request contract and validates that contract before SDK construction. The implementation calls factories once by keyword, rejects incompatible signatures and workflow-agent results, and adds regression coverage for ambiguous signatures, configured factories, exception behavior, ownership, and cleanup. Those guards and the documented breaking migration leave no publishable Critical, High, or Medium finding in the authoritative incremental range.

Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

This branch was previously deployed

1 inactive deployment
github-app-auth — 5a663510 Deployed Nov 10, 2026 by eavanvalkenburg via team_check #9187
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Usage: [PRs], Target: all PRs that introduce changes that are not backward compatible documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants