Python: [BREAKING] added SerializationMixin and applied to contents, agents, chat client… (#1012)

* added SerializationMixin and applied to contents, agents, chat clients, removed AFBaseModel

* fix annotations type

* mypy fixes

* fix tests

* fix serializable subvalues and added large docstring

* updated indents in code block

* fixed exported urls
This commit is contained in:
Eduard van Valkenburg
2025-09-30 21:53:46 +02:00
committed by GitHub
Unverified
parent 3eb26632ce
commit 54ad135914
84 changed files with 2302 additions and 1957 deletions
@@ -38,7 +38,7 @@ async def non_streaming_example() -> None:
agent = OpenAIChatClient(
api_key=os.getenv("ANTHROPIC_API_KEY"),
base_url="https://api.anthropic.com/v1/",
ai_model_id=os.getenv("ANTHROPIC_MODEL"),
model_id=os.getenv("ANTHROPIC_MODEL"),
).create_agent(
name="WeatherAgent",
instructions="You are a helpful weather agent.",
@@ -58,7 +58,7 @@ async def streaming_example() -> None:
agent = OpenAIChatClient(
api_key=os.getenv("ANTHROPIC_API_KEY"),
base_url="https://api.anthropic.com/v1/",
ai_model_id=os.getenv("ANTHROPIC_MODEL"),
model_id=os.getenv("ANTHROPIC_MODEL"),
).create_agent(
name="WeatherAgent",
instructions="You are a helpful weather agent.",
@@ -3,7 +3,7 @@
import asyncio
import random
from collections.abc import AsyncIterable, MutableSequence
from typing import Any
from typing import Any, ClassVar
from agent_framework import (
BaseChatClient,
@@ -46,9 +46,7 @@ class EchoingChatClient(BaseChatClient):
and implementing the required _inner_get_response() and _inner_get_streaming_response() methods.
"""
OTEL_PROVIDER_NAME: str = "EchoingChatClient"
prefix: str = "Echo:"
OTEL_PROVIDER_NAME: ClassVar[str] = "EchoingChatClient"
def __init__(self, *, prefix: str = "Echo:", **kwargs: Any) -> None:
"""Initialize the EchoingChatClient.
@@ -57,10 +55,8 @@ class EchoingChatClient(BaseChatClient):
prefix: Prefix to add to echoed messages.
**kwargs: Additional keyword arguments passed to BaseChatClient.
"""
super().__init__(
prefix=prefix, # type: ignore
**kwargs,
)
super().__init__(**kwargs)
self.prefix = prefix
async def _inner_get_response(
self,
@@ -21,7 +21,7 @@ async def main() -> None:
print("=== OpenAI Assistants Client with Explicit Settings ===")
async with OpenAIAssistantsClient(
ai_model_id=os.environ["OPENAI_CHAT_MODEL_ID"],
model_id=os.environ["OPENAI_CHAT_MODEL_ID"],
api_key=os.environ["OPENAI_API_KEY"],
).create_agent(
instructions="You are a helpful weather agent.",
@@ -21,7 +21,7 @@ async def main() -> None:
print("=== OpenAI Chat Client with Explicit Settings ===")
agent = OpenAIChatClient(
ai_model_id=os.environ["OPENAI_CHAT_MODEL_ID"],
model_id=os.environ["OPENAI_CHAT_MODEL_ID"],
api_key=os.environ["OPENAI_API_KEY"],
).create_agent(
instructions="You are a helpful weather agent.",
@@ -7,7 +7,7 @@ from agent_framework.openai import OpenAIChatClient
async def main() -> None:
client = OpenAIChatClient(ai_model_id="gpt-4o-search-preview")
client = OpenAIChatClient(model_id="gpt-4o-search-preview")
message = "What is the current weather? Do not ask for my current location."
# Test that the client will use the web search tool with location
@@ -10,7 +10,7 @@ async def reasoning_example() -> None:
"""Example of reasoning response (get results as they are generated)."""
print("=== Reasoning Example ===")
agent = OpenAIResponsesClient(ai_model_id="gpt-5").create_agent(
agent = OpenAIResponsesClient(model_id="gpt-5").create_agent(
name="MathHelper",
instructions="You are a personal math tutor. When asked a math question, "
"write and run code using the python tool to answer the question.",
@@ -21,7 +21,7 @@ async def main() -> None:
print("=== OpenAI Responses Client with Explicit Settings ===")
agent = OpenAIResponsesClient(
ai_model_id=os.environ["OPENAI_RESPONSES_MODEL_ID"],
model_id=os.environ["OPENAI_RESPONSES_MODEL_ID"],
api_key=os.environ["OPENAI_API_KEY"],
).create_agent(
instructions="You are a helpful weather agent.",
@@ -11,7 +11,7 @@ async def main() -> None:
Creates a task for the chat request, waits briefly, then cancels it to show proper cleanup.
Configuration:
- OpenAI model ID: Use "ai_model_id" parameter or "OPENAI_CHAT_MODEL_ID" environment variable
- OpenAI model ID: Use "model_id" parameter or "OPENAI_CHAT_MODEL_ID" environment variable
- OpenAI API key: Use "api_key" parameter or "OPENAI_API_KEY" environment variable
"""
chat_client = OpenAIChatClient()
@@ -175,7 +175,7 @@ async def main() -> None:
)
# Create chat client for the agent
client = OpenAIChatClient(ai_model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
client = OpenAIChatClient(model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
# Create agent wired to the Redis context provider. The provider automatically
# persists conversational details and surfaces relevant context on each turn.
agent = client.create_agent(
@@ -219,7 +219,7 @@ async def main() -> None:
# Create agent exposing the flight search tool. Tool outputs are captured by the
# provider and become retrievable context for later turns.
client = OpenAIChatClient(ai_model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
client = OpenAIChatClient(model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
agent = client.create_agent(
name="MemoryEnhancedAssistant",
instructions=(
@@ -60,7 +60,7 @@ async def main() -> None:
)
# Create chat client for the agent
client = OpenAIChatClient(ai_model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
client = OpenAIChatClient(model_id=os.getenv("OPENAI_CHAT_MODEL_ID"), api_key=os.getenv("OPENAI_API_KEY"))
# Create agent wired to the Redis context provider. The provider automatically
# persists conversational details and surfaces relevant context on each turn.
agent = client.create_agent(
@@ -47,7 +47,7 @@ async def example_global_thread_scope() -> None:
global_thread_id = str(uuid.uuid4())
client = OpenAIChatClient(
ai_model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
@@ -100,7 +100,7 @@ async def example_per_operation_thread_scope() -> None:
print("-" * 40)
client = OpenAIChatClient(
ai_model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
@@ -168,7 +168,7 @@ async def example_multiple_agents() -> None:
print("-" * 40)
client = OpenAIChatClient(
ai_model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
)
@@ -11,7 +11,7 @@ from agent_framework.openai import OpenAIChatClient
async def test_image() -> None:
"""Test image analysis with OpenAI."""
client = OpenAIChatClient(ai_model_id="gpt-4o")
client = OpenAIChatClient(model_id="gpt-4o")
# Fetch image from httpbin
image_url = "https://httpbin.org/image/jpeg"
@@ -30,7 +30,7 @@ async def test_image() -> None:
async def test_audio() -> None:
"""Test audio analysis with OpenAI."""
client = OpenAIChatClient(ai_model_id="gpt-4o-audio-preview")
client = OpenAIChatClient(model_id="gpt-4o-audio-preview")
# Create minimal WAV file (0.1 seconds of silence)
wav_header = (
@@ -102,7 +102,7 @@ async def main() -> None:
# Create executors for the workflow.
print("Creating chat client and executors...")
mini_chat_client = OpenAIChatClient(ai_model_id="gpt-4.1-nano")
mini_chat_client = OpenAIChatClient(model_id="gpt-4.1-nano")
worker = Worker(id="sub-worker", chat_client=mini_chat_client)
request_info_executor = RequestInfoExecutor(id="request_info")
reviewer = ReviewerWithHumanInTheLoop(worker_id=worker.id, request_info_id=request_info_executor.id)
@@ -197,8 +197,8 @@ async def main() -> None:
# Initialize chat clients and executors.
print("Creating chat client and executors...")
mini_chat_client = OpenAIChatClient(ai_model_id="gpt-4.1-nano")
chat_client = OpenAIChatClient(ai_model_id="gpt-4.1")
mini_chat_client = OpenAIChatClient(model_id="gpt-4.1-nano")
chat_client = OpenAIChatClient(model_id="gpt-4.1")
reviewer = Reviewer(id="reviewer", chat_client=chat_client)
worker = Worker(id="worker", chat_client=mini_chat_client)
@@ -55,7 +55,7 @@ async def main() -> None:
# This agent requires the gpt-4o-search-preview model to perform web searches.
# Feel free to explore with other agents that support web search, for example,
# the `OpenAIResponseAgent` or `AzureAgentProtocol` with bing grounding.
chat_client=OpenAIChatClient(ai_model_id="gpt-4o-search-preview"),
chat_client=OpenAIChatClient(model_id="gpt-4o-search-preview"),
)
coder_agent = ChatAgent(
@@ -58,7 +58,7 @@ async def main() -> None:
# This agent requires the gpt-4o-search-preview model to perform web searches.
# Feel free to explore with other agents that support web search, for example,
# the `OpenAIResponseAgent` or `AzureAgentProtocol` with bing grounding.
chat_client=OpenAIChatClient(ai_model_id="gpt-4o-search-preview"),
chat_client=OpenAIChatClient(model_id="gpt-4o-search-preview"),
)
coder_agent = ChatAgent(