Python: Create/Get Agent API for OpenAI Assistants (#3208)

* Added provider implementation

* Added example with response format

* Small improvements
This commit is contained in:
Dmytro Struk
2026-01-15 14:52:32 -08:00
committed by GitHub
Unverified
parent dd3e2b6e53
commit b5ca0c8eda
14 changed files with 1940 additions and 126 deletions
@@ -6,13 +6,15 @@ This folder contains examples demonstrating different ways to create and use age
| File | Description |
|------|-------------|
| [`openai_assistants_basic.py`](openai_assistants_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIAssistantsClient`. Shows both streaming and non-streaming responses with automatic assistant creation and cleanup. |
| [`openai_assistants_with_code_interpreter.py`](openai_assistants_with_code_interpreter.py) | Shows how to use the HostedCodeInterpreterTool with OpenAI agents to write and execute Python code. Includes helper methods for accessing code interpreter data from response chunks. |
| [`openai_assistants_with_existing_assistant.py`](openai_assistants_with_existing_assistant.py) | Shows how to work with a pre-existing assistant by providing the assistant ID to the OpenAI Assistants client. Demonstrates proper cleanup of manually created assistants. |
| [`openai_assistants_with_explicit_settings.py`](openai_assistants_with_explicit_settings.py) | Shows how to initialize an agent with a specific assistants client, configuring settings explicitly including API key and model ID. |
| [`openai_assistants_with_file_search.py`](openai_assistants_with_file_search.py) | Demonstrates how to use file search capabilities with OpenAI agents, allowing the agent to search through uploaded files to answer questions. |
| [`openai_assistants_with_function_tools.py`](openai_assistants_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
| [`openai_assistants_with_thread.py`](openai_assistants_with_thread.py) | Demonstrates thread management with OpenAI agents, including automatic thread creation for stateless conversations and explicit thread management for maintaining conversation context across multiple interactions. |
| [`openai_assistants_basic.py`](openai_assistants_basic.py) | Basic usage of `OpenAIAssistantProvider` with streaming and non-streaming responses. |
| [`openai_assistants_provider_methods.py`](openai_assistants_provider_methods.py) | Demonstrates all `OpenAIAssistantProvider` methods: `create_agent()`, `get_agent()`, and `as_agent()`. |
| [`openai_assistants_with_code_interpreter.py`](openai_assistants_with_code_interpreter.py) | Using `HostedCodeInterpreterTool` with `OpenAIAssistantProvider` to execute Python code. |
| [`openai_assistants_with_existing_assistant.py`](openai_assistants_with_existing_assistant.py) | Working with pre-existing assistants using `get_agent()` and `as_agent()` methods. |
| [`openai_assistants_with_explicit_settings.py`](openai_assistants_with_explicit_settings.py) | Configuring `OpenAIAssistantProvider` with explicit settings including API key and model ID. |
| [`openai_assistants_with_file_search.py`](openai_assistants_with_file_search.py) | Using `HostedFileSearchTool` with `OpenAIAssistantProvider` for file search capabilities. |
| [`openai_assistants_with_function_tools.py`](openai_assistants_with_function_tools.py) | Function tools with `OpenAIAssistantProvider` at both agent-level and query-level. |
| [`openai_assistants_with_response_format.py`](openai_assistants_with_response_format.py) | Structured outputs with `OpenAIAssistantProvider` using Pydantic models. |
| [`openai_assistants_with_thread.py`](openai_assistants_with_thread.py) | Thread management with `OpenAIAssistantProvider` for conversation context persistence. |
| [`openai_chat_client_basic.py`](openai_chat_client_basic.py) | The simplest way to create an agent using `ChatAgent` with `OpenAIChatClient`. Shows both streaming and non-streaming responses for chat-based interactions with OpenAI models. |
| [`openai_chat_client_with_explicit_settings.py`](openai_chat_client_with_explicit_settings.py) | Shows how to initialize an agent with a specific chat client, configuring settings explicitly including API key and model ID. |
| [`openai_chat_client_with_function_tools.py`](openai_chat_client_with_function_tools.py) | Demonstrates how to use function tools with agents. Shows both agent-level tools (defined when creating the agent) and query-level tools (provided with specific queries). |
@@ -1,16 +1,18 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from random import randint
from typing import Annotated
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
"""
OpenAI Assistants Basic Example
This sample demonstrates basic usage of OpenAIAssistantsClient with automatic
This sample demonstrates basic usage of OpenAIAssistantProvider with automatic
assistant lifecycle management, showing both streaming and non-streaming responses.
"""
@@ -20,35 +22,50 @@ def get_weather(
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
async def non_streaming_example() -> None:
"""Example of non-streaming response (get the complete result at once)."""
print("=== Non-streaming Response Example ===")
# Since no assistant ID is provided, the assistant will be automatically created
# and deleted after getting a response
async with OpenAIAssistantsClient().create_agent(
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Create a new assistant via the provider
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
tools=[get_weather],
)
try:
query = "What's the weather like in Seattle?"
print(f"User: {query}")
result = await agent.run(query)
print(f"Agent: {result}\n")
finally:
# Clean up the assistant from OpenAI
await client.beta.assistants.delete(agent.id)
async def streaming_example() -> None:
"""Example of streaming response (get results as they are generated)."""
print("=== Streaming Response Example ===")
# Since no assistant ID is provided, the assistant will be automatically created
# and deleted after getting a response
async with OpenAIAssistantsClient().create_agent(
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Create a new assistant via the provider
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
tools=[get_weather],
)
try:
query = "What's the weather like in Portland?"
print(f"User: {query}")
print("Agent: ", end="", flush=True)
@@ -56,10 +73,13 @@ async def streaming_example() -> None:
if chunk.text:
print(chunk.text, end="", flush=True)
print("\n")
finally:
# Clean up the assistant from OpenAI
await client.beta.assistants.delete(agent.id)
async def main() -> None:
print("=== Basic OpenAI Assistants Chat Client Agent Example ===")
print("=== Basic OpenAI Assistants Provider Example ===")
await non_streaming_example()
await streaming_example()
@@ -0,0 +1,149 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from random import randint
from typing import Annotated
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
"""
OpenAI Assistant Provider Methods Example
This sample demonstrates the methods available on the OpenAIAssistantProvider class:
- create_agent(): Create a new assistant on the service
- get_agent(): Retrieve an existing assistant by ID
- as_agent(): Wrap an SDK Assistant object without making HTTP calls
"""
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
async def create_agent_example() -> None:
"""Create a new assistant using provider.create_agent()."""
print("\n--- create_agent() ---")
async with (
AsyncOpenAI() as client,
OpenAIAssistantProvider(client) as provider,
):
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful weather assistant.",
tools=[get_weather],
)
try:
print(f"Created: {agent.name} (ID: {agent.id})")
result = await agent.run("What's the weather in Seattle?")
print(f"Response: {result}")
finally:
await client.beta.assistants.delete(agent.id)
async def get_agent_example() -> None:
"""Retrieve an existing assistant by ID using provider.get_agent()."""
print("\n--- get_agent() ---")
async with (
AsyncOpenAI() as client,
OpenAIAssistantProvider(client) as provider,
):
# Create an assistant directly with SDK (simulating pre-existing assistant)
sdk_assistant = await client.beta.assistants.create(
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
name="ExistingAssistant",
instructions="You always respond with 'Hello!'",
)
try:
# Retrieve using provider
agent = await provider.get_agent(sdk_assistant.id)
print(f"Retrieved: {agent.name} (ID: {agent.id})")
result = await agent.run("Hi there!")
print(f"Response: {result}")
finally:
await client.beta.assistants.delete(sdk_assistant.id)
async def as_agent_example() -> None:
"""Wrap an SDK Assistant object using provider.as_agent()."""
print("\n--- as_agent() ---")
async with (
AsyncOpenAI() as client,
OpenAIAssistantProvider(client) as provider,
):
# Create assistant using SDK
sdk_assistant = await client.beta.assistants.create(
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
name="WrappedAssistant",
instructions="You respond with poetry.",
)
try:
# Wrap synchronously (no HTTP call)
agent = provider.as_agent(sdk_assistant)
print(f"Wrapped: {agent.name} (ID: {agent.id})")
result = await agent.run("Tell me about the sunset.")
print(f"Response: {result}")
finally:
await client.beta.assistants.delete(sdk_assistant.id)
async def multiple_agents_example() -> None:
"""Create and manage multiple assistants with a single provider."""
print("\n--- Multiple Agents ---")
async with (
AsyncOpenAI() as client,
OpenAIAssistantProvider(client) as provider,
):
weather_agent = await provider.create_agent(
name="WeatherSpecialist",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a weather specialist.",
tools=[get_weather],
)
greeter_agent = await provider.create_agent(
name="GreeterAgent",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a friendly greeter.",
)
try:
print(f"Created: {weather_agent.name}, {greeter_agent.name}")
greeting = await greeter_agent.run("Hello!")
print(f"Greeter: {greeting}")
weather = await weather_agent.run("What's the weather in Tokyo?")
print(f"Weather: {weather}")
finally:
await client.beta.assistants.delete(weather_agent.id)
await client.beta.assistants.delete(greeter_agent.id)
async def main() -> None:
print("OpenAI Assistant Provider Methods")
await create_agent_example()
await get_agent_example()
await as_agent_example()
await multiple_agents_example()
if __name__ == "__main__":
asyncio.run(main())
@@ -1,9 +1,11 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework import AgentResponseUpdate, ChatAgent, ChatResponseUpdate, HostedCodeInterpreterTool
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework import AgentResponseUpdate, ChatResponseUpdate, HostedCodeInterpreterTool
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from openai.types.beta.threads.runs import (
CodeInterpreterToolCallDelta,
RunStepDelta,
@@ -41,13 +43,19 @@ def get_code_interpreter_chunk(chunk: AgentResponseUpdate) -> str | None:
async def main() -> None:
"""Example showing how to use the HostedCodeInterpreterTool with OpenAI Assistants."""
print("=== OpenAI Assistants Agent with Code Interpreter Example ===")
print("=== OpenAI Assistants Provider with Code Interpreter Example ===")
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
agent = await provider.create_agent(
name="CodeHelper",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful assistant that can write and execute Python code to solve problems.",
tools=HostedCodeInterpreterTool(),
) as agent:
tools=[HostedCodeInterpreterTool()],
)
try:
query = "Use code to get the factorial of 100?"
print(f"User: {query}")
print("Agent: ", end="", flush=True)
@@ -60,6 +68,8 @@ async def main() -> None:
generated_code += code_interpreter_chunk
print(f"\nGenerated code:\n{generated_code}")
finally:
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
@@ -5,8 +5,7 @@ import os
from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
@@ -14,7 +13,7 @@ from pydantic import Field
OpenAI Assistants with Existing Assistant Example
This sample demonstrates working with pre-existing OpenAI Assistants
using existing assistant IDs rather than creating new ones.
using the provider's get_agent() and as_agent() methods.
"""
@@ -23,31 +22,86 @@ def get_weather(
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
async def example_get_agent_by_id() -> None:
"""Example: Using get_agent() to retrieve an existing assistant by ID."""
print("=== Get Existing Assistant by ID ===")
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Create an assistant via SDK (simulating an existing assistant)
created_assistant = await client.beta.assistants.create(
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
name="WeatherAssistant",
tools=[
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the weather for a given location.",
"parameters": {
"type": "object",
"properties": {"location": {"type": "string", "description": "The location"}},
"required": ["location"],
},
},
}
],
)
print(f"Created assistant: {created_assistant.id}")
try:
# Use get_agent() to retrieve the existing assistant
agent = await provider.get_agent(
assistant_id=created_assistant.id,
tools=[get_weather], # Required: implementation for function tools
instructions="You are a helpful weather agent.",
)
result = await agent.run("What's the weather like in Tokyo?")
print(f"Agent: {result}\n")
finally:
await client.beta.assistants.delete(created_assistant.id)
print("Assistant deleted.\n")
async def example_as_agent_wrap_sdk_object() -> None:
"""Example: Using as_agent() to wrap an existing SDK Assistant object."""
print("=== Wrap Existing SDK Assistant Object ===")
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Create and fetch an assistant via SDK
created_assistant = await client.beta.assistants.create(
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
name="SimpleAssistant",
instructions="You are a friendly assistant.",
)
print(f"Created assistant: {created_assistant.id}")
try:
# Use as_agent() to wrap the SDK object
agent = provider.as_agent(
created_assistant,
instructions="You are an extremely helpful assistant. Be enthusiastic!",
)
result = await agent.run("Hello! What can you help me with?")
print(f"Agent: {result}\n")
finally:
await client.beta.assistants.delete(created_assistant.id)
print("Assistant deleted.\n")
async def main() -> None:
print("=== OpenAI Assistants Chat Client with Existing Assistant ===")
print("=== OpenAI Assistants Provider with Existing Assistant Examples ===\n")
# Create the client
client = AsyncOpenAI()
# Create an assistant that will persist
created_assistant = await client.beta.assistants.create(
model=os.environ["OPENAI_CHAT_MODEL_ID"], name="WeatherAssistant"
)
try:
async with ChatAgent(
chat_client=OpenAIAssistantsClient(async_client=client, assistant_id=created_assistant.id),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
result = await agent.run("What's the weather like in Tokyo?")
print(f"Result: {result}\n")
finally:
# Clean up the assistant manually
await client.beta.assistants.delete(created_assistant.id)
await example_get_agent_by_id()
await example_as_agent_wrap_sdk_object()
if __name__ == "__main__":
@@ -5,7 +5,8 @@ import os
from random import randint
from typing import Annotated
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
"""
@@ -21,21 +22,28 @@ def get_weather(
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
async def main() -> None:
print("=== OpenAI Assistants Client with Explicit Settings ===")
print("=== OpenAI Assistants Provider with Explicit Settings ===")
async with OpenAIAssistantsClient(
model_id=os.environ["OPENAI_CHAT_MODEL_ID"],
api_key=os.environ["OPENAI_API_KEY"],
).create_agent(
# Create client with explicit API key
client = AsyncOpenAI(api_key=os.environ["OPENAI_API_KEY"])
provider = OpenAIAssistantProvider(client)
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ["OPENAI_CHAT_MODEL_ID"],
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
tools=[get_weather],
)
try:
result = await agent.run("What's the weather like in New York?")
print(f"Result: {result}\n")
finally:
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
@@ -1,9 +1,11 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework import ChatAgent, HostedFileSearchTool, HostedVectorStoreContent
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework import HostedFileSearchTool, HostedVectorStoreContent
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
"""
OpenAI Assistants with File Search Example
@@ -12,41 +14,43 @@ This sample demonstrates using HostedFileSearchTool with OpenAI Assistants
for document-based question answering and information retrieval.
"""
# Helper functions
async def create_vector_store(client: OpenAIAssistantsClient) -> tuple[str, HostedVectorStoreContent]:
async def create_vector_store(client: AsyncOpenAI) -> tuple[str, HostedVectorStoreContent]:
"""Create a vector store with sample documents."""
file = await client.client.files.create(
file = await client.files.create(
file=("todays_weather.txt", b"The weather today is sunny with a high of 75F."), purpose="user_data"
)
vector_store = await client.client.vector_stores.create(
vector_store = await client.vector_stores.create(
name="knowledge_base",
expires_after={"anchor": "last_active_at", "days": 1},
)
result = await client.client.vector_stores.files.create_and_poll(vector_store_id=vector_store.id, file_id=file.id)
result = await client.vector_stores.files.create_and_poll(vector_store_id=vector_store.id, file_id=file.id)
if result.last_error is not None:
raise Exception(f"Vector store file processing failed with status: {result.last_error.message}")
return file.id, HostedVectorStoreContent(vector_store_id=vector_store.id)
async def delete_vector_store(client: OpenAIAssistantsClient, file_id: str, vector_store_id: str) -> None:
async def delete_vector_store(client: AsyncOpenAI, file_id: str, vector_store_id: str) -> None:
"""Delete the vector store after using it."""
await client.client.vector_stores.delete(vector_store_id=vector_store_id)
await client.client.files.delete(file_id=file_id)
await client.vector_stores.delete(vector_store_id=vector_store_id)
await client.files.delete(file_id=file_id)
async def main() -> None:
print("=== OpenAI Assistants Client Agent with File Search Example ===\n")
print("=== OpenAI Assistants Provider with File Search Example ===\n")
client = OpenAIAssistantsClient()
async with ChatAgent(
chat_client=client,
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
agent = await provider.create_agent(
name="SearchAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful assistant that searches files in a knowledge base.",
tools=HostedFileSearchTool(),
) as agent:
tools=[HostedFileSearchTool()],
)
try:
query = "What is the weather today? Do a file search to find the answer."
file_id, vector_store = await create_vector_store(client)
@@ -57,7 +61,10 @@ async def main() -> None:
):
if chunk.text:
print(chunk.text, end="", flush=True)
await delete_vector_store(client, file_id, vector_store.vector_store_id)
finally:
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
@@ -1,12 +1,13 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from datetime import datetime, timezone
from random import randint
from typing import Annotated
from agent_framework import ChatAgent
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
"""
@@ -22,7 +23,7 @@ def get_weather(
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
def get_time() -> str:
@@ -35,13 +36,19 @@ async def tools_on_agent_level() -> None:
"""Example showing tools defined when creating the agent."""
print("=== Tools Defined on Agent Level ===")
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Tools are provided when creating the agent
# The agent can use these tools for any query during its lifetime
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
agent = await provider.create_agent(
name="InfoAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful assistant that can provide weather and time information.",
tools=[get_weather, get_time], # Tools defined at agent creation
) as agent:
)
try:
# First query - agent can use weather tool
query1 = "What's the weather like in New York?"
print(f"User: {query1}")
@@ -59,47 +66,63 @@ async def tools_on_agent_level() -> None:
print(f"User: {query3}")
result3 = await agent.run(query3)
print(f"Agent: {result3}\n")
finally:
await client.beta.assistants.delete(agent.id)
async def tools_on_run_level() -> None:
"""Example showing tools passed to the run method."""
print("=== Tools Passed to Run Method ===")
# Agent created without tools
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Agent created with base tools, additional tools can be passed at run time
agent = await provider.create_agent(
name="FlexibleAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful assistant.",
# No tools defined here
) as agent:
# First query with weather tool
tools=[get_weather], # Base tool
)
try:
# First query using base weather tool
query1 = "What's the weather like in Seattle?"
print(f"User: {query1}")
result1 = await agent.run(query1, tools=[get_weather]) # Tool passed to run method
result1 = await agent.run(query1)
print(f"Agent: {result1}\n")
# Second query with time tool
# Second query with additional time tool
query2 = "What's the current UTC time?"
print(f"User: {query2}")
result2 = await agent.run(query2, tools=[get_time]) # Different tool for this query
result2 = await agent.run(query2, tools=[get_time]) # Additional tool for this query
print(f"Agent: {result2}\n")
# Third query with multiple tools
# Third query with both tools
query3 = "What's the weather in Chicago and what's the current UTC time?"
print(f"User: {query3}")
result3 = await agent.run(query3, tools=[get_weather, get_time]) # Multiple tools
result3 = await agent.run(query3, tools=[get_time]) # Time tool adds to weather
print(f"Agent: {result3}\n")
finally:
await client.beta.assistants.delete(agent.id)
async def mixed_tools_example() -> None:
"""Example showing both agent-level tools and run-method tools."""
print("=== Mixed Tools Example (Agent + Run Method) ===")
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# Agent created with some base tools
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
agent = await provider.create_agent(
name="ComprehensiveAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a comprehensive assistant that can help with various information requests.",
tools=[get_weather], # Base tool available for all queries
) as agent:
)
try:
# Query using both agent tool and additional run-method tools
query = "What's the weather in Denver and what's the current UTC time?"
print(f"User: {query}")
@@ -110,10 +133,12 @@ async def mixed_tools_example() -> None:
tools=[get_time], # Additional tools for this specific query
)
print(f"Agent: {result}\n")
finally:
await client.beta.assistants.delete(agent.id)
async def main() -> None:
print("=== OpenAI Assistants Chat Client Agent with Function Tools Examples ===\n")
print("=== OpenAI Assistants Provider with Function Tools Examples ===\n")
await tools_on_agent_level()
await tools_on_run_level()
@@ -0,0 +1,60 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import BaseModel, ConfigDict
"""
OpenAI Assistant Provider Response Format Example
This sample demonstrates using OpenAIAssistantProvider with default_options
containing response_format for structured outputs.
"""
class WeatherInfo(BaseModel):
"""Structured weather information."""
location: str
temperature: int
conditions: str
recommendation: str
model_config = ConfigDict(extra="forbid")
async def main() -> None:
"""Example of using default_options with response_format in OpenAIAssistantProvider."""
async with (
AsyncOpenAI() as client,
OpenAIAssistantProvider(client) as provider,
):
agent = await provider.create_agent(
name="WeatherReporter",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You provide weather reports in structured JSON format.",
default_options={"response_format": WeatherInfo},
)
try:
query = "What's the weather like in Paris today?"
print(f"User: {query}")
result = await agent.run(query)
if isinstance(result.value, WeatherInfo):
weather = result.value
print("Agent:")
print(f" Location: {weather.location}")
print(f" Temperature: {weather.temperature}")
print(f" Conditions: {weather.conditions}")
print(f" Recommendation: {weather.recommendation}")
finally:
await client.beta.assistants.delete(agent.id)
if __name__ == "__main__":
asyncio.run(main())
@@ -1,11 +1,13 @@
# Copyright (c) Microsoft. All rights reserved.
import asyncio
import os
from random import randint
from typing import Annotated
from agent_framework import AgentThread, ChatAgent
from agent_framework.openai import OpenAIAssistantsClient
from agent_framework import AgentThread
from agent_framework.openai import OpenAIAssistantProvider
from openai import AsyncOpenAI
from pydantic import Field
"""
@@ -21,18 +23,24 @@ def get_weather(
) -> str:
"""Get the weather for a given location."""
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}C."
async def example_with_automatic_thread_creation() -> None:
"""Example showing automatic thread creation (service-managed thread)."""
print("=== Automatic Thread Creation Example ===")
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
tools=[get_weather],
)
try:
# First conversation - no thread provided, will be created automatically
query1 = "What's the weather like in Seattle?"
print(f"User: {query1}")
@@ -45,6 +53,8 @@ async def example_with_automatic_thread_creation() -> None:
result2 = await agent.run(query2)
print(f"Agent: {result2.text}")
print("Note: Each call creates a separate thread, so the agent doesn't remember previous context.\n")
finally:
await client.beta.assistants.delete(agent.id)
async def example_with_thread_persistence() -> None:
@@ -52,11 +62,17 @@ async def example_with_thread_persistence() -> None:
print("=== Thread Persistence Example ===")
print("Using the same thread across multiple conversations to maintain context.\n")
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
tools=[get_weather],
)
try:
# Create a new thread that will be reused
thread = agent.get_new_thread()
@@ -78,6 +94,8 @@ async def example_with_thread_persistence() -> None:
result3 = await agent.run(query3, thread=thread)
print(f"Agent: {result3.text}")
print("Note: The agent remembers context from previous messages in the same thread.\n")
finally:
await client.beta.assistants.delete(agent.id)
async def example_with_existing_thread_id() -> None:
@@ -85,14 +103,22 @@ async def example_with_existing_thread_id() -> None:
print("=== Existing Thread ID Example ===")
print("Using a specific thread ID to continue an existing conversation.\n")
client = AsyncOpenAI()
provider = OpenAIAssistantProvider(client)
# First, create a conversation and capture the thread ID
existing_thread_id = None
assistant_id = None
async with ChatAgent(
chat_client=OpenAIAssistantsClient(),
agent = await provider.create_agent(
name="WeatherAssistant",
model=os.environ.get("OPENAI_CHAT_MODEL_ID", "gpt-4"),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
tools=[get_weather],
)
assistant_id = agent.id
try:
# Start a conversation and get the thread ID
thread = agent.get_new_thread()
query1 = "What's the weather in Paris?"
@@ -104,27 +130,30 @@ async def example_with_existing_thread_id() -> None:
existing_thread_id = thread.service_thread_id
print(f"Thread ID: {existing_thread_id}")
if existing_thread_id:
print("\n--- Continuing with the same thread ID in a new agent instance ---")
if existing_thread_id:
print("\n--- Continuing with the same thread ID using get_agent ---")
# Get the existing assistant by ID
agent2 = await provider.get_agent(
assistant_id=assistant_id,
tools=[get_weather], # Must provide function implementations
)
# Create a new agent instance but use the existing thread ID
async with ChatAgent(
chat_client=OpenAIAssistantsClient(thread_id=existing_thread_id),
instructions="You are a helpful weather agent.",
tools=get_weather,
) as agent:
# Create a thread with the existing ID
thread = AgentThread(service_thread_id=existing_thread_id)
query2 = "What was the last city I asked about?"
print(f"User: {query2}")
result2 = await agent.run(query2, thread=thread)
result2 = await agent2.run(query2, thread=thread)
print(f"Agent: {result2.text}")
print("Note: The agent continues the conversation from the previous thread.\n")
finally:
if assistant_id:
await client.beta.assistants.delete(assistant_id)
async def main() -> None:
print("=== OpenAI Assistants Chat Client Agent Thread Management Examples ===\n")
print("=== OpenAI Assistants Provider Thread Management Examples ===\n")
await example_with_automatic_thread_creation()
await example_with_thread_persistence()