Python: [Breaking] Simplified Content types to a single class with classmethod constructors. (#3252)

* ported Content to a new model

* fixed linting

* fixes

* fixed data format handling

* fix for 3.10 mypy

* fix

* fix int test
This commit is contained in:
Eduard van Valkenburg
2026-01-20 23:09:39 +01:00
committed by GitHub
Unverified
parent 73761aa4a3
commit 83e6229c11
132 changed files with 3949 additions and 4741 deletions
@@ -4,7 +4,7 @@
import importlib.metadata
from agent_framework.observability import OBSERVABILITY_SETTINGS
from agent_framework.observability import enable_instrumentation
from agentlightning import AgentOpsTracer # type: ignore
try:
@@ -22,13 +22,12 @@ class AgentFrameworkTracer(AgentOpsTracer): # type: ignore
def init(self) -> None:
"""Initialize the agent-framework-lab-lightning for training."""
OBSERVABILITY_SETTINGS.enable_instrumentation = True
enable_instrumentation()
super().init()
def teardown(self) -> None:
"""Teardown the agent-framework-lab-lightning for training."""
super().teardown()
OBSERVABILITY_SETTINGS.enable_instrumentation = False
__all__: list[str] = ["AgentFrameworkTracer"]
@@ -9,8 +9,8 @@ import pytest
agentlightning = pytest.importorskip("agentlightning")
from agent_framework import AgentExecutor, AgentRunEvent, ChatAgent, WorkflowBuilder
from agent_framework.lab.lightning import AgentFrameworkTracer
from agent_framework import AgentExecutor, AgentRunEvent, ChatAgent, WorkflowBuilder, Workflow
from agent_framework_lab_lightning import AgentFrameworkTracer
from agent_framework.openai import OpenAIChatClient
from agentlightning import TracerTraceToTriplet
from openai.types.chat import ChatCompletion, ChatCompletionMessage
@@ -106,7 +106,7 @@ def workflow_two_agents():
yield workflow
async def test_openai_workflow_two_agents(workflow_two_agents):
async def test_openai_workflow_two_agents(workflow_two_agents: Workflow):
events = await workflow_two_agents.run("Please analyze the quarterly sales data")
# Get all AgentRunEvent data
@@ -121,7 +121,7 @@ async def test_openai_workflow_two_agents(workflow_two_agents):
)
async def test_observability(workflow_two_agents):
async def test_observability(workflow_two_agents: Workflow):
r"""Expected trace tree:
[workflow.run]
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft. All rights reserved.
from agent_framework._types import ChatMessage, Contents, Role
from agent_framework._types import ChatMessage, Content, Role
from loguru import logger
@@ -12,7 +12,7 @@ def flip_messages(messages: list[ChatMessage]) -> list[ChatMessage]:
messages to user messages (since users typically don't make function calls).
"""
def filter_out_function_calls(messages: list[Contents]) -> list[Contents]:
def filter_out_function_calls(messages: list[Content]) -> list[Content]:
"""Remove function call content from message contents."""
return [content for content in messages if content.type != "function_call"]
@@ -58,7 +58,7 @@ def log_messages(messages: list[ChatMessage]) -> None:
for content in msg.contents:
if hasattr(content, "type"):
if content.type == "text":
escape_text = content.text.replace("<", r"\<")
escape_text = content.text.replace("<", r"\<") # type: ignore[union-attr]
if msg.role == Role.SYSTEM:
logger_.info(f"<cyan>[SYSTEM]</cyan> {escape_text}")
elif msg.role == Role.USER:
@@ -77,7 +77,7 @@ class SlidingWindowChatMessageStore(ChatMessageStore):
for content in msg.contents:
if hasattr(content, "type"):
if content.type == "text":
total_tokens += len(self.encoding.encode(content.text))
total_tokens += len(self.encoding.encode(content.text)) # type: ignore[arg-type]
elif content.type == "function_call":
total_tokens += 4
# Serialize function call and count tokens
@@ -60,7 +60,7 @@ def convert_agent_framework_messages_to_tau2_messages(messages: list[ChatMessage
text_content = None
text_contents = [c for c in msg.contents if hasattr(c, "text") and hasattr(c, "type") and c.type == "text"]
if text_contents:
text_content = " ".join(c.text for c in text_contents)
text_content = " ".join(c.text for c in text_contents) # type: ignore[misc]
# Extract function calls and convert to ToolCall objects
function_calls = [c for c in msg.contents if hasattr(c, "type") and c.type == "function_call"]
@@ -2,7 +2,7 @@
from unittest.mock import patch
from agent_framework._types import ChatMessage, FunctionCallContent, FunctionResultContent, Role, TextContent
from agent_framework._types import ChatMessage, Content, Role
from agent_framework_lab_tau2._message_utils import flip_messages, log_messages
@@ -10,7 +10,10 @@ def test_flip_messages_user_to_assistant():
"""Test flipping user message to assistant."""
messages = [
ChatMessage(
role=Role.USER, contents=[TextContent(text="Hello assistant")], author_name="User1", message_id="msg_001"
role=Role.USER,
contents=[Content.from_text(text="Hello assistant")],
author_name="User1",
message_id="msg_001",
)
]
@@ -28,7 +31,7 @@ def test_flip_messages_assistant_to_user():
messages = [
ChatMessage(
role=Role.ASSISTANT,
contents=[TextContent(text="Hello user")],
contents=[Content.from_text(text="Hello user")],
author_name="Assistant1",
message_id="msg_002",
)
@@ -45,12 +48,16 @@ def test_flip_messages_assistant_to_user():
def test_flip_messages_assistant_with_function_calls_filtered():
"""Test that function calls are filtered out when flipping assistant to user."""
function_call = FunctionCallContent(call_id="call_123", name="test_function", arguments={"param": "value"})
function_call = Content.from_function_call(call_id="call_123", name="test_function", arguments={"param": "value"})
messages = [
ChatMessage(
role=Role.ASSISTANT,
contents=[TextContent(text="I'll call a function"), function_call, TextContent(text="After the call")],
contents=[
Content.from_text(text="I'll call a function"),
function_call,
Content.from_text(text="After the call"),
],
message_id="msg_003",
)
]
@@ -68,7 +75,7 @@ def test_flip_messages_assistant_with_function_calls_filtered():
def test_flip_messages_assistant_with_only_function_calls_skipped():
"""Test that assistant messages with only function calls are skipped."""
function_call = FunctionCallContent(call_id="call_456", name="another_function", arguments={"key": "value"})
function_call = Content.from_function_call(call_id="call_456", name="another_function", arguments={"key": "value"})
messages = [
ChatMessage(role=Role.ASSISTANT, contents=[function_call], message_id="msg_004") # Only function call, no text
@@ -82,7 +89,7 @@ def test_flip_messages_assistant_with_only_function_calls_skipped():
def test_flip_messages_tool_messages_skipped():
"""Test that tool messages are skipped."""
function_result = FunctionResultContent(call_id="call_789", result={"success": True})
function_result = Content.from_function_result(call_id="call_789", result={"success": True})
messages = [ChatMessage(role=Role.TOOL, contents=[function_result])]
@@ -94,7 +101,9 @@ def test_flip_messages_tool_messages_skipped():
def test_flip_messages_system_messages_preserved():
"""Test that system messages are preserved as-is."""
messages = [ChatMessage(role=Role.SYSTEM, contents=[TextContent(text="System instruction")], message_id="sys_001")]
messages = [
ChatMessage(role=Role.SYSTEM, contents=[Content.from_text(text="System instruction")], message_id="sys_001")
]
flipped = flip_messages(messages)
@@ -106,16 +115,16 @@ def test_flip_messages_system_messages_preserved():
def test_flip_messages_mixed_conversation():
"""Test flipping a mixed conversation."""
function_call = FunctionCallContent(call_id="call_mixed", name="mixed_function", arguments={})
function_call = Content.from_function_call(call_id="call_mixed", name="mixed_function", arguments={})
function_result = FunctionResultContent(call_id="call_mixed", result="function result")
function_result = Content.from_function_result(call_id="call_mixed", result="function result")
messages = [
ChatMessage(role=Role.SYSTEM, contents=[TextContent(text="System prompt")]),
ChatMessage(role=Role.USER, contents=[TextContent(text="User question")]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Assistant response"), function_call]),
ChatMessage(role=Role.SYSTEM, contents=[Content.from_text(text="System prompt")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="User question")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Assistant response"), function_call]),
ChatMessage(role=Role.TOOL, contents=[function_result]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Final response")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Final response")]),
]
flipped = flip_messages(messages)
@@ -151,7 +160,10 @@ def test_flip_messages_preserves_metadata():
"""Test that message metadata is preserved during flipping."""
messages = [
ChatMessage(
role=Role.USER, contents=[TextContent(text="Test message")], author_name="TestUser", message_id="test_123"
role=Role.USER,
contents=[Content.from_text(text="Test message")],
author_name="TestUser",
message_id="test_123",
)
]
@@ -166,8 +178,8 @@ def test_flip_messages_preserves_metadata():
def test_log_messages_text_content(mock_logger):
"""Test logging messages with text content."""
messages = [
ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Hi there!")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Hi there!")]),
]
log_messages(messages)
@@ -179,7 +191,7 @@ def test_log_messages_text_content(mock_logger):
@patch("agent_framework_lab_tau2._message_utils.logger")
def test_log_messages_function_call(mock_logger):
"""Test logging messages with function calls."""
function_call = FunctionCallContent(call_id="call_log", name="log_function", arguments={"param": "value"})
function_call = Content.from_function_call(call_id="call_log", name="log_function", arguments={"param": "value"})
messages = [ChatMessage(role=Role.ASSISTANT, contents=[function_call])]
@@ -195,7 +207,7 @@ def test_log_messages_function_call(mock_logger):
@patch("agent_framework_lab_tau2._message_utils.logger")
def test_log_messages_function_result(mock_logger):
"""Test logging messages with function results."""
function_result = FunctionResultContent(call_id="call_result", result="success")
function_result = Content.from_function_result(call_id="call_result", result="success")
messages = [ChatMessage(role=Role.TOOL, contents=[function_result])]
@@ -211,10 +223,10 @@ def test_log_messages_function_result(mock_logger):
def test_log_messages_different_roles(mock_logger):
"""Test logging messages with different roles get different colors."""
messages = [
ChatMessage(role=Role.SYSTEM, contents=[TextContent(text="System")]),
ChatMessage(role=Role.USER, contents=[TextContent(text="User")]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Assistant")]),
ChatMessage(role=Role.TOOL, contents=[TextContent(text="Tool")]),
ChatMessage(role=Role.SYSTEM, contents=[Content.from_text(text="System")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="User")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Assistant")]),
ChatMessage(role=Role.TOOL, contents=[Content.from_text(text="Tool")]),
]
log_messages(messages)
@@ -238,7 +250,7 @@ def test_log_messages_different_roles(mock_logger):
@patch("agent_framework_lab_tau2._message_utils.logger")
def test_log_messages_escapes_html(mock_logger):
"""Test that HTML-like characters are properly escaped in log output."""
messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Message with <tag> content")])]
messages = [ChatMessage(role=Role.USER, contents=[Content.from_text(text="Message with <tag> content")])]
log_messages(messages)
@@ -251,12 +263,12 @@ def test_log_messages_escapes_html(mock_logger):
@patch("agent_framework_lab_tau2._message_utils.logger")
def test_log_messages_mixed_content_types(mock_logger):
"""Test logging messages with mixed content types."""
function_call = FunctionCallContent(call_id="mixed_call", name="mixed_function", arguments={"key": "value"})
function_call = Content.from_function_call(call_id="mixed_call", name="mixed_function", arguments={"key": "value"})
messages = [
ChatMessage(
role=Role.ASSISTANT,
contents=[TextContent(text="I'll call a function"), function_call, TextContent(text="Done!")],
contents=[Content.from_text(text="I'll call a function"), function_call, Content.from_text(text="Done!")],
)
]
@@ -4,7 +4,7 @@
from unittest.mock import patch
from agent_framework._types import ChatMessage, FunctionCallContent, FunctionResultContent, Role, TextContent
from agent_framework._types import ChatMessage, Content, Role
from agent_framework_lab_tau2._sliding_window import SlidingWindowChatMessageStore
@@ -36,8 +36,8 @@ def test_initialization_with_parameters():
def test_initialization_with_messages():
"""Test initializing with existing messages."""
messages = [
ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Hi there!")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Hi there!")]),
]
sliding_window = SlidingWindowChatMessageStore(messages=messages, max_tokens=1000)
@@ -51,8 +51,8 @@ async def test_add_messages_simple():
sliding_window = SlidingWindowChatMessageStore(max_tokens=10000) # Large limit
new_messages = [
ChatMessage(role=Role.USER, contents=[TextContent(text="What's the weather?")]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="I can help with that.")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="What's the weather?")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="I can help with that.")]),
]
await sliding_window.add_messages(new_messages)
@@ -69,7 +69,8 @@ async def test_list_all_messages_vs_list_messages():
# Add many messages to trigger truncation
messages = [
ChatMessage(role=Role.USER, contents=[TextContent(text=f"Message {i} with some content")]) for i in range(10)
ChatMessage(role=Role.USER, contents=[Content.from_text(text=f"Message {i} with some content")])
for i in range(10)
]
await sliding_window.add_messages(messages)
@@ -87,7 +88,7 @@ async def test_list_all_messages_vs_list_messages():
def test_get_token_count_basic():
"""Test basic token counting."""
sliding_window = SlidingWindowChatMessageStore(max_tokens=1000)
sliding_window.truncated_messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")])]
sliding_window.truncated_messages = [ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello")])]
token_count = sliding_window.get_token_count()
@@ -104,7 +105,7 @@ def test_get_token_count_with_system_message():
token_count_empty = sliding_window.get_token_count()
# Add a message
sliding_window.truncated_messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")])]
sliding_window.truncated_messages = [ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello")])]
token_count_with_message = sliding_window.get_token_count()
# With message should be more tokens
@@ -114,7 +115,7 @@ def test_get_token_count_with_system_message():
def test_get_token_count_function_call():
"""Test token counting with function calls."""
function_call = FunctionCallContent(call_id="call_123", name="test_function", arguments={"param": "value"})
function_call = Content.from_function_call(call_id="call_123", name="test_function", arguments={"param": "value"})
sliding_window = SlidingWindowChatMessageStore(max_tokens=1000)
sliding_window.truncated_messages = [ChatMessage(role=Role.ASSISTANT, contents=[function_call])]
@@ -125,7 +126,7 @@ def test_get_token_count_function_call():
def test_get_token_count_function_result():
"""Test token counting with function results."""
function_result = FunctionResultContent(call_id="call_123", result={"success": True, "data": "result"})
function_result = Content.from_function_result(call_id="call_123", result={"success": True, "data": "result"})
sliding_window = SlidingWindowChatMessageStore(max_tokens=1000)
sliding_window.truncated_messages = [ChatMessage(role=Role.TOOL, contents=[function_result])]
@@ -143,13 +144,15 @@ def test_truncate_messages_removes_old_messages(mock_logger):
messages = [
ChatMessage(
role=Role.USER,
contents=[TextContent(text="This is a very long message that should exceed the token limit")],
contents=[Content.from_text(text="This is a very long message that should exceed the token limit")],
),
ChatMessage(
role=Role.ASSISTANT,
contents=[TextContent(text="This is another very long message that should also exceed the token limit")],
contents=[
Content.from_text(text="This is another very long message that should also exceed the token limit")
],
),
ChatMessage(role=Role.USER, contents=[TextContent(text="Short msg")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="Short msg")]),
]
sliding_window.truncated_messages = messages.copy()
@@ -168,8 +171,10 @@ def test_truncate_messages_removes_leading_tool_messages(mock_logger):
sliding_window = SlidingWindowChatMessageStore(max_tokens=10000) # Large limit
# Create messages starting with tool message
tool_message = ChatMessage(role=Role.TOOL, contents=[FunctionResultContent(call_id="call_123", result="result")])
user_message = ChatMessage(role=Role.USER, contents=[TextContent(text="Hello")])
tool_message = ChatMessage(
role=Role.TOOL, contents=[Content.from_function_result(call_id="call_123", result="result")]
)
user_message = ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello")])
sliding_window.truncated_messages = [tool_message, user_message]
sliding_window.truncate_messages()
@@ -227,24 +232,27 @@ async def test_real_world_scenario():
# Simulate a conversation
conversation = [
ChatMessage(role=Role.USER, contents=[TextContent(text="Hello, how are you?")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello, how are you?")]),
ChatMessage(
role=Role.ASSISTANT, contents=[TextContent(text="I'm doing well, thank you! How can I help you today?")]
role=Role.ASSISTANT,
contents=[Content.from_text(text="I'm doing well, thank you! How can I help you today?")],
),
ChatMessage(role=Role.USER, contents=[TextContent(text="Can you tell me about the weather?")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="Can you tell me about the weather?")]),
ChatMessage(
role=Role.ASSISTANT,
contents=[
TextContent(
Content.from_text(
text="I'd be happy to help with weather information, "
"but I don't have access to current weather data."
)
],
),
ChatMessage(role=Role.USER, contents=[TextContent(text="What about telling me a joke instead?")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="What about telling me a joke instead?")]),
ChatMessage(
role=Role.ASSISTANT,
contents=[TextContent(text="Sure! Why don't scientists trust atoms? Because they make up everything!")],
contents=[
Content.from_text(text="Sure! Why don't scientists trust atoms? Because they make up everything!")
],
),
]
@@ -7,7 +7,7 @@ from pathlib import Path
import pytest
from agent_framework._tools import AIFunction
from agent_framework._types import ChatMessage, FunctionCallContent, FunctionResultContent, Role, TextContent
from agent_framework._types import ChatMessage, Content, Role
from agent_framework_lab_tau2._tau2_utils import (
convert_agent_framework_messages_to_tau2_messages,
convert_tau2_tool_to_ai_function,
@@ -92,7 +92,7 @@ def test_convert_tau2_tool_to_ai_function_multiple_tools(tau2_airline_environmen
def test_convert_agent_framework_messages_to_tau2_messages_system():
"""Test converting system message."""
messages = [ChatMessage(role=Role.SYSTEM, contents=[TextContent(text="System instruction")])]
messages = [ChatMessage(role=Role.SYSTEM, contents=[Content.from_text(text="System instruction")])]
tau2_messages = convert_agent_framework_messages_to_tau2_messages(messages)
@@ -104,7 +104,7 @@ def test_convert_agent_framework_messages_to_tau2_messages_system():
def test_convert_agent_framework_messages_to_tau2_messages_user():
"""Test converting user message."""
messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="Hello assistant")])]
messages = [ChatMessage(role=Role.USER, contents=[Content.from_text(text="Hello assistant")])]
tau2_messages = convert_agent_framework_messages_to_tau2_messages(messages)
@@ -117,7 +117,7 @@ def test_convert_agent_framework_messages_to_tau2_messages_user():
def test_convert_agent_framework_messages_to_tau2_messages_assistant():
"""Test converting assistant message."""
messages = [ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Hello user")])]
messages = [ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Hello user")])]
tau2_messages = convert_agent_framework_messages_to_tau2_messages(messages)
@@ -130,9 +130,11 @@ def test_convert_agent_framework_messages_to_tau2_messages_assistant():
def test_convert_agent_framework_messages_to_tau2_messages_with_function_call():
"""Test converting message with function call."""
function_call = FunctionCallContent(call_id="call_123", name="test_function", arguments={"param": "value"})
function_call = Content.from_function_call(call_id="call_123", name="test_function", arguments={"param": "value"})
messages = [ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="I'll call a function"), function_call])]
messages = [
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="I'll call a function"), function_call])
]
tau2_messages = convert_agent_framework_messages_to_tau2_messages(messages)
@@ -152,7 +154,7 @@ def test_convert_agent_framework_messages_to_tau2_messages_with_function_call():
def test_convert_agent_framework_messages_to_tau2_messages_with_function_result():
"""Test converting message with function result."""
function_result = FunctionResultContent(call_id="call_123", result={"success": True, "data": "result data"})
function_result = Content.from_function_result(call_id="call_123", result={"success": True, "data": "result data"})
messages = [ChatMessage(role=Role.TOOL, contents=[function_result])]
@@ -170,7 +172,7 @@ def test_convert_agent_framework_messages_to_tau2_messages_with_function_result(
def test_convert_agent_framework_messages_to_tau2_messages_with_error():
"""Test converting function result with error."""
function_result = FunctionResultContent(
function_result = Content.from_function_result(
call_id="call_456", result="Error occurred", exception=Exception("Test error")
)
@@ -185,7 +187,11 @@ def test_convert_agent_framework_messages_to_tau2_messages_with_error():
def test_convert_agent_framework_messages_to_tau2_messages_multiple_text_contents():
"""Test converting message with multiple text contents."""
messages = [ChatMessage(role=Role.USER, contents=[TextContent(text="First part"), TextContent(text="Second part")])]
messages = [
ChatMessage(
role=Role.USER, contents=[Content.from_text(text="First part"), Content.from_text(text="Second part")]
)
]
tau2_messages = convert_agent_framework_messages_to_tau2_messages(messages)
@@ -196,16 +202,16 @@ def test_convert_agent_framework_messages_to_tau2_messages_multiple_text_content
def test_convert_agent_framework_messages_to_tau2_messages_complex_scenario():
"""Test converting complex scenario with multiple message types."""
function_call = FunctionCallContent(call_id="call_789", name="complex_tool", arguments='{"key": "value"}')
function_call = Content.from_function_call(call_id="call_789", name="complex_tool", arguments='{"key": "value"}')
function_result = FunctionResultContent(call_id="call_789", result={"output": "tool result"})
function_result = Content.from_function_result(call_id="call_789", result={"output": "tool result"})
messages = [
ChatMessage(role=Role.SYSTEM, contents=[TextContent(text="System prompt")]),
ChatMessage(role=Role.USER, contents=[TextContent(text="User request")]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="I'll help you"), function_call]),
ChatMessage(role=Role.SYSTEM, contents=[Content.from_text(text="System prompt")]),
ChatMessage(role=Role.USER, contents=[Content.from_text(text="User request")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="I'll help you"), function_call]),
ChatMessage(role=Role.TOOL, contents=[function_result]),
ChatMessage(role=Role.ASSISTANT, contents=[TextContent(text="Based on the result...")]),
ChatMessage(role=Role.ASSISTANT, contents=[Content.from_text(text="Based on the result...")]),
]
tau2_messages = convert_agent_framework_messages_to_tau2_messages(messages)