Skip to content

Commit d774b64

Browse files
Python: added inline yaml sample (#2582)
* added inline yaml sample * fixed some typos and added intro comment * added description params and pass through to client * add azure assistants * fix tests * observabiltiy mypy fix * for some reason mypy doesn't accept a subclass --------- Co-authored-by: Evan Mattson <35585003+moonbox3@users.noreply.github.com>
1 parent 42ffe59 commit d774b64

File tree

12 files changed

+136
-40
lines changed

12 files changed

+136
-40
lines changed

python/packages/azure-ai/agent_framework_azure_ai/_chat_client.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def __init__(
118118
agents_client: AgentsClient | None = None,
119119
agent_id: str | None = None,
120120
agent_name: str | None = None,
121+
agent_description: str | None = None,
121122
thread_id: str | None = None,
122123
project_endpoint: str | None = None,
123124
model_deployment_name: str | None = None,
@@ -135,6 +136,7 @@ def __init__(
135136
a new agent will be created (and deleted after the request). If neither agents_client
136137
nor agent_id is provided, both will be created and managed automatically.
137138
agent_name: The name to use when creating new agents.
139+
agent_description: The description to use when creating new agents.
138140
thread_id: Default thread ID to use for conversations. Can be overridden by
139141
conversation_id property when making a request.
140142
project_endpoint: The Azure AI Project endpoint URL.
@@ -215,6 +217,7 @@ def __init__(
215217
self.credential = async_credential
216218
self.agent_id = agent_id
217219
self.agent_name = agent_name
220+
self.agent_description = agent_description
218221
self.model_id = azure_ai_settings.model_deployment_name
219222
self.thread_id = thread_id
220223
self.should_cleanup_agent = should_cleanup_agent # Track whether we should delete the agent
@@ -311,6 +314,7 @@ async def _get_agent_id_or_create(self, run_options: dict[str, Any] | None = Non
311314
args: dict[str, Any] = {
312315
"model": run_options["model"],
313316
"name": agent_name,
317+
"description": self.agent_description,
314318
}
315319
if "tools" in run_options:
316320
args["tools"] = run_options["tools"]
@@ -1038,16 +1042,19 @@ def _convert_required_action_to_tool_output(
10381042

10391043
return run_id, tool_outputs, tool_approvals
10401044

1041-
def _update_agent_name(self, agent_name: str | None) -> None:
1045+
def _update_agent_name_and_description(self, agent_name: str | None, description: str | None) -> None:
10421046
"""Update the agent name in the chat client.
10431047
10441048
Args:
10451049
agent_name: The new name for the agent.
1050+
description: The new description for the agent.
10461051
"""
10471052
# This is a no-op in the base class, but can be overridden by subclasses
10481053
# to update the agent name in the client.
10491054
if agent_name and not self.agent_name:
10501055
self.agent_name = agent_name
1056+
if description and not self.agent_description:
1057+
self.agent_description = description
10511058

10521059
def service_url(self) -> str:
10531060
"""Get the service URL for the chat client.

python/packages/azure-ai/agent_framework_azure_ai/_client.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __init__(
6262
project_client: AIProjectClient | None = None,
6363
agent_name: str | None = None,
6464
agent_version: str | None = None,
65+
agent_description: str | None = None,
6566
conversation_id: str | None = None,
6667
project_endpoint: str | None = None,
6768
model_deployment_name: str | None = None,
@@ -77,6 +78,7 @@ def __init__(
7778
project_client: An existing AIProjectClient to use. If not provided, one will be created.
7879
agent_name: The name to use when creating new agents or using existing agents.
7980
agent_version: The version of the agent to use.
81+
agent_description: The description to use when creating new agents.
8082
conversation_id: Default conversation ID to use for conversations. Can be overridden by
8183
conversation_id property when making a request.
8284
project_endpoint: The Azure AI Project endpoint URL.
@@ -150,6 +152,7 @@ def __init__(
150152
# Initialize instance variables
151153
self.agent_name = agent_name
152154
self.agent_version = agent_version
155+
self.agent_description = agent_description
153156
self.use_latest_version = use_latest_version
154157
self.project_client = project_client
155158
self.credential = async_credential
@@ -280,7 +283,9 @@ async def _get_agent_reference_or_create(
280283
args["instructions"] = "".join(combined_instructions)
281284

282285
created_agent = await self.project_client.agents.create_version(
283-
agent_name=self.agent_name, definition=PromptAgentDefinition(**args)
286+
agent_name=self.agent_name,
287+
definition=PromptAgentDefinition(**args),
288+
description=self.agent_description,
284289
)
285290

286291
self.agent_version = created_agent.version
@@ -352,16 +357,19 @@ async def initialize_client(self) -> None:
352357
"""Initialize OpenAI client."""
353358
self.client = self.project_client.get_openai_client() # type: ignore
354359

355-
def _update_agent_name(self, agent_name: str | None) -> None:
360+
def _update_agent_name_and_description(self, agent_name: str | None, description: str | None = None) -> None:
356361
"""Update the agent name in the chat client.
357362
358363
Args:
359364
agent_name: The new name for the agent.
365+
description: The new description for the agent.
360366
"""
361367
# This is a no-op in the base class, but can be overridden by subclasses
362368
# to update the agent name in the client.
363369
if agent_name and not self.agent_name:
364370
self.agent_name = agent_name
371+
if description and not self.agent_description:
372+
self.agent_description = description
365373

366374
def get_mcp_tool(self, tool: HostedMCPTool) -> Any:
367375
"""Get MCP tool from HostedMCPTool."""

python/packages/azure-ai/tests/test_azure_ai_agent_client.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ def create_test_azure_ai_chat_client(
8686
client.credential = None
8787
client.agent_id = agent_id
8888
client.agent_name = agent_name
89+
client.agent_description = None
8990
client.model_id = azure_ai_settings.model_deployment_name
9091
client.thread_id = thread_id
9192
client.should_cleanup_agent = should_cleanup_agent
@@ -441,34 +442,43 @@ async def test_azure_ai_chat_client_close_client_when_should_close_false(mock_ag
441442
mock_agents_client.close.assert_not_called()
442443

443444

444-
def test_azure_ai_chat_client_update_agent_name_when_current_is_none(mock_agents_client: MagicMock) -> None:
445-
"""Test _update_agent_name updates name when current agent_name is None."""
445+
def test_azure_ai_chat_client_update_agent_name_and_description_when_current_is_none(
446+
mock_agents_client: MagicMock,
447+
) -> None:
448+
"""Test _update_agent_name_and_description updates name when current agent_name is None."""
446449
chat_client = create_test_azure_ai_chat_client(mock_agents_client)
447450
chat_client.agent_name = None # type: ignore
448451

449-
chat_client._update_agent_name("NewAgentName") # type: ignore
452+
chat_client._update_agent_name_and_description("NewAgentName", "description") # type: ignore
450453

451454
assert chat_client.agent_name == "NewAgentName"
455+
assert chat_client.agent_description == "description"
452456

453457

454-
def test_azure_ai_chat_client_update_agent_name_when_current_exists(mock_agents_client: MagicMock) -> None:
455-
"""Test _update_agent_name does not update when current agent_name exists."""
458+
def test_azure_ai_chat_client_update_agent_name_and_description_when_current_exists(
459+
mock_agents_client: MagicMock,
460+
) -> None:
461+
"""Test _update_agent_name_and_description does not update when current agent_name exists."""
456462
chat_client = create_test_azure_ai_chat_client(mock_agents_client)
457463
chat_client.agent_name = "ExistingName" # type: ignore
464+
chat_client.agent_description = "ExistingDescription" # type: ignore
458465

459-
chat_client._update_agent_name("NewAgentName") # type: ignore
466+
chat_client._update_agent_name_and_description("NewAgentName", "description") # type: ignore
460467

461468
assert chat_client.agent_name == "ExistingName"
469+
assert chat_client.agent_description == "ExistingDescription"
462470

463471

464-
def test_azure_ai_chat_client_update_agent_name_with_none_input(mock_agents_client: MagicMock) -> None:
465-
"""Test _update_agent_name with None input."""
472+
def test_azure_ai_chat_client_update_agent_name_and_description_with_none_input(mock_agents_client: MagicMock) -> None:
473+
"""Test _update_agent_name_and_description with None input."""
466474
chat_client = create_test_azure_ai_chat_client(mock_agents_client)
467475
chat_client.agent_name = None # type: ignore
476+
chat_client.agent_description = None # type: ignore
468477

469-
chat_client._update_agent_name(None) # type: ignore
478+
chat_client._update_agent_name_and_description(None, None) # type: ignore
470479

471480
assert chat_client.agent_name is None
481+
assert chat_client.agent_description is None
472482

473483

474484
async def test_azure_ai_chat_client_create_run_options_with_messages(mock_agents_client: MagicMock) -> None:

python/packages/azure-ai/tests/test_azure_ai_client.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def create_test_azure_ai_client(
8484
client.credential = None
8585
client.agent_name = agent_name
8686
client.agent_version = agent_version
87+
client.agent_description = None
8788
client.use_latest_version = use_latest_version
8889
client.model_id = azure_ai_settings.model_deployment_name
8990
client.conversation_id = conversation_id
@@ -397,24 +398,24 @@ async def test_azure_ai_client_initialize_client(mock_project_client: MagicMock)
397398
mock_project_client.get_openai_client.assert_called_once()
398399

399400

400-
def test_azure_ai_client_update_agent_name(mock_project_client: MagicMock) -> None:
401-
"""Test _update_agent_name method."""
401+
def test_azure_ai_client_update_agent_name_and_description(mock_project_client: MagicMock) -> None:
402+
"""Test _update_agent_name_and_description method."""
402403
client = create_test_azure_ai_client(mock_project_client)
403404

404405
# Test updating agent name when current is None
405-
with patch.object(client, "_update_agent_name") as mock_update:
406+
with patch.object(client, "_update_agent_name_and_description") as mock_update:
406407
mock_update.return_value = None
407-
client._update_agent_name("new-agent") # type: ignore
408+
client._update_agent_name_and_description("new-agent") # type: ignore
408409
mock_update.assert_called_once_with("new-agent")
409410

410411
# Test behavior when agent name is updated
411412
assert client.agent_name is None # Should remain None since we didn't actually update
412413
client.agent_name = "test-agent" # Manually set for the test
413414

414415
# Test with None input
415-
with patch.object(client, "_update_agent_name") as mock_update:
416+
with patch.object(client, "_update_agent_name_and_description") as mock_update:
416417
mock_update.return_value = None
417-
client._update_agent_name(None) # type: ignore
418+
client._update_agent_name_and_description(None) # type: ignore
418419
mock_update.assert_called_once_with(None)
419420

420421

python/packages/core/agent_framework/_agents.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ def __init__(
719719
additional_properties=additional_chat_options or {}, # type: ignore
720720
)
721721
self._async_exit_stack = AsyncExitStack()
722-
self._update_agent_name()
722+
self._update_agent_name_and_description()
723723

724724
async def __aenter__(self) -> "Self":
725725
"""Enter the async context manager.
@@ -755,15 +755,17 @@ async def __aexit__(
755755
"""
756756
await self._async_exit_stack.aclose()
757757

758-
def _update_agent_name(self) -> None:
758+
def _update_agent_name_and_description(self) -> None:
759759
"""Update the agent name in the chat client.
760760
761761
Checks if the chat client supports agent name updates. The implementation
762762
should check if there is already an agent name defined, and if not
763763
set it to this value.
764764
"""
765-
if hasattr(self.chat_client, "_update_agent_name") and callable(self.chat_client._update_agent_name): # type: ignore[reportAttributeAccessIssue, attr-defined]
766-
self.chat_client._update_agent_name(self.name) # type: ignore[reportAttributeAccessIssue, attr-defined]
765+
if hasattr(self.chat_client, "_update_agent_name_and_description") and callable(
766+
self.chat_client._update_agent_name_and_description
767+
): # type: ignore[reportAttributeAccessIssue, attr-defined]
768+
self.chat_client._update_agent_name_and_description(self.name, self.description) # type: ignore[reportAttributeAccessIssue, attr-defined]
767769

768770
async def run(
769771
self,

python/packages/core/agent_framework/azure/_assistants_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(
2727
deployment_name: str | None = None,
2828
assistant_id: str | None = None,
2929
assistant_name: str | None = None,
30+
assistant_description: str | None = None,
3031
thread_id: str | None = None,
3132
api_key: str | None = None,
3233
endpoint: str | None = None,
@@ -49,6 +50,7 @@ def __init__(
4950
assistant_id: The ID of an Azure OpenAI assistant to use.
5051
If not provided, a new assistant will be created (and deleted after the request).
5152
assistant_name: The name to use when creating new assistants.
53+
assistant_description: The description to use when creating new assistants.
5254
thread_id: Default thread ID to use for conversations. Can be overridden by
5355
conversation_id property when making a request.
5456
If not provided, a new thread will be created (and deleted after the request).
@@ -155,6 +157,7 @@ def __init__(
155157
model_id=azure_openai_settings.chat_deployment_name,
156158
assistant_id=assistant_id,
157159
assistant_name=assistant_name,
160+
assistant_description=assistant_description,
158161
thread_id=thread_id,
159162
async_client=async_client, # type: ignore[reportArgumentType]
160163
default_headers=default_headers,

python/packages/core/agent_framework/observability.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,9 @@ def _get_otlp_exporters(endpoints: list[str]) -> list["LogRecordExporter | SpanE
268268
exporters: list["LogRecordExporter | SpanExporter | MetricExporter"] = []
269269

270270
for endpoint in endpoints:
271-
exporters.append(OTLPLogExporter(endpoint=endpoint))
272-
exporters.append(OTLPSpanExporter(endpoint=endpoint))
273-
exporters.append(OTLPMetricExporter(endpoint=endpoint))
271+
exporters.append(OTLPLogExporter(endpoint=endpoint)) # type: ignore[arg-type]
272+
exporters.append(OTLPSpanExporter(endpoint=endpoint)) # type: ignore[arg-type]
273+
exporters.append(OTLPMetricExporter(endpoint=endpoint)) # type: ignore[arg-type]
274274
return exporters
275275

276276

python/packages/core/agent_framework/openai/_assistants_client.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(
6464
model_id: str | None = None,
6565
assistant_id: str | None = None,
6666
assistant_name: str | None = None,
67+
assistant_description: str | None = None,
6768
thread_id: str | None = None,
6869
api_key: str | Callable[[], str | Awaitable[str]] | None = None,
6970
org_id: str | None = None,
@@ -82,6 +83,7 @@ def __init__(
8283
assistant_id: The ID of an OpenAI assistant to use.
8384
If not provided, a new assistant will be created (and deleted after the request).
8485
assistant_name: The name to use when creating new assistants.
86+
assistant_description: The description to use when creating new assistants.
8587
thread_id: Default thread ID to use for conversations. Can be overridden by
8688
conversation_id property when making a request.
8789
If not provided, a new thread will be created (and deleted after the request).
@@ -147,6 +149,7 @@ def __init__(
147149
)
148150
self.assistant_id: str | None = assistant_id
149151
self.assistant_name: str | None = assistant_name
152+
self.assistant_description: str | None = assistant_description
150153
self.thread_id: str | None = thread_id
151154
self._should_delete_assistant: bool = False
152155

@@ -220,7 +223,11 @@ async def _get_assistant_id_or_create(self) -> str:
220223
raise ServiceInitializationError("Parameter 'model_id' is required for assistant creation.")
221224

222225
client = await self.ensure_client()
223-
created_assistant = await client.beta.assistants.create(name=self.assistant_name, model=self.model_id)
226+
created_assistant = await client.beta.assistants.create(
227+
model=self.model_id,
228+
description=self.assistant_description,
229+
name=self.assistant_name,
230+
)
224231
self.assistant_id = created_assistant.id
225232
self._should_delete_assistant = True
226233

@@ -516,13 +523,16 @@ def _convert_function_results_to_tool_output(
516523

517524
return run_id, tool_outputs
518525

519-
def _update_agent_name(self, agent_name: str | None) -> None:
526+
def _update_agent_name_and_description(self, agent_name: str | None, description: str | None = None) -> None:
520527
"""Update the agent name in the chat client.
521528
522529
Args:
523530
agent_name: The new name for the agent.
531+
description: The new description for the agent.
524532
"""
525533
# This is a no-op in the base class, but can be overridden by subclasses
526534
# to update the agent name in the client.
527535
if agent_name and not self.assistant_name:
528-
object.__setattr__(self, "assistant_name", agent_name)
536+
self.assistant_name = agent_name
537+
if description and not self.assistant_description:
538+
self.assistant_description = description

python/packages/core/tests/openai/test_openai_assistants_client.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -872,36 +872,36 @@ def test_openai_assistants_client_convert_function_results_to_tool_output_mismat
872872
assert tool_outputs[0].get("tool_call_id") == "call-456"
873873

874874

875-
def test_openai_assistants_client_update_agent_name(mock_async_openai: MagicMock) -> None:
876-
"""Test _update_agent_name method updates assistant_name when not already set."""
875+
def test_openai_assistants_client_update_agent_name_and_description(mock_async_openai: MagicMock) -> None:
876+
"""Test _update_agent_name_and_description method updates assistant_name when not already set."""
877877
# Test updating agent name when assistant_name is None
878878
chat_client = create_test_openai_assistants_client(mock_async_openai, assistant_name=None)
879879

880880
# Call the private method to update agent name
881-
chat_client._update_agent_name("New Assistant Name") # type: ignore
881+
chat_client._update_agent_name_and_description("New Assistant Name") # type: ignore
882882

883883
assert chat_client.assistant_name == "New Assistant Name"
884884

885885

886-
def test_openai_assistants_client_update_agent_name_existing(mock_async_openai: MagicMock) -> None:
887-
"""Test _update_agent_name method doesn't override existing assistant_name."""
886+
def test_openai_assistants_client_update_agent_name_and_description_existing(mock_async_openai: MagicMock) -> None:
887+
"""Test _update_agent_name_and_description method doesn't override existing assistant_name."""
888888
# Test that existing assistant_name is not overridden
889889
chat_client = create_test_openai_assistants_client(mock_async_openai, assistant_name="Existing Assistant")
890890

891891
# Call the private method to update agent name
892-
chat_client._update_agent_name("New Assistant Name") # type: ignore
892+
chat_client._update_agent_name_and_description("New Assistant Name") # type: ignore
893893

894894
# Should keep the existing name
895895
assert chat_client.assistant_name == "Existing Assistant"
896896

897897

898-
def test_openai_assistants_client_update_agent_name_none(mock_async_openai: MagicMock) -> None:
899-
"""Test _update_agent_name method with None agent_name parameter."""
898+
def test_openai_assistants_client_update_agent_name_and_description_none(mock_async_openai: MagicMock) -> None:
899+
"""Test _update_agent_name_and_description method with None agent_name parameter."""
900900
# Test that None agent_name doesn't change anything
901901
chat_client = create_test_openai_assistants_client(mock_async_openai, assistant_name=None)
902902

903903
# Call the private method with None
904-
chat_client._update_agent_name(None) # type: ignore
904+
chat_client._update_agent_name_and_description(None) # type: ignore
905905

906906
# Should remain None
907907
assert chat_client.assistant_name is None

0 commit comments

Comments
 (0)