Microsoft代理框架提供内置支持,用于管理与 AI 代理的多轮次对话。 这包括维护跨多个交互的上下文。 用于生成代理的不同代理类型和基础服务可能支持不同的线程类型,代理框架将这些差异抽象化,为开发人员提供一致的接口。
例如,使用基于 Foundry 代理的 ChatClientAgent 时,会话历史记录将保留在服务中。 虽然使用基于 gpt-4.1 聊天完成的 ChatClientAgent 时,对话历史记录是由代理在内存中管理的。
基础线程模型之间的差异通过 AgentThread 类型抽象化。
AgentThread 创建
AgentThread 可以通过两种方式创建实例:
- 在代理上调用
GetNewThread。 - 在运行代理时不提供
AgentThread。 在这种情况下,代理将创建一个带有基础线程的临时AgentThread,该线程仅在运行期间使用。
某些底层线程可能在底层服务中持续创建,当服务需要此类功能时,例如 Foundry 代理或 OpenAI 响应。 这些线程的任何清理或删除都是用户的责任。
// Create a new thread.
AgentThread thread = agent.GetNewThread();
// Run the agent with the thread.
var response = await agent.RunAsync("Hello, how are you?", thread);
// Run an agent with a temporary thread.
response = await agent.RunAsync("Hello, how are you?");
AgentThread 存储
AgentThread 实例可以序列化并存储以供以后使用。 这允许在不同会话或服务调用之间保留会话上下文。
对于会话历史记录存储在服务中的情况,序列化 AgentThread 将包含服务中线程的 ID。
对于会话历史记录在内存中管理的情况,序列化 AgentThread 将包含消息本身。
// Create a new thread.
AgentThread thread = agent.GetNewThread();
// Run the agent with the thread.
var response = await agent.RunAsync("Hello, how are you?", thread);
// Serialize the thread for storage.
JsonElement serializedThread = await thread.SerializeAsync();
// Deserialize the thread state after loading from storage.
AgentThread resumedThread = await agent.DeserializeThreadAsync(serializedThread);
// Run the agent with the resumed thread.
var response = await agent.RunAsync("Hello, how are you?", resumedThread);
Microsoft代理框架提供内置支持,用于管理与 AI 代理的多轮次对话。 这包括维护跨多个交互的上下文。 用于生成代理的不同代理类型和基础服务可能支持不同的线程类型,并且 Agent Framework 会将这些差异抽象化,为开发人员提供一致的接口。
例如,使用 ChatAgent 基于 Foundry 代理的会话历史记录将保留在服务中。 当使用基于 ChatAgent 的 gpt-4 聊天完成时,对话历史记录存储在内存中并由代理托管。
基础线程模型之间的差异通过 AgentThread 类型抽象化。
Agent/AgentThread 关系
AIAgent 实例是无状态的,同一代理实例可以与多个 AgentThread 实例一起使用。
但并非所有代理都支持所有线程类型。 例如,如果您使用 ChatClientAgent 响应服务,则由此代理创建的 AgentThread 实例将无法与使用 Foundry 代理服务的 ChatClientAgent 一同工作。
这是因为这些服务都支持在服务中保存会话历史记录,并且 AgentThread 只保留对此服务托管线程的引用。
因此,使用由一个代理创建的 AgentThread 实例与不同的代理实例一起使用是不安全的,除非你了解基础线程模型及其影响。
服务/协议的线程支持
| 服务 | 线程支持 |
|---|---|
| 铸造剂 | 服务托管持久线程 |
| OpenAI 响应 | 服务托管持久线程或内存中线程 |
| OpenAI ChatCompletion (聊天完成工具) | 内存中线程 |
| OpenAI 助手 | 服务托管线程 |
| A2A | 服务托管线程 |
AgentThread 创建
AgentThread 可以通过两种方式创建实例:
- 在代理上调用
get_new_thread()。 - 在运行代理时不提供
AgentThread。 在这种情况下,代理将创建一个带有基础线程的临时AgentThread,该线程仅在运行期间使用。
某些基础线程可能在基础服务中永久创建,其中服务需要此服务,例如 Azure AI 代理或 OpenAI 响应。 这些线程的任何清理或删除都是用户的责任。
# Create a new thread.
thread = agent.get_new_thread()
# Run the agent with the thread.
response = await agent.run("Hello, how are you?", thread=thread)
# Run an agent with a temporary thread.
response = await agent.run("Hello, how are you?")
AgentThread 存储
AgentThread 实例可以序列化并存储以供以后使用。 这允许在不同会话或服务调用之间保留会话上下文。
对于会话历史记录存储在服务中的情况,序列化 AgentThread 将包含服务中线程的 ID。
对于会话历史记录在内存中管理的情况,序列化 AgentThread 将包含消息本身。
# Create a new thread.
thread = agent.get_new_thread()
# Run the agent with the thread.
response = await agent.run("Hello, how are you?", thread=thread)
# Serialize the thread for storage.
serialized_thread = await thread.serialize()
# Deserialize the thread state after loading from storage.
resumed_thread = await agent.deserialize_thread(serialized_thread)
# Run the agent with the resumed thread.
response = await agent.run("Hello, how are you?", thread=resumed_thread)
自定义消息存储
对于内存中线程,可以提供自定义消息存储实现来控制消息的存储和检索方式:
from agent_framework import AgentThread, ChatMessageStore, ChatAgent
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
class CustomStore(ChatMessageStore):
# Implement custom storage logic here
pass
# You can also provide a custom message store factory when creating the agent
def custom_message_store_factory():
return CustomStore() # or your custom implementation
async with AzureCliCredential() as credential:
agent = ChatAgent(
chat_client=AzureAIAgentClient(async_credential=credential),
instructions="You are a helpful assistant",
chat_message_store_factory=custom_message_store_factory
)
# Or let the agent create one automatically
thread = agent.get_new_thread()
# thread.message_store is not a instance of CustomStore
Agent/AgentThread 关系
Agents 是无状态的,同一个代理实例可以与多个 AgentThread 实例一起使用。
但并非所有代理都支持所有线程类型。 例如,如果您使用ChatAgent OpenAI 响应服务,并且此代理正在使用的 store=TrueAgentThread 实例将无法与使用 Azure AI 代理服务的 ChatAgent 兼容,因为 thread_ids 不兼容。
因此,使用由一个代理创建的 AgentThread 实例与不同的代理实例一起使用是不安全的,除非你了解基础线程模型及其影响。
实用多轮次示例
下面是一个完整示例,展示如何跨多个交互维护上下文:
from agent_framework import ChatAgent
from agent_framework.azure import AzureAIAgentClient
from azure.identity.aio import AzureCliCredential
async def multi_turn_example():
async with (
AzureCliCredential() as credential,
ChatAgent(
chat_client=AzureAIAgentClient(async_credential=credential),
instructions="You are a helpful assistant"
) as agent
):
# Create a thread for persistent conversation
thread = agent.get_new_thread()
# First interaction
response1 = await agent.run("My name is Alice", thread=thread)
print(f"Agent: {response1.text}")
# Second interaction - agent remembers the name
response2 = await agent.run("What's my name?", thread=thread)
print(f"Agent: {response2.text}") # Should mention "Alice"
# Serialize thread for storage
serialized = await thread.serialize()
# Later, deserialize and continue conversation
new_thread = await agent.deserialize_thread(serialized)
response3 = await agent.run("What did we talk about?", thread=new_thread)
print(f"Agent: {response3.text}") # Should remember previous context