Skip to content

Python: Fix CopilotStudioAgent to reuse conversation ID from existing session#5299

Open
giles17 wants to merge 2 commits intomicrosoft:mainfrom
giles17:agent/fix-5285-1
Open

Python: Fix CopilotStudioAgent to reuse conversation ID from existing session#5299
giles17 wants to merge 2 commits intomicrosoft:mainfrom
giles17:agent/fix-5285-1

Conversation

@giles17
Copy link
Copy Markdown
Contributor

@giles17 giles17 commented Apr 16, 2026

Motivation and Context

CopilotStudioAgent._run_impl and _run_stream_impl unconditionally called _start_new_conversation() on every run() invocation, overwriting the session's service_session_id even when a persistent session was passed in. This made multi-turn conversations impossible because each call started a fresh server-side conversation with no memory of prior turns.

Fixes #5285

Description

The root cause was that both _run_impl and _run_stream_impl always replaced session.service_session_id with a new conversation ID, ignoring any existing value. The fix adds a guard (if not session.service_session_id) so that _start_new_conversation() is only called when the session does not already carry a conversation ID, allowing calers to reuse the same session across multiple run() calls for continuous dialog. Regression tests verify that both the non-streaming and streaming paths skip start_conversation and pass the existing conversation ID to ask_question when a session already has a service_session_id.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Note: PR autogenerated by giles17's agent

…rosoft#5285)

CopilotStudioAgent unconditionally called _start_new_conversation() in both
_run_impl and _run_stream_impl, ignoring any existing service_session_id on
the session. Add a guard to only start a new conversation when there is no
existing service_session_id, matching the pattern used by other agents.

Also fix pre-existing pyright reportMissingImports errors for orjson in
file_history_provider samples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 16, 2026 04:23
@giles17 giles17 self-assigned this Apr 16, 2026
Copy link
Copy Markdown
Contributor Author

@giles17 giles17 left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 93%

✓ Correctness

The fix correctly guards _start_new_conversation() behind if not session.service_session_id: in both _run_impl and _run_stream_impl, matching the pattern used by other agents (GitHub Copilot, Claude). AgentSession.service_session_id defaults to None (confirmed in _sessions.py:179), so the falsy check works correctly. The two new tests properly verify that an existing service_session_id is preserved and start_conversation is not called. The orjson type-ignore comments in the sample files are harmless cosmetic changes. No correctness issues found.

✓ Security Reliability

The fix is correct and well-tested. It adds a simple guard (if not session.service_session_id) before calling _start_new_conversation() in both the streaming and non-streaming paths, preventing the agent from discarding an existing conversation ID. The service_session_id attribute on AgentSession defaults to None (confirmed at _sessions.py:739), so the truthiness check is appropriate. Two new tests properly verify that start_conversation is not called when a session already has a conversation ID. The orjson type-ignore comments in the sample files are harmless cosmetic changes. No security or reliability concerns.

✓ Test Coverage

The test coverage for the bug fix is solid. Two new tests (test_run_reuses_existing_conversation and test_run_streaming_reuses_existing_conversation) properly verify both the non-streaming and streaming paths. The assertions are meaningful: they check that start_conversation is not called, that ask_question receives the existing conversation ID, and that the session ID is preserved. The existing tests continue to cover the new-conversation path (where service_session_id starts as None). No blocking issues found.

✓ Design Approach

The core fix is correct and well-motivated: adding if not session.service_session_id: guards in both _run_impl and _run_stream_impl matches the pattern used by every other agent in the framework and is backed by solid tests. The new tests verify both non-streaming and streaming session reuse paths, check that start_conversation is not called, and confirm the existing ID is forwarded to ask_question. No design issues with the main change. A minor issue exists in the sample file changes: # type: ignore[reportMissingImports] is not valid syntax for either mypy (which uses error codes like import) or pyright (which uses # pyright: ignore[...]). The repo's own convention, as seen in other sample files, is # pyright: ignore[...], so the suppression comment as written is effectively a no-op.

Suggestions

  • Consider adding a multi-turn integration-style test that calls run twice on the same session: first without a service_session_id (triggering _start_new_conversation), then a second time verifying the session reuses the ID from the first call. This would exercise the full lifecycle and catch any mutation issues between calls.
  • The # type: ignore[reportMissingImports] comment added in both sample files uses invalid mixed syntax — reportMissingImports is a pyright code but # type: ignore is mypy syntax. Neither tool will recognize this. Change to # pyright: ignore[reportMissingImports] to match project convention and actually suppress the warning.

Automated review by giles17's agents

Comment thread python/samples/02-agents/conversations/file_history_provider.py Outdated
@moonbox3
Copy link
Copy Markdown
Contributor

moonbox3 commented Apr 16, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/copilotstudio/agent_framework_copilotstudio
   _agent.py86297%174, 182
TOTAL27692319888% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
5613 20 💤 0 ❌ 0 🔥 1m 33s ⏱️

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes Copilot Studio multi-turn behavior by preserving an existing AgentSession.service_session_id (conversation ID) across repeated run() calls, enabling server-side conversation continuity (Fixes #5285).

Changes:

  • Guarded _start_new_conversation() in both non-streaming and streaming execution paths so it only runs when session.service_session_id is unset.
  • Added regression tests verifying start_conversation is skipped and ask_question receives the existing conversation ID when a session already has one.
  • Updated two conversation sample files to suppress optional orjson import typing errors.

Reviewed changes

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

File Description
python/packages/copilotstudio/agent_framework_copilotstudio/_agent.py Reuses existing service_session_id instead of always starting a new conversation.
python/packages/copilotstudio/tests/test_copilot_agent.py Adds regression tests for conversation ID reuse in both streaming and non-streaming paths.
python/samples/02-agents/conversations/file_history_provider.py Adds typing ignore for optional orjson import in sample.
python/samples/02-agents/conversations/file_history_provider_conversation_persistence.py Adds typing ignore for optional orjson import in sample.

@giles17 giles17 closed this Apr 16, 2026
@giles17 giles17 deleted the agent/fix-5285-1 branch April 16, 2026 16:28
Remove unrelated orjson type-ignore comment changes from sample files
that were outside the scope of the conversation-ID reuse fix.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Bug]: CopilotStudioAgent creates a new conversation on every run(), ignoring the session= parameter

4 participants