Python: Add FoundryAgent conversation session helper#6623
Python: Add FoundryAgent conversation session helper#6623eavanvalkenburg wants to merge 5 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Automated Code Review
Reviewers: 5 | Confidence: 92%
✓ Correctness
The implementation is correct and well-defended. The create_conversation_session method properly validates inputs, handles edge cases (missing conversations client, empty conversation ID), and correctly delegates to the existing get_session method. The test coverage is thorough. No correctness issues found.
✓ Security Reliability
The implementation is defensively written with proper type checking (isinstance check for client type), safe attribute access (getattr with None defaults), and input validation (non-empty conversation ID check). Error paths are clearly defined with appropriate exception types. No injection risks, resource leaks, or unhandled failure modes were identified. The await call on create_conversation() will naturally propagate network/auth errors to the caller, which is the expected pattern.
✓ Test Coverage
The test coverage for the new
create_conversation_sessionmethod is comprehensive. Tests cover the happy path, caller-supplied session IDs, and all practically-reachable error conditions (RuntimeError for missing conversations client, ValueError for empty/missing conversation ID). Assertions are meaningful—they verify return types, specific attribute values, and mock interactions. The only untested error path is the TypeError guard (line 776-777), but this is a defensive check that is unreachable through normal construction since the constructor already validates client_type at line 679.
✓ Failure Modes
The create_conversation_session implementation is well-structured for failure handling. It validates preconditions (client type check, SDK capability check via getattr chain), validates postconditions (non-empty conversation ID), and does not swallow exceptions from the underlying network call. The getattr chain correctly handles None conversations (getattr(None, 'create', None) returns None, caught by the subsequent check). No silent failures, lost errors, partial writes, or missing cleanup paths were identified.
✗ Design Approach
I found one design issue in the new helper: it creates a fresh project OpenAI client for conversation creation instead of reusing the configured client path that
FoundryAgentwas constructed with. That means constructor-level OpenAI settings likedefault_headersandtimeoutare applied torun(...)requests but silently skipped forcreate_conversation_session(...), so the new API can behave differently from the rest of the agent in setups that depend on those options.
Flagged Issues
-
create_conversation_session()bypasses the configured OpenAI client settings. The constructor documentsdefault_headersas applying to "requests made through the OpenAI client" and applies bothdefault_headersandtimeoutwhen it first builds the client (python/packages/foundry/agent_framework_foundry/_agent.py:208-216,261-268), but the new helper recreates a client withself.client.project_client.get_openai_client()and no kwargs (python/packages/foundry/agent_framework_foundry/_agent.py:779-785). In any deployment that relies on custom headers or a non-default timeout,agent.run(...)andagent.create_conversation_session()will now hit the service with different client configuration.
Automated review by eavanvalkenburg's agents
|
Flagged issue
Source: automated DevFlow PR review |
There was a problem hiding this comment.
Pull request overview
Adds a Python convenience API on FoundryAgent/RawFoundryAgent to create a Foundry project conversation and return an AgentSession wired up with the resulting server-side conversation ID, reducing the need for application code to directly use the underlying OpenAI client.
Changes:
- Added
create_conversation_session(session_id: str | None = None)to create a project conversation via the Foundry project OpenAI client and return anAgentSessionwithservice_session_idset. - Added unit tests covering success, caller-provided local
session_id, missing conversations support, and missing/invalid conversation ID. - Documented the helper usage and how it relates to hosted-agent
isolation_keysessions in the Foundry package README.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| python/packages/foundry/agent_framework_foundry/_agent.py | Implements create_conversation_session() on the Foundry agent base. |
| python/packages/foundry/tests/foundry/test_foundry_agent.py | Adds unit tests for the new conversation-session helper and error paths. |
| python/packages/foundry/README.md | Documents the new helper and clarifies session ID semantics. |
Comments suppressed due to low confidence (1)
python/packages/foundry/agent_framework_foundry/_agent.py:783
- create_conversation_session() calls project_client.get_openai_client() without carrying over any agent-configured default_headers. If callers rely on default_headers (e.g., isolation-related headers) for all OpenAI traffic, conversation creation will behave differently from agent.run() and can fail in environments that require those headers.
messages: AgentRunInputs | None,
session: AgentSession | None,
tools: ToolTypes | Callable[..., Any] | Sequence[ToolTypes | Callable[..., Any]] | None,
options: Mapping[str, Any] | None,
compaction_strategy: CompactionStrategy | None,
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Automated Code Review
Reviewers: 5 | Confidence: 88%
✓ Correctness
The PR adds a simple
create_conversationhelper onRawFoundryAgentthat creates a project-level Foundry conversation via the OpenAI client and wraps the result in anAgentSession. The implementation is correct: the cast toRawFoundryAgentChatClientis safe (enforced byRawFoundryAgent.__init__type check at line 678),get_openai_client()is correctly called synchronously (matching the pattern at line 266), andget_sessionis invoked with the right positional/keyword arguments matching its signature atBaseAgentline 434. Tests adequately cover the success path and caller-supplied session ID. No correctness issues found.
✓ Security Reliability
The PR adds a
create_conversationhelper that delegates to the Foundry project OpenAI client. The implementation is straightforward and the class hierarchy guaranteesself.clientis always aRawFoundryAgentChatClient. One reliability concern: unlike the sibling_create_service_session_idmethod which validates the returned session ID is a non-empty string (lines 751-753),create_conversationpassesconversation.iddirectly toget_sessionwithout validation, which could silently produce anAgentSessionwith a None or emptyservice_session_idif the API behaves unexpectedly.
✓ Test Coverage
The test coverage for the new
create_conversationmethod is adequate. The two tests cover the primary happy-path behaviors: creating a conversation session with auto-generated session ID and with a caller-supplied session ID. Both tests properly verify mock interactions and assert the correct values on the returned AgentSession. The implementation is a simple 3-line method, and the tests cover both parameter variants. No significant test coverage gaps identified.
✓ Failure Modes
The PR adds a
create_conversationhelper that creates a Foundry project conversation and wraps it in an AgentSession. The implementation is straightforward and correct. Thecaston line 771 is safe because the_FoundryAgentBase.__init__(line 679) already validates that the client type is a subclass ofRawFoundryAgentChatClient. Theget_openai_client()call pattern matches existing usage (line 266). No silent failures, lost errors, or partial-success paths are introduced — any API failure inconversations.create()will propagate as an exception to the caller.
✗ Design Approach
I found two design-level issues in the new helper. It recreates an unconfigured OpenAI client for conversation creation instead of reusing the agent's already-configured client, and it does not validate that the service actually returned a usable conversation ID before building an AgentSession. Both can silently produce behavior that diverges from the rest of FoundryAgent.
Flagged Issues
- python/packages/foundry/agent_framework_foundry/_agent.py:772 bypasses the agent's configured OpenAI client. The constructor applies default_headers, agent_name, and timeout at _agent.py:261-268, and tests assert those settings matter (test_foundry_agent.py:721-735, 779-795). create_conversation() issues its request through a fresh bare client instead, silently dropping those settings.
- python/packages/foundry/agent_framework_foundry/_agent.py:773 never validates that conversation creation returned a non-empty id. The sibling _create_service_session_id() explicitly rejects empty ids (_agent.py:750-755), but this path passes the raw value into get_session(), which forwards it unchanged into AgentSession. Callers can receive a session not actually bound to the created conversation.
Automated review by eavanvalkenburg's agents
|
Flagged issue python/packages/foundry/agent_framework_foundry/_agent.py:772 bypasses the agent's configured OpenAI client. The constructor applies default_headers, agent_name, and timeout at _agent.py:261-268, and tests assert those settings matter (test_foundry_agent.py:721-735, 779-795). create_conversation() issues its request through a fresh bare client instead, silently dropping those settings. Source: automated DevFlow PR review |
|
Flagged issue python/packages/foundry/agent_framework_foundry/_agent.py:773 never validates that conversation creation returned a non-empty id. The sibling _create_service_session_id() explicitly rejects empty ids (_agent.py:750-755), but this path passes the raw value into get_session(), which forwards it unchanged into AgentSession. Callers can receive a session not actually bound to the created conversation. Source: automated DevFlow PR review |
…ndry-agent-conversation-session
|
|
||
| return agent_session_id | ||
|
|
||
| async def create_conversation(self, *, session_id: str | None = None) -> AgentSession: |
There was a problem hiding this comment.
Shall we align the method name with the .NET one for consistency? — create_conversation_session
?
Motivation & Context
Foundry users can create project conversations through the underlying OpenAI client, but doing so requires application code to reach through the Foundry project client just to create a conversation ID before using
FoundryAgent. This adds provider-specific boilerplate for a common server-side conversation/session setup path.This change adds a Python
FoundryAgenthelper that mirrors the existing .NET FoundryAgent conversation-session convenience API for the Foundry-specific scenario. Broader provider-agnostic conversation creation APIs are intentionally left for a separate cross-language design discussion tracked by #6622.Description & Review Guide
FoundryAgent.create_conversation(...)via the shared Foundry agent base implementation.AgentSessionwithservice_session_idset to the created conversation ID.isolation_keysession behavior remains separate and unchanged.AgentSessionwithservice_session_idis the right fit for project conversations.Related Issue
Fixes #2931
Contribution 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.