Skip to content

[agentserver-core] Update task client to Routines=V2Preview opt-in header - #48617

Merged
Nathandrake229 merged 14 commits into
mainfrom
users/naman/tasks-routines-v2preview
Aug 18, 2026
Merged

Nathandrake229 merged 14 commits into
mainfrom
users/naman/tasks-routines-v2preview

Conversation

@Nathandrake229

Copy link
Copy Markdown
Member

Summary

Aligns the hosted task provider's Foundry-Features opt-in header with the Routines V1Preview → V2Preview rename in the agentserver-persistence TypeSpec contract.

Change

Single line in sdk/agentserver/azure-ai-agentserver-core/azure/ai/agentserver/core/tasks/_client.py:

- HeadersPolicy(base_headers={"Foundry-Features": "Routines=V1Preview"}),
+ HeadersPolicy(base_headers={"Foundry-Features": "Routines=V2Preview"}),

The HostedTaskProvider calls {FOUNDRY_PROJECT_ENDPOINT}/tasks — the operations defined by the agentserver-persistence REST contract, which are gated behind the Routines preview opt-in key. That key was renamed from routines_v1_preview (Routines=V1Preview) to routines_v2_preview (Routines=V2Preview) in Azure/azure-rest-api-specs#45520.

Testing

tests/tasks contract/conformance suite: 602 passed, 51 skipped, 0 failed locally.

⚠️ Rollout note

This client header must match the deployed service. The V2 rename currently lives only on the specs feature/foundry-release branch; main service is still on V1Preview. Do not merge until the service adopting Routines=V2Preview is confirmed live, otherwise the client will send an opt-in key the service does not yet recognize.

Related: Azure/azure-rest-api-specs#45520

Naman Tyagi and others added 12 commits August 14, 2026 13:28
Make the durable-response/task subsystem strictly opt-in via
`set_resilient_tasks_enabled` (auto-set by `resilient_background` /
`steerable_conversations`). Previously every responses host wrapped all
`store=true` responses in internal resilient tasks and therefore forced the
boot-time recovery scan, even for a plain host that opted into nothing.

Core (_base.py):
- Construct the TaskManager (and run startup recovery) ONLY when the switch is
  enabled. When off, no manager is installed; `get_task_manager()` raises
  `TaskManagerNotInitialized` and callers degrade to non-durable in-process
  execution. A plain host pays nothing: no manager, no task-store call.

Responses:
- ResilientResponseOrchestrator auto-enables the switch when
  `resilient_background` or `steerable_conversations` is set, so resilient
  deployments keep full Row 1/2/3 recovery.
- _start_resilient_background swallows `TaskManagerNotInitialized` at the
  single outer catch and runs the handler in-process (non-durable). Removed the
  hosted fail-loud branch and the now-unused `_is_hosted_environment` helper.

Tests/samples:
- Updated the opt-in gate tests for gated construction.
- Rewrote the resilient-start-failure contract test: no-manager now swallows and
  runs in-process (real task-store start failures with a manager present still
  fail loud as platform errors).
- Conformance `_test_handler` enables the switch so Row 2
  (resilient_background=False) still validates mark-failed-on-crash.
- Invocations resilient samples (research, multiturn, langgraph) enable the
  switch explicitly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Emit a one-time WARNING at responses host startup when the durable-response
subsystem is off (store=true responses are non-durable across an ungraceful
crash), and an INFO when it is enabled, so operators are not surprised by the
plain non-durable default. Reflects the final resolved state (after the
resilient orchestrator's resilient_background/steerable auto-enable).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Narrow the responses auto-enable of the resilient-tasks switch to
`resilient_background` only; `steerable_conversations` no longer implicitly
enables the durable subsystem. Recovery is tied to resilient_background alone; a
steerable host that wants durability sets resilient_background=True (or the
switch explicitly). The two-switch UX is a known rough edge to smooth over
post-Public-Preview.

Steering conformance handler now enables the switch explicitly, since steering
(multi-turn input queuing) needs the TaskManager regardless of
resilient_background.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…cations samples

- Rewrite set_resilient_tasks_enabled/_enablement docs to describe the switch as
  the opt-in gate for TaskManager construction (not just the recovery scan), and
  that a declared @task no longer implicitly enables it.
- Update core README + tasks-guide to show the required opt-in, and core/responses
  CHANGELOGs with the breaking-change note.
- Fix _start_resilient_background docstring: TaskManagerNotInitialized is now
  swallowed (in-process fallback) regardless of hosting; only real task-start
  failures raise/tag platform errors.
- Rewrite the swallow contract test to enter the ASGI lifespan with the switch
  off, assert no TaskManager is installed, and poll GET to completion.
- Revert the 3 invocations resilient sample edits (unrelated api.md whitespace
  consistency drift); sample opt-in to be handled as a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Initialized message

- The switch-off contract tests asserted get_task_manager() raises, but the
  process-global TaskManager singleton can leak from a prior test in a shared
  pytest process (CI), causing DID-NOT-RAISE. The _switch_off fixture now also
  snapshots/resets/restores the manager singleton (set_task_manager(None)), so
  the no-manager path is exercised deterministically.
- Make the TaskManagerNotInitialized message actionable: it now names
  set_resilient_tasks_enabled(True) and the responses resilient_background=True
  option instead of a generic 'ensure resilient tasks are enabled'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ake)

The switch-off contract tests asserted get_task_manager() raises after entering
the lifespan, but that depended on process-global manager/flag state (mutated by
1400+ other tests) and on which core build performs manager construction — making
it fail deterministically in CI while passing locally. Force the no-manager
condition explicitly via set_task_manager(None) inside the running lifespan so
the responses SWALLOW path is exercised robustly. Core's gating of manager
construction is covered separately by the core opt-in tests.

Verified in a Linux (WSL) full-suite run: both tests pass among 1436 others.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…a helper

The added durability-mode startup log pushed ResponsesAgentServerHost.__init__
over the 50-statement pylint limit (53/50, R0915). Move the startup config +
resilience-mode logging into a module-level _log_startup_configuration() helper,
called once from __init__. Also correct the resilience note to reflect that only
resilient_background auto-enables the subsystem (not steerable_conversations).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ation

Copilot review fixes:
- _RUNTIME_REFS leak: start_resilient() cached per-request refs keyed by
  response_id but only the resilient task body's finally evicts them. When
  primitive .start() raises (e.g. TaskManagerNotInitialized on the opt-out
  fallback), the body never runs, permanently retaining record/context/parsed/
  cancel. Pop the entry on any start failure before propagating.
- Ambiguous TaskManagerNotInitialized: instead of a per-request switch check
  (which broke non-lifespan test clients that auto-enable via
  resilient_background), AgentServerHost now FAILS THE LIFESPAN when resilient
  tasks are enabled but manager construction/startup fails - fail-fast at boot.
  A missing manager at request time therefore means opt-out, so the responses
  swallow stays unconditional (in-process non-durable fallback).
- ASCII-only TaskManagerNotInitialized message (the em-dash broke latin-1 HTTP
  header encoding on the platform-error path).

Test isolation:
- Add an autouse fixture in the responses tests that snapshots/restores the
  process-global resilient-tasks switch + TaskManager singleton per test, so a
  resilient_background=True host in one test no longer leaks enabled state into
  later tests (was causing integration failures when run after resilient e2e).
- Add a core test asserting the lifespan fails fast on boot startup failure.

Verified on Linux (WSL): core optin 12, responses contract 6, and the full
responses suite (minus the POSIX-only crash-harness dir) 1436 passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When resilient tasks are enabled and TaskManager.startup() raises, the manager
was already installed globally via set_task_manager() but the lifespan aborts
before the shutdown block, leaving a failed/partially-started manager visible
through get_task_manager(). Wrap startup with best-effort shutdown + clear the
singleton before re-raising. The startup-failure test now asserts the singleton
is cleared (and shutdown was invoked).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Aligns the hosted task provider's Foundry-Features opt-in header with the
Routines V1Preview -> V2Preview rename in the agentserver-persistence
TypeSpec contract (azure-rest-api-specs #45520).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the Hosted Agents sdk/agentserver/* label Aug 18, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
9 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@Nathandrake229
Nathandrake229 marked this pull request as ready for review August 18, 2026 05:46
Copilot AI balanced review requested due to automatic review settings August 18, 2026 05:46
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
9 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI 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.

Pull request overview

Updates the hosted task provider to match the V2 preview contract.

Changes:

  • Changes Foundry-Features from Routines=V1Preview to Routines=V2Preview.
  • Requires coordination with the service rollout.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Addresses PR review feedback: the transport conformance test sent requests
but did not verify the Foundry-Features opt-in value, so it would pass with
the old or a misspelled key. Extend test_request_carries_user_agent_and_request_id
to assert the emitted header is exactly 'Routines=V2Preview'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 18, 2026 09:58

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Nathandrake229
Nathandrake229 enabled auto-merge (squash) August 18, 2026 10:25
@Nathandrake229
Nathandrake229 merged commit a94a8aa into main Aug 18, 2026
21 checks passed
@Nathandrake229
Nathandrake229 deleted the users/naman/tasks-routines-v2preview branch August 18, 2026 10:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Hosted Agents sdk/agentserver/*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants