diff --git a/python/packages/foundry/README.md b/python/packages/foundry/README.md index b253d2d000..bcaa83f616 100644 --- a/python/packages/foundry/README.md +++ b/python/packages/foundry/README.md @@ -106,6 +106,30 @@ Generally available factories: `get_code_interpreter_tool`, | `get_browser_automation_tool(connection_id)` | `BrowserAutomationPreviewTool` | | `get_bing_custom_search_tool(connection_id, instance_name, ...)` | `BingCustomSearchPreviewTool` | | `get_a2a_tool(base_url=..., project_connection_id=..., ...)` | `A2APreviewTool` | + +## Creating Foundry conversation sessions + +`FoundryAgent.create_conversation()` creates a server-side Foundry +project conversation and returns an `AgentSession` that can be passed to +`agent.run(...)` without reaching into the raw OpenAI client. + +```python +from agent_framework.foundry import FoundryAgent + +agent = FoundryAgent( + project_endpoint=project_endpoint, + agent_name="travel-agent", + credential=credential, +) + +session = await agent.create_conversation() +response = await agent.run("Help me plan a trip to Seattle.", session=session) +``` + +This is separate from hosted-agent `isolation_key` sessions: the created +conversation ID is stored on `AgentSession.service_session_id`, while the local +`session_id` remains available for application/session storage. + ## Publishing an agent as a Foundry prompt agent > **Experimental — `ExperimentalFeature.TO_PROMPT_AGENT`.** `to_prompt_agent` diff --git a/python/packages/foundry/agent_framework_foundry/_agent.py b/python/packages/foundry/agent_framework_foundry/_agent.py index 370e034bca..3d3735606e 100644 --- a/python/packages/foundry/agent_framework_foundry/_agent.py +++ b/python/packages/foundry/agent_framework_foundry/_agent.py @@ -754,6 +754,24 @@ async def _create_service_session_id( return agent_session_id + async def create_conversation(self, *, session_id: str | None = None) -> AgentSession: + """Create a project-level Foundry conversation session. + + This creates a server-side conversation through the Foundry project's OpenAI + client and returns an ``AgentSession`` configured to continue that + conversation. + + Keyword Args: + session_id: Optional local session ID (generated if not provided). + + Returns: + A new ``AgentSession`` whose ``service_session_id`` is the created + Foundry conversation ID. + """ + client = cast(RawFoundryAgentChatClient, self.client) + conversation = await client.project_client.get_openai_client().conversations.create() + return self.get_session(service_session_id=conversation.id, session_id=session_id) + @override async def _prepare_run_context( self, diff --git a/python/packages/foundry/tests/foundry/test_foundry_agent.py b/python/packages/foundry/tests/foundry/test_foundry_agent.py index f14c757d7c..aa15c024be 100644 --- a/python/packages/foundry/tests/foundry/test_foundry_agent.py +++ b/python/packages/foundry/tests/foundry/test_foundry_agent.py @@ -913,6 +913,38 @@ async def test_raw_foundry_agent_prepare_run_context_requires_preview_for_hosted ) +async def test_foundry_agent_create_conversation_returns_agent_session() -> None: + """Test that FoundryAgent creates a project conversation and returns a session.""" + + openai_client = MagicMock() + openai_client.conversations.create = AsyncMock(return_value=SimpleNamespace(id="conv_123")) + mock_project = MagicMock() + mock_project.get_openai_client.return_value = openai_client + agent = FoundryAgent(project_client=mock_project, agent_name="test-agent") + + session = await agent.create_conversation() + + assert isinstance(session, AgentSession) + assert session.service_session_id == "conv_123" + mock_project.get_openai_client.assert_called() + openai_client.conversations.create.assert_awaited_once_with() + + +async def test_foundry_agent_create_conversation_accepts_local_session_id() -> None: + """Test that project conversation sessions can use a caller-provided local session ID.""" + + openai_client = MagicMock() + openai_client.conversations.create = AsyncMock(return_value=SimpleNamespace(id="conv_123")) + mock_project = MagicMock() + mock_project.get_openai_client.return_value = openai_client + agent = FoundryAgent(project_client=mock_project, agent_name="test-agent") + + session = await agent.create_conversation(session_id="local-session") + + assert session.session_id == "local-session" + assert session.service_session_id == "conv_123" + + def test_foundry_agent_init() -> None: """Test construction of the full-middleware agent."""