Skip to content

Carry over hosted-agent session across azd deploy#8942

Open
harsheet-shah wants to merge 6 commits into
mainfrom
harsheetshah/agent-session-carryover-on-deploy
Open

Carry over hosted-agent session across azd deploy#8942
harsheet-shah wants to merge 6 commits into
mainfrom
harsheetshah/agent-session-carryover-on-deploy

Conversation

@harsheet-shah

@harsheet-shah harsheet-shah commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Closes #8957

Automatically stop the current hosted-agent session during azd deploy and re-point the newly deployed version's session pointer at it, so the next azd ai agent invoke resumes the same session on the new code with its /home/session volume intact instead of minting a fresh session. - session_carryover.go: capture (predeploy) + stop-and-carry-forward (postdeploy) logic, opt-out via AZD_AGENT_SKIP_SESSION_CARRYOVER. - listen.go: wire capture into predeployHandler and carry-over into postdeployHandler (best-effort, never blocks deploy). - session_carryover_test.go: env-flag and guard no-op tests.

Automatically stop the current hosted-agent session during `azd deploy` and
re-point the newly deployed version's session pointer at it, so the next
`azd ai agent invoke` resumes the same session on the new code with its
/home/session volume intact instead of minting a fresh session.

- session_carryover.go: capture (predeploy) + stop-and-carry-forward
  (postdeploy) logic, opt-out via AZD_AGENT_SKIP_SESSION_CARRYOVER.
- listen.go: wire capture into predeployHandler and carry-over into
  postdeployHandler (best-effort, never blocks deploy).
- session_carryover_test.go: env-flag and guard no-op tests.

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

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

This PR adds best-effort “session carry-over” behavior for azure.ai.agents hosted agents during azd deploy, so the next azd ai agent invoke can resume the same session (and its /home/session volume) after a new agent version is deployed.

Changes:

  • Introduces predeploy capture and postdeploy stop+repoint logic for carried sessions, with opt-out via AZD_AGENT_SKIP_SESSION_CARRYOVER.
  • Wires session capture into predeployHandler and session carry-over into postdeployHandler for hosted agents.
  • Adds unit tests for env-flag parsing and guard/no-op behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
cli/azd/extensions/azure.ai.agents/internal/cmd/session_carryover.go Implements in-process stash, capture, stop, and session-pointer repointing across deploys.
cli/azd/extensions/azure.ai.agents/internal/cmd/session_carryover_test.go Adds tests for opt-out behavior and early-return guards.
cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go Hooks session capture into predeploy and carry-over into postdeploy for hosted agents.

Comment on lines +141 to +143
if !sessionCarryoverEnabled() || svc == nil || agentClient == nil {
return
}
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/session_carryover.go Outdated
@github-actions github-actions Bot added the ext-agents azure.ai.agents extension label Jul 2, 2026

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The session carry-over design is solid: pre-deploy capture, post-deploy stop+repoint, with best-effort guarantees that never block deploy. The code uses modern Go patterns correctly (�rrors.AsType, mutex-guarded stash) and the error handling is thorough with informative log messages at every failure point.

One suggestion on test coverage: the current tests verify guard/no-op behavior (disabled flag, nil params), but the interesting logic -- the StopSession error classification (409 conflict vs 404 vs unexpected), the endpoint re-read after deploy, and the config-store write -- is untested. A table-driven test with a fake AgentClient (or httptest server) covering the session_already_stopped proceeds path, the 404 bails-out path, and the successful end-to-end repoint would strengthen confidence in the branching logic and prevent regressions.

if got, ok := stashedSession(svc.Name); !ok || got != "sess-abc" {
t.Fatalf("expected stash untouched when agentClient is nil, got %q (present=%v)", got, ok)
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider adding a test that exercises the StopSession branching -- at minimum the session_already_stopped conflict case (should proceed to repoint) and the 404 case (should bail out). These are the most nuanced code paths and a table-driven test with a fake round-tripper or httptest server would catch regressions in the error-code matching logic.

Replace the AZD_AGENT_SKIP_SESSION_CARRYOVER opt-out env var with an opt-in
per-service azure.yaml field, resumeSessionOnDeploy (default false). This is
more discoverable, versioned with the project, and scoped per agent service.

- config.go: add ResumeSessionOnDeploy to ServiceTargetAgentConfig.
- session_carryover.go: gate capture/carry-over on the per-service field via
  LoadServiceTargetAgentConfig instead of the env var.
- schemas: document resumeSessionOnDeploy in Agent.json and azure.ai.agent.json.
- tests: cover the opt-in/opt-out/absent/nil cases.

Validated live on a Foundry hosted agent: with resumeSessionOnDeploy: true and
no env var, a redeploy + plain invoke resumed the same session on the new code
(BUILD v9 -> v10, /home/session 2 -> 3, volume preserved).

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

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The switch from a global env-var opt-out to per-service resumeSessionOnDeploy config is the right design: more granular, opt-in by default, and source-controlled. Implementation is clean with proper nil/error guards.

My earlier suggestion about testing the deeper carry-over logic (StopSession 409/404 classification, endpoint re-read after deploy, config-store write) still applies as follow-up work for confidence in the branching paths, but is not blocking for this PR.

- Serialize the carry-over read-modify-write of the shared UserConfig
  'sessions' map with a package mutex, since concurrent postdeploy handlers
  could otherwise clobber each other's carried session (last-writer-wins).
- Extract stop-error classification into classifyStopSessionErr and add a
  table-driven test covering nil/409 already-stopped/404/other-409/500/
  non-response cases.
- Document that carry-over consumes the stashed session single-shot and is
  intentionally non-retriable (best-effort contract).

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

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 6 out of 6 changed files in this pull request and generated 3 comments.

Comment on lines +48 to +49
// The behavior is OPT-IN per agent service via `resumeSessionOnDeploy: true` in
// azure.yaml. It is always best-effort and never fails a deploy.
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/session_carryover.go Outdated
Comment on lines +154 to +162
oldKey := buildRemoteAgentKeyFromEndpoint(endpointResp.Value)
sessionID, err := getAgentSpecificContextValue(ctx, azdClient, "sessions", oldKey)
if err != nil || sessionID == "" {
return
}

pendingSessionCarryover.Lock()
pendingSessionCarryover.byService[svc.Name] = sessionID
pendingSessionCarryover.Unlock()
…carryover

Main refactored postdeployHandler and removed the local agentClient and the
agent_api import; the session carry-over call referenced the now-undefined
agentClient (typecheck failure). Rebuild agentClient from the in-scope endpoint
and credential and re-add the agent_api import. Also apply gofmt to
session_carryover.go (stray trailing blank line) so the gofmt lint passes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot mentioned this pull request Jul 3, 2026

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental check: the two new commits (merge main + rebuild agentClient in postdeploy) are mechanical CI fixes. The agent_api.NewAgentClient(endpointResp.Value, cred) construction in postdeployHandler correctly targets the post-deploy endpoint for the StopSession call. No design changes, no new risk.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

📋 Prioritization Note

Thanks for the contribution! The linked issue isn't in the current milestone yet.
Thank you for logging this issue; our team is reviewing it. If you need urgent prioritization, tag @RickWinter and @kristenwomack to let us know.

…zure.yaml field

Revert the opt-in control from a per-service azure.yaml field back to an
environment variable, named resumeSessionOnDeploy. Carry-over is opt-in: off
unless resumeSessionOnDeploy is truthy (1/true/yes/on). Removes the
ServiceTargetAgentConfig.ResumeSessionOnDeploy field and its schema entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-agents azure.ai.agents extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Issue] In hosted agent workflow, add the ability to resume same session after subsequent deploy

3 participants