Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions python/packages/azure-ai/agent_framework_azure_ai/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,14 @@ def _prepare_input(self, messages: MutableSequence[ChatMessage]) -> tuple[list[C
return result, instructions

async def prepare_options(
self, messages: MutableSequence[ChatMessage], chat_options: ChatOptions
self,
messages: MutableSequence[ChatMessage],
chat_options: ChatOptions,
**kwargs: Any,
) -> dict[str, Any]:
"""Take ChatOptions and create the specific options for Azure AI."""
chat_options.store = bool(chat_options.store or chat_options.store is None)
prepared_messages, instructions = self._prepare_input(messages)
run_options = await super().prepare_options(prepared_messages, chat_options)
run_options = await super().prepare_options(prepared_messages, chat_options, **kwargs)
agent_reference = await self._get_agent_reference_or_create(run_options, instructions)

run_options["extra_body"] = {"agent": agent_reference}
Expand Down Expand Up @@ -378,12 +380,12 @@ def get_conversation_id(
self, response: OpenAIResponse | ParsedResponse[BaseModel], store: bool | None
) -> str | None:
"""Get the conversation ID from the response if store is True."""
if store:
# If conversation ID exists, it means that we operate with conversation
# so we use conversation ID as input and output.
if response.conversation and response.conversation.id:
return response.conversation.id
# If conversation ID doesn't exist, we operate with responses
# so we use response ID as input and output.
return response.id
return None
if store is False:
return None
# If conversation ID exists, it means that we operate with conversation
# so we use conversation ID as input and output.
if response.conversation and response.conversation.id:
return response.conversation.id
# If conversation ID doesn't exist, we operate with responses
# so we use response ID as input and output.
return response.id
8 changes: 0 additions & 8 deletions python/packages/core/agent_framework/_clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,10 +568,6 @@ async def get_response(
additional_properties=additional_properties,
)

# Validate that store is True when conversation_id is set
if chat_options.conversation_id is not None and chat_options.store is not True:
chat_options.store = True

if chat_options.instructions:
system_msg = ChatMessage(role="system", text=chat_options.instructions)
prepped_messages = [system_msg, *prepare_messages(messages)]
Expand Down Expand Up @@ -666,10 +662,6 @@ async def get_streaming_response(
additional_properties=additional_properties,
)

# Validate that store is True when conversation_id is set
if chat_options.conversation_id is not None and chat_options.store is not True:
chat_options.store = True

if chat_options.instructions:
system_msg = ChatMessage(role="system", text=chat_options.instructions)
prepped_messages = [system_msg, *prepare_messages(messages)]
Expand Down
25 changes: 17 additions & 8 deletions python/packages/core/agent_framework/openai/_responses_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def _inner_get_response(
**kwargs: Any,
) -> ChatResponse:
client = await self.ensure_client()
run_options = await self.prepare_options(messages, chat_options)
run_options = await self.prepare_options(messages, chat_options, **kwargs)
response_format = run_options.pop("response_format", None)
text_config = run_options.pop("text", None)
text_format, text_config = self._prepare_text_config(response_format=response_format, text_config=text_config)
Expand Down Expand Up @@ -135,7 +135,7 @@ async def _inner_get_streaming_response(
**kwargs: Any,
) -> AsyncIterable[ChatResponseUpdate]:
client = await self.ensure_client()
run_options = await self.prepare_options(messages, chat_options)
run_options = await self.prepare_options(messages, chat_options, **kwargs)
function_call_ids: dict[int, tuple[str, str]] = {} # output_index: (call_id, name)
response_format = run_options.pop("response_format", None)
text_config = run_options.pop("text", None)
Expand Down Expand Up @@ -248,7 +248,7 @@ def get_conversation_id(
self, response: OpenAIResponse | ParsedResponse[BaseModel], store: bool | None
) -> str | None:
"""Get the conversation ID from the response if store is True."""
return response.id if store else None
return None if store is False else response.id

# region Prep methods

Expand Down Expand Up @@ -386,9 +386,17 @@ def get_mcp_tool(self, tool: HostedMCPTool) -> Any:
return mcp

async def prepare_options(
self, messages: MutableSequence[ChatMessage], chat_options: ChatOptions
self,
messages: MutableSequence[ChatMessage],
chat_options: ChatOptions,
**kwargs: Any,
) -> dict[str, Any]:
"""Take ChatOptions and create the specific options for Responses API."""
conversation_id = kwargs.pop("conversation_id", None)

if conversation_id:
chat_options.conversation_id = conversation_id

run_options: dict[str, Any] = chat_options.to_dict(
exclude={
"type",
Expand Down Expand Up @@ -437,8 +445,6 @@ async def prepare_options(
for key, value in additional_properties.items():
if value is not None:
run_options[key] = value
if "store" not in run_options:
run_options["store"] = False
if (tool_choice := run_options.get("tool_choice")) and len(tool_choice.keys()) == 1:
run_options["tool_choice"] = tool_choice["mode"]
return run_options
Expand Down Expand Up @@ -815,8 +821,11 @@ def _create_response_content(
"additional_properties": metadata,
"raw_representation": response,
}
if chat_options.store:
args["conversation_id"] = self.get_conversation_id(response, chat_options.store)

conversation_id = self.get_conversation_id(response, chat_options.store)

if conversation_id:
args["conversation_id"] = conversation_id
if response.usage and (usage_details := self._usage_details_from_openai(response.usage)):
args["usage_details"] = usage_details
if structured_response:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1423,12 +1423,12 @@ async def test_prepare_options_store_parameter_handling() -> None:

chat_options = ChatOptions(store=None, conversation_id=None)
options = await client.prepare_options(messages, chat_options)
assert options["store"] is False
assert "store" not in options
assert "previous_response_id" not in options

chat_options = ChatOptions()
options = await client.prepare_options(messages, chat_options)
assert options["store"] is False
assert "store" not in options
assert "previous_response_id" not in options


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,19 @@ async def example_with_thread_persistence_in_memory() -> None:
# First conversation
query1 = "What's the weather like in Tokyo?"
print(f"User: {query1}")
result1 = await agent.run(query1, thread=thread)
result1 = await agent.run(query1, thread=thread, store=False)
print(f"Agent: {result1.text}")

# Second conversation using the same thread - maintains context
query2 = "How about London?"
print(f"\nUser: {query2}")
result2 = await agent.run(query2, thread=thread)
result2 = await agent.run(query2, thread=thread, store=False)
print(f"Agent: {result2.text}")

# Third conversation - agent should remember both previous cities
query3 = "Which of the cities I asked about has better weather?"
print(f"\nUser: {query3}")
result3 = await agent.run(query3, thread=thread)
result3 = await agent.run(query3, thread=thread, store=False)
print(f"Agent: {result3.text}")
print("Note: The agent remembers context from previous messages in the same thread.\n")

Expand All @@ -105,8 +105,7 @@ async def example_with_existing_thread_id() -> None:

query1 = "What's the weather in Paris?"
print(f"User: {query1}")
# Enable OpenAI conversation state by setting `store` parameter to True
result1 = await agent.run(query1, thread=thread, store=True)
result1 = await agent.run(query1, thread=thread)
print(f"Agent: {result1.text}")

# The thread ID is set after the first response
Expand All @@ -127,7 +126,7 @@ async def example_with_existing_thread_id() -> None:

query2 = "What was the last city I asked about?"
print(f"User: {query2}")
result2 = await agent.run(query2, thread=thread, store=True)
result2 = await agent.run(query2, thread=thread)
print(f"Agent: {result2.text}")
print("Note: The agent continues the conversation from the previous thread by using thread ID.\n")

Expand Down
Loading