Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 87bc3d6

Browse files
authoredMar 11, 2025··
Python: Support AzureAIAgent agent_id instead of assistant_id (microsoft#10908)
### Motivation and Context The Azure Python SDK made an underlying change to move away from `assistant_id` keyword arguments to now support `agent_id` keyword arguments. Additionally, they now support a `MessageTextUrlCitationAnnotation` and `MessageDeltaTextUrlCitationAnnotation` for annotations. <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> ### Description Update the `AzureAIAgent` to pass in `agent_id` in place of `assistant_id`, and bring in support for the new annotation types. - Updates samples to simpler patterns where needed. - Updates unit tests. - Closes microsoft#10852 Validated that our [AzureAIAgent + Azure AI Search sample](https://github.com/microsoft/semantic-kernel/blob/main/python/samples/concepts/agents/azure_ai_agent/azure_ai_agent_azure_ai_search.py) works properly: --- ```markdown # User: 'Which hotels are available with full-sized kitchens in Nashville, TN?' # Agent: In Nashville, TN, here are some hotel options that feature full-sized kitchens: 1. **Extended Stay Suites** - All suites include full-sized kitchens stocked with cookware, separate living and sleeping areas, and sofa beds. Some larger rooms have fireplaces and patios or balconies【3:0†source】. 2. **New Premium Rooms** - These newly furnished rooms are fully equipped with premium amenities, including a full kitchen, washer & dryer, and access to a fitness center. Units also include fireplaces and small outdoor balconies【3:1†source】. 3. **Conveniently Located Extended Stay** - This option offers a full kitchen along with a washer & dryer, and amenities such as free WiFi and a fitness center, located near downtown Nashville【3:3†source】. 4. **Inn with Functional Kitchens** - This inn provides living room suites and functional kitchens, situated conveniently near a lake and welcomes pets【3:4†source】. These options provide a range of amenities for travelers looking for the convenience of a full-sized kitchen during their stay. # User: 'Fun hotels with free WiFi.' # Agent: Here are some fun hotels that offer free WiFi: 1. **Hotel with Rooftop Plaza** - Offers complimentary continental breakfast in the lobby and free Wi-Fi throughout the hotel. Its penthouse suites provide stunning views【7:0†source】. 2. **Lakeside Hotel** - Features newly redesigned rooms, an airport shuttle, and lakeside amenities including a resort-style pool. The hotel provides stylish new guestrooms with Internet TVs and free WiFi【7:3†source】. 3. **Downtown Hotel** - Located near the vibrant downtown area and the business district. This hotel offers free WiFi, local transportation, and a special treat of milk and cookies for guests【7:4†source】. These hotels combine fun experiences with the convenience of free internet access for guests. ``` <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X] The code builds clean without any errors or warnings - [X] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [X] All unit tests pass, and I have added new tests where possible - [X] I didn't break anyone 😄
1 parent ba9c17c commit 87bc3d6

13 files changed

+111
-61
lines changed
 

‎python/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ autogen = [
5757
]
5858
azure = [
5959
"azure-ai-inference >= 1.0.0b6",
60-
"azure-ai-projects == 1.0.0b5",
60+
"azure-ai-projects >= 1.0.0b7",
6161
"azure-core-tracing-opentelemetry >= 1.0.0b11",
6262
"azure-search-documents >= 11.6.0b4",
6363
"azure-identity ~= 1.13",

‎python/samples/concepts/agents/azure_ai_agent/azure_ai_agent_azure_ai_search.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from azure.identity.aio import DefaultAzureCredential
88

99
from semantic_kernel.agents.azure_ai import AzureAIAgent, AzureAIAgentSettings
10-
from semantic_kernel.contents.chat_message_content import ChatMessageContent
11-
from semantic_kernel.contents.utils.author_role import AuthorRole
1210

1311
logging.basicConfig(level=logging.WARNING)
1412

@@ -84,13 +82,12 @@ async def main() -> None:
8482
# Add the user input as a chat message
8583
await agent.add_chat_message(
8684
thread_id=thread.id,
87-
message=ChatMessageContent(role=AuthorRole.USER, content=user_input),
85+
message=user_input,
8886
)
8987
print(f"# User: '{user_input}'\n")
9088
# Invoke the agent for the specified thread
9189
async for content in agent.invoke(thread_id=thread.id):
92-
if content.role != AuthorRole.TOOL:
93-
print(f"# Agent: {content.content}\n")
90+
print(f"# Agent: {content.content}\n")
9491
finally:
9592
await client.agents.delete_thread(thread.id)
9693
await client.agents.delete_agent(agent.id)

‎python/samples/concepts/agents/azure_ai_agent/azure_ai_agent_file_manipulation.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88

99
from semantic_kernel.agents.azure_ai import AzureAIAgent, AzureAIAgentSettings
1010
from semantic_kernel.contents.annotation_content import AnnotationContent
11-
from semantic_kernel.contents.chat_message_content import ChatMessageContent
1211
from semantic_kernel.contents.utils.author_role import AuthorRole
1312

14-
###################################################################
15-
# The following sample demonstrates how to create a simple, #
16-
# Azure AI agent that uses the code interpreter tool to answer #
17-
# a coding question. #
18-
###################################################################
13+
"""
14+
The following sample demonstrates how to create a simple,
15+
Azure AI agent that uses the code interpreter tool to answer
16+
a coding question.
17+
"""
1918

2019

2120
async def main() -> None:
@@ -66,7 +65,7 @@ async def main() -> None:
6665
# Add the user input as a chat message
6766
await agent.add_chat_message(
6867
thread_id=thread.id,
69-
message=ChatMessageContent(role=AuthorRole.USER, content=user_input),
68+
message=user_input,
7069
)
7170
print(f"# User: '{user_input}'")
7271
# Invoke the agent for the specified thread

‎python/samples/concepts/agents/azure_ai_agent/azure_ai_agent_streaming.py

+8-12
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
from azure.identity.aio import DefaultAzureCredential
77

88
from semantic_kernel.agents.azure_ai import AzureAIAgent, AzureAIAgentSettings
9-
from semantic_kernel.contents.chat_message_content import ChatMessageContent
10-
from semantic_kernel.contents.utils.author_role import AuthorRole
11-
from semantic_kernel.functions.kernel_function_decorator import kernel_function
9+
from semantic_kernel.functions import kernel_function
1210

1311

1412
# Define a sample plugin for the sample
@@ -54,11 +52,9 @@ async def main() -> None:
5452
agent = AzureAIAgent(
5553
client=client,
5654
definition=agent_definition,
55+
plugins=[MenuPlugin()], # add the sample plugin to the agent
5756
)
5857

59-
# Add the sample plugin to the kernel
60-
agent.kernel.add_plugin(MenuPlugin(), plugin_name="menu")
61-
6258
# Create a new thread
6359
thread = await client.agents.create_thread()
6460

@@ -73,16 +69,16 @@ async def main() -> None:
7369
for user_input in user_inputs:
7470
# Add the user input as a chat message
7571
await agent.add_chat_message(
76-
thread_id=thread.id, message=ChatMessageContent(role=AuthorRole.USER, content=user_input)
72+
thread_id=thread.id,
73+
message=user_input,
7774
)
7875
print(f"# User: '{user_input}'")
7976
first_chunk = True
8077
async for content in agent.invoke_stream(thread_id=thread.id):
81-
if content.role != AuthorRole.TOOL:
82-
if first_chunk:
83-
print(f"# {content.role}: ", end="", flush=True)
84-
first_chunk = False
85-
print(content.content, end="", flush=True)
78+
if first_chunk:
79+
print(f"# {content.role}: ", end="", flush=True)
80+
first_chunk = False
81+
print(content.content, end="", flush=True)
8682
print()
8783
finally:
8884
await client.agents.delete_thread(thread.id)

‎python/semantic_kernel/agents/azure_ai/agent_content_generation.py

+26-9
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
MessageDeltaTextContent,
99
MessageDeltaTextFileCitationAnnotation,
1010
MessageDeltaTextFilePathAnnotation,
11+
MessageDeltaTextUrlCitationAnnotation,
1112
MessageImageFileContent,
1213
MessageTextContent,
1314
MessageTextFileCitationAnnotation,
1415
MessageTextFilePathAnnotation,
16+
MessageTextUrlCitationAnnotation,
1517
RunStep,
1618
RunStepDeltaCodeInterpreterDetailItemObject,
1719
RunStepDeltaCodeInterpreterImageOutput,
@@ -44,11 +46,11 @@
4446
RunStepDeltaToolCallObject,
4547
)
4648

47-
###################################################################
48-
# The methods in this file are used with Azure AI Agent #
49-
# related code. They are used to invoke, create chat messages, #
50-
# or generate message content. #
51-
###################################################################
49+
"""
50+
The methods in this file are used with Azure AI Agent
51+
related code. They are used to invoke, create chat messages,
52+
or generate message content.
53+
"""
5254

5355

5456
@experimental
@@ -109,7 +111,7 @@ def generate_message_content(
109111
"step_id": completed_step.id,
110112
"run_id": completed_step.run_id,
111113
"thread_id": completed_step.thread_id,
112-
"assistant_id": completed_step.assistant_id,
114+
"agent_id": completed_step.agent_id,
113115
"usage": completed_step.usage,
114116
}
115117
if completed_step is not None
@@ -173,6 +175,7 @@ def generate_streaming_message_content(
173175
(
174176
MessageDeltaTextFileCitationAnnotation,
175177
MessageDeltaTextFilePathAnnotation,
178+
MessageDeltaTextUrlCitationAnnotation,
176179
),
177180
):
178181
items.append(generate_streaming_annotation_content(annotation))
@@ -399,37 +402,51 @@ def generate_streaming_code_interpreter_content(
399402

400403
@experimental
401404
def generate_annotation_content(
402-
annotation: MessageTextFilePathAnnotation | MessageTextFileCitationAnnotation,
405+
annotation: MessageTextFilePathAnnotation | MessageTextFileCitationAnnotation | MessageTextUrlCitationAnnotation,
403406
) -> AnnotationContent:
404407
"""Generate annotation content."""
405408
file_id = None
409+
url = None
406410
if isinstance(annotation, MessageTextFilePathAnnotation) and annotation.file_path is not None:
407411
file_id = annotation.file_path.file_id
408412
elif isinstance(annotation, MessageTextFileCitationAnnotation) and annotation.file_citation is not None:
409413
file_id = annotation.file_citation.file_id
414+
elif isinstance(annotation, MessageTextUrlCitationAnnotation) and annotation.url_citation is not None:
415+
url = annotation.url_citation.url if annotation.url_citation.url else None
410416

411417
return AnnotationContent(
412418
file_id=file_id,
413419
quote=annotation.text,
414420
start_index=annotation.start_index if annotation.start_index is not None else None,
415421
end_index=annotation.end_index if annotation.end_index is not None else None,
422+
url=url,
416423
)
417424

418425

419426
@experimental
420427
def generate_streaming_annotation_content(
421-
annotation: MessageDeltaTextFilePathAnnotation | MessageDeltaTextFileCitationAnnotation,
428+
annotation: MessageDeltaTextFilePathAnnotation
429+
| MessageDeltaTextFileCitationAnnotation
430+
| MessageDeltaTextUrlCitationAnnotation,
422431
) -> StreamingAnnotationContent:
423432
"""Generate streaming annotation content."""
424433
file_id = None
434+
url = None
435+
quote = None
425436
if isinstance(annotation, MessageDeltaTextFilePathAnnotation) and annotation.file_path:
426437
file_id = annotation.file_path.file_id if annotation.file_path.file_id else None
438+
quote = annotation.text if annotation.text else None
427439
elif isinstance(annotation, MessageDeltaTextFileCitationAnnotation) and annotation.file_citation:
428440
file_id = annotation.file_citation.file_id if annotation.file_citation.file_id else None
441+
quote = annotation.text if annotation.text else None
442+
elif isinstance(annotation, MessageDeltaTextUrlCitationAnnotation) and annotation.url_citation:
443+
url = annotation.url_citation.url if annotation.url_citation.url else None
444+
quote = annotation.url_citation.title if annotation.url_citation.title else None
429445

430446
return StreamingAnnotationContent(
431447
file_id=file_id,
432-
quote=annotation.text,
448+
quote=quote,
433449
start_index=annotation.start_index if annotation.start_index is not None else None,
434450
end_index=annotation.end_index if annotation.end_index is not None else None,
451+
url=url,
435452
)

‎python/semantic_kernel/agents/azure_ai/agent_thread_actions.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ async def invoke(
162162
run_options = {k: v for k, v in run_options.items() if v is not None}
163163

164164
run: ThreadRun = await agent.client.agents.create_run(
165-
assistant_id=agent.id,
165+
agent_id=agent.id,
166166
thread_id=thread_id,
167167
instructions=merged_instructions or agent.instructions,
168168
tools=tools,
@@ -388,7 +388,7 @@ async def invoke_stream(
388388
run_options = {k: v for k, v in run_options.items() if v is not None}
389389

390390
stream: AsyncAgentRunStream = await agent.client.agents.create_stream(
391-
assistant_id=agent.id,
391+
agent_id=agent.id,
392392
thread_id=thread_id,
393393
instructions=merged_instructions or agent.instructions,
394394
tools=tools,
@@ -663,12 +663,12 @@ async def get_messages(
663663
last_id = message.id
664664
assistant_name: str | None = None
665665

666-
if message.assistant_id and message.assistant_id.strip() and message.assistant_id not in agent_names:
667-
assistant = await client.agents.get_agent(message.assistant_id)
666+
if message.agent_id and message.agent_id.strip() and message.agent_id not in agent_names:
667+
assistant = await client.agents.get_agent(message.agent_id)
668668
if assistant.name and assistant.name.strip():
669669
agent_names[assistant.id] = assistant.name
670670

671-
assistant_name = agent_names.get(message.assistant_id) or message.assistant_id
671+
assistant_name = agent_names.get(message.agent_id) or message.agent_id
672672

673673
content = generate_message_content(assistant_name, message)
674674

‎python/semantic_kernel/contents/annotation_content.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ class AnnotationContent(KernelContent):
2525
quote: str | None = None
2626
start_index: int | None = None
2727
end_index: int | None = None
28+
url: str | None = None
2829

2930
def __str__(self) -> str:
3031
"""Return the string representation of the annotation content."""
31-
return f"AnnotationContent(file_id={self.file_id}, quote={self.quote}, start_index={self.start_index}, end_index={self.end_index})" # noqa: E501
32+
return f"AnnotationContent(file_id={self.file_id}, url={self.url}, quote={self.quote}, start_index={self.start_index}, end_index={self.end_index})" # noqa: E501
3233

3334
def to_element(self) -> Element:
3435
"""Convert the annotation content to an Element."""
@@ -41,6 +42,8 @@ def to_element(self) -> Element:
4142
element.set("start_index", str(self.start_index))
4243
if self.end_index is not None:
4344
element.set("end_index", str(self.end_index))
45+
if self.url is not None:
46+
element.set("url", self.url)
4447
return element
4548

4649
@classmethod
@@ -51,11 +54,12 @@ def from_element(cls: type[_T], element: Element) -> _T:
5154
quote=element.get("quote"),
5255
start_index=int(element.get("start_index")) if element.get("start_index") else None, # type: ignore
5356
end_index=int(element.get("end_index")) if element.get("end_index") else None, # type: ignore
57+
url=element.get("url") if element.get("url") else None, # type: ignore
5458
)
5559

5660
def to_dict(self) -> dict[str, Any]:
5761
"""Convert the instance to a dictionary."""
5862
return {
5963
"type": "text",
60-
"text": f"{self.file_id} {self.quote} (Start Index={self.start_index}->End Index={self.end_index})",
64+
"text": f"{self.file_id or self.url} {self.quote} (Start Index={self.start_index}->End Index={self.end_index})", # noqa: E501
6165
}

‎python/semantic_kernel/contents/streaming_annotation_content.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ class StreamingAnnotationContent(KernelContent):
2828
quote: str | None = None
2929
start_index: int | None = None
3030
end_index: int | None = None
31+
url: str | None = None
3132

3233
def __str__(self) -> str:
3334
"""Return the string representation of the annotation content."""
34-
return f"StreamingAnnotationContent(file_id={self.file_id}, quote={self.quote}, start_index={self.start_index}, end_index={self.end_index})" # noqa: E501
35+
return f"StreamingAnnotationContent(file_id={self.file_id}, url={self.url}, quote={self.quote}, start_index={self.start_index}, end_index={self.end_index})" # noqa: E501
3536

3637
def to_element(self) -> Element:
3738
"""Convert the annotation content to an Element."""
@@ -44,6 +45,8 @@ def to_element(self) -> Element:
4445
element.set("start_index", str(self.start_index))
4546
if self.end_index is not None:
4647
element.set("end_index", str(self.end_index))
48+
if self.url is not None:
49+
element.set("url", self.url)
4750
return element
4851

4952
@classmethod
@@ -54,11 +57,12 @@ def from_element(cls: type[_T], element: Element) -> _T:
5457
quote=element.get("quote"),
5558
start_index=int(element.get("start_index")) if element.get("start_index") else None, # type: ignore
5659
end_index=int(element.get("end_index")) if element.get("end_index") else None, # type: ignore
60+
url=element.get("url") if element.get("url") else None, # type: ignore
5761
)
5862

5963
def to_dict(self) -> dict[str, Any]:
6064
"""Convert the instance to a dictionary."""
6165
return {
6266
"type": "text",
63-
"text": f"{self.file_id} {self.quote} (Start Index={self.start_index}->End Index={self.end_index})",
67+
"text": f"{self.file_id or self.url} {self.quote} (Start Index={self.start_index}->End Index={self.end_index})", # noqa: E501
6468
}

‎python/tests/unit/agents/azure_ai_agent/test_agent_content_generation.py

+34-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
MessageDeltaTextFileCitationAnnotationObject,
1313
MessageDeltaTextFilePathAnnotation,
1414
MessageDeltaTextFilePathAnnotationObject,
15+
MessageDeltaTextUrlCitationAnnotation,
16+
MessageDeltaTextUrlCitationDetails,
1517
MessageImageFileContent,
1618
MessageImageFileDetails,
1719
MessageTextContent,
@@ -20,6 +22,8 @@
2022
MessageTextFileCitationDetails,
2123
MessageTextFilePathAnnotation,
2224
MessageTextFilePathDetails,
25+
MessageTextUrlCitationAnnotation,
26+
MessageTextUrlCitationDetails,
2327
RunStep,
2428
RunStepDeltaFunction,
2529
RunStepDeltaFunctionToolCall,
@@ -90,18 +94,25 @@ def test_generate_message_content_text_and_image():
9094
start_index=1,
9195
end_index=10,
9296
),
97+
MessageTextUrlCitationAnnotation(
98+
text="text",
99+
url_citation=MessageTextUrlCitationDetails(title="some title", url="http://example.com"),
100+
start_index=1,
101+
end_index=10,
102+
),
93103
],
94104
)
95105
)
96106

97107
thread_msg.content = [image, text]
98-
step = RunStep(id="step_id", run_id="run_id", thread_id="thread_id", assistant_id="assistant_id")
108+
step = RunStep(id="step_id", run_id="run_id", thread_id="thread_id", agent_id="assistant_id")
99109
out = generate_message_content("assistant", thread_msg, step)
100-
assert len(out.items) == 4
110+
assert len(out.items) == 5
101111
assert isinstance(out.items[0], FileReferenceContent)
102112
assert isinstance(out.items[1], TextContent)
103113
assert isinstance(out.items[2], AnnotationContent)
104114
assert isinstance(out.items[3], AnnotationContent)
115+
assert isinstance(out.items[4], AnnotationContent)
105116

106117
assert out.items[0].file_id == "test_file_id"
107118

@@ -117,6 +128,11 @@ def test_generate_message_content_text_and_image():
117128
assert out.items[3].start_index == 1
118129
assert out.items[3].end_index == 10
119130

131+
assert out.items[4].url == "http://example.com"
132+
assert out.items[4].quote == "text"
133+
assert out.items[4].start_index == 1
134+
assert out.items[4].end_index == 10
135+
120136
assert out.metadata["step_id"] == "step_id"
121137
assert out.role == AuthorRole.USER
122138

@@ -171,6 +187,15 @@ def test_generate_streaming_message_content_text_annotations():
171187
end_index=9,
172188
text="some text",
173189
),
190+
MessageDeltaTextUrlCitationAnnotation(
191+
index=0,
192+
url_citation=MessageDeltaTextUrlCitationDetails(
193+
title="some title",
194+
url="http://example.com",
195+
),
196+
start_index=0,
197+
end_index=9,
198+
),
174199
],
175200
),
176201
)
@@ -183,7 +208,7 @@ def test_generate_streaming_message_content_text_annotations():
183208
out = generate_streaming_message_content("assistant", delta)
184209
assert out is not None
185210
assert out.content == "some text"
186-
assert len(out.items) == 4
211+
assert len(out.items) == 5
187212
assert out.items[0].file_id == "image_file"
188213
assert isinstance(out.items[0], StreamingFileReferenceContent)
189214
assert isinstance(out.items[1], StreamingTextContent)
@@ -200,6 +225,12 @@ def test_generate_streaming_message_content_text_annotations():
200225
assert out.items[3].start_index == 0
201226
assert out.items[3].end_index == 9
202227

228+
assert isinstance(out.items[4], StreamingAnnotationContent)
229+
assert out.items[4].url == "http://example.com"
230+
assert out.items[4].quote == "some title"
231+
assert out.items[4].start_index == 0
232+
assert out.items[4].end_index == 9
233+
203234

204235
def test_generate_streaming_function_content_with_function():
205236
step_details = RunStepDeltaToolCallObject(

‎python/tests/unit/agents/azure_ai_agent/test_agent_thread_actions.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ async def test_agent_thread_actions_invoke(ai_project_client, ai_agent_definitio
9494
created_at=int(datetime.now(timezone.utc).timestamp()),
9595
completed_at=int(datetime.now(timezone.utc).timestamp()),
9696
status="completed",
97-
assistant_id="assistant123",
97+
agent_id="agent123",
9898
step_details=RunStepMessageCreationDetails(
9999
message_creation=RunStepMessageCreationReference(
100100
message_id="msg123",
@@ -113,7 +113,7 @@ async def test_agent_thread_actions_invoke(ai_project_client, ai_agent_definitio
113113
created_at=int(datetime.now(timezone.utc).timestamp()),
114114
completed_at=int(datetime.now(timezone.utc).timestamp()),
115115
status="completed",
116-
assistant_id="assistant123",
116+
agent_id="agent123",
117117
role="assistant",
118118
content=[MessageTextContent(text=MessageTextDetails(value="some message", annotations=[]))],
119119
)
@@ -180,7 +180,7 @@ def mock_get_function_call_contents(run: ThreadRun, function_steps: dict):
180180
created_at=int(datetime.now(timezone.utc).timestamp()),
181181
completed_at=int(datetime.now(timezone.utc).timestamp()),
182182
status="completed",
183-
assistant_id="assistant123",
183+
agent_id="agent123",
184184
step_details=RunStepToolCallDetails(
185185
tool_calls=[
186186
RunStepCodeInterpreterToolCall(
@@ -209,7 +209,7 @@ def mock_get_function_call_contents(run: ThreadRun, function_steps: dict):
209209
created_at=int(datetime.now(timezone.utc).timestamp()),
210210
completed_at=int(datetime.now(timezone.utc).timestamp()),
211211
status="completed",
212-
assistant_id="assistant123",
212+
agent_id="agent123",
213213
step_details=RunStepMessageCreationDetails(
214214
message_creation=RunStepMessageCreationReference(message_id="msg123")
215215
),
@@ -225,7 +225,7 @@ def mock_get_function_call_contents(run: ThreadRun, function_steps: dict):
225225
created_at=int(datetime.now(timezone.utc).timestamp()),
226226
completed_at=int(datetime.now(timezone.utc).timestamp()),
227227
status="completed",
228-
assistant_id="assistant123",
228+
agent_id="agent123",
229229
role="assistant",
230230
content=[MessageTextContent(text=MessageTextDetails(value="some message", annotations=[]))],
231231
)

‎python/tests/unit/contents/test_annotation_content.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ def test_update_indices():
7070

7171
def test_to_str():
7272
annotation = AnnotationContent(file_id="12345", quote="This is a quote.", start_index=5, end_index=20)
73-
assert str(annotation) == "AnnotationContent(file_id=12345, quote=This is a quote., start_index=5, end_index=20)"
73+
assert (
74+
str(annotation)
75+
== "AnnotationContent(file_id=12345, url=None, quote=This is a quote., start_index=5, end_index=20)"
76+
) # noqa: E501
7477

7578

7679
def test_to_element():

‎python/tests/unit/contents/test_streaming_annotation_content.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def test_to_str():
7373
annotation = StreamingAnnotationContent(file_id="12345", quote="This is a quote.", start_index=5, end_index=20)
7474
assert (
7575
str(annotation)
76-
== "StreamingAnnotationContent(file_id=12345, quote=This is a quote., start_index=5, end_index=20)"
76+
== "StreamingAnnotationContent(file_id=12345, url=None, quote=This is a quote., start_index=5, end_index=20)"
7777
)
7878

7979

‎python/uv.lock

+7-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.