Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Os fornecedores de contexto correm em torno de cada invocação para adicionar contexto antes da execução e processar os dados após a execução.
Observação
Para uma lista de fornecedores de contexto pré-construídos que pode usar com o seu agente, veja Integrações com fornecedores de contexto.
Padrão incorporado
Configure fornecedores utilizando opções do construtor ao criar um agente.
AIContextProvider é o ponto de extensão incorporado para enriquecimento de memória/contexto.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.AsAIAgent(new ChatClientAgentOptions()
{
ChatOptions = new() { Instructions = "You are a helpful assistant." },
AIContextProviders = [
new MyCustomMemoryProvider()
],
});
AgentSession session = await agent.CreateSessionAsync();
Console.WriteLine(await agent.RunAsync("Remember my name is Alice.", session));
Tip
Para uma lista de implementações pré-construídas AIContextProvider , veja Integrações com fornecedores de contexto.
O padrão habitual é configurar os provedores através de context_providers=[...] ao criar um agente.
InMemoryHistoryProvider é o fornecedor de histórico incorporado utilizado para memória conversacional local.
from agent_framework import Agent, InMemoryHistoryProvider
from agent_framework.openai import OpenAIChatClient
agent = Agent(
client=OpenAIChatClient(),
name="MemoryBot",
instructions="You are a helpful assistant.",
context_providers=[InMemoryHistoryProvider("memory", load_messages=True)],
)
session = agent.create_session()
await agent.run("Remember that I prefer vegetarian food.", session=session)
RawAgent Pode adicionar InMemoryHistoryProvider() automaticamente com o ID "in_memory" de origem predefinido em casos específicos, mas adicioná-lo explicitamente quando quiser um comportamento determinístico da memória local.
Memória suportada por ficheiros entre sessões
Use FileMemoryProvider quando o modelo decidir o que armazenar e recolher através de file_memory_* ferramentas. Em Python, omitir scope deriva a pasta de trabalho a partir do ID da sessão atual, por isso sessões separadas não partilham ficheiros de memória. Passe um estável scope, como um identificador de utilizador, para partilhar os mesmos ficheiros de memória entre sessões, e escolha uma AgentFileStore implementação para o armazenamento de backup.
# 1. Create the file store the provider will use to persist memory files.
# Here we use a file-system backed store rooted at a local
# ``agent-file-memory`` folder, but any AgentFileStore implementation can
# be used, e.g. InMemoryAgentFileStore or a custom blob-backed store.
memory_root = Path(__file__).parent / "agent-file-memory"
store = FileSystemAgentFileStore(memory_root)
# 2. Create the FileMemoryProvider over that store.
# The ``scope`` determines the scope and lifetime of the memories:
# - A stable scope, like the per-user one below, gives durable memories
# shared by every session for that user. That is what allows the second
# conversation further down to recall what the user said in the first.
# - Omitting ``scope`` (the default) isolates memories to a single session
# (the working folder is derived from the session id).
file_memory_provider = FileMemoryProvider(store, scope=f"users/{USER_ID}")
# 3. Attach the provider to the agent so it gets the file_memory_* tools.
agent = Agent(
client=client,
name="TravelAssistant",
instructions=(
"You are a helpful travel assistant. Remember what the user tells you about "
"themselves so that you can give better recommendations later."
),
context_providers=[file_memory_provider],
)
Configure os fornecedores através de agent.Config.ContextProviders ao criar um agente. Os fornecedores de contexto injetam contexto adicional antes de cada execução do agente e podem persistir o estado após cada execução.
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Config: agent.Config{
ContextProviders: []agent.ContextProvider{provider},
},
})
Use fornecedores de contexto com o Harness Agent
Os padrões manuais acima anexam apenas os fornecedores que escolher. O Harness Agent monta um conjunto de fornecedores ordenado quando este é criado. Use as opções de construção de cada SDK para desativar ou substituir os predefinidos e adicionar fornecedores adicionais.
HarnessAgent ativa TodoProvider, AgentModeProvider, FileMemoryProvider, e AgentSkillsProvider por defeito. Adiciona fornecedores a partir HarnessAgentOptions.AIContextProviders desses integrados.
HarnessAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
AIContextProviders = [new MyCustomMemoryProvider()],
DisableAgentSkillsProvider = true,
});
Use DisableTodoProvider, DisableAgentModeProvider, DisableFileMemory, e DisableAgentSkillsProvider para remover os defaults. Configure o modo e as competências com AgentModeProviderOptions e AgentSkillsSource; substitua o armazenamento de memória de ficheiros por FileMemoryStore. O acesso ao ficheiro é opt-in através FileAccessStore de e FileAccessProviderOptions, e a delegação em segundo plano é opt-in através BackgroundAgents de e BackgroundAgentsProviderOptions.
AsHarnessAgent(options) e new HarnessAgent(chatClient, options) aceitam o mesmo HarnessAgentOptions.
create_harness_agent ordena primeiro o fornecedor de histórico, depois compactação pós-execução quando ativada, seguida dos fornecedores de todo, modo e memória de ficheiros. A memória de ficheiros está ativada por defeito; Competências, acesso a ficheiros, agentes de fundo e contexto do shell são opt-in. Os prestadores que passaram context_providers= são anexados por último.
agent = create_harness_agent(
client,
context_providers=[UserPreferenceProvider()],
disable_mode=True,
skills_paths=["./skills"],
)
Use history_provider, , e mode_provider para substituir esses predefinidos, por disable_todo, disable_mode, e disable_file_memorytodo_providercomo exclusão. Use file_memory_store para substituir a loja padrão {cwd}/agent-file-memory . Ativar fornecedores opcionais com file_access_store, skills_provider ou skills_paths, background_agents, e shell_executor; os seus parâmetros de configuração relacionados configurar permissões, instruções e comportamento ambiental.
O Harness Agent não está atualmente disponível no Go SDK. Adicionar fornecedores de contexto explicitamente através de agent.Config.ContextProviders.
Fornecedor de contexto personalizado
Usa fornecedores de contexto personalizados quando precisares de injetar instruções/mensagens/ferramentas dinâmicas ou extrair estado após as execuções.
A classe base para fornecedores de contexto é Microsoft.Agents.AI.AIContextProvider.
Os fornecedores de contexto participam no pipeline do agente, têm a capacidade de contribuir ou substituir mensagens de entrada do agente e podem extrair informações de novas mensagens.
AIContextProvider tem vários métodos virtuais que podem ser ultrapassados para implementar o seu próprio fornecedor de contexto personalizado.
Consulte as diferentes opções de implementação abaixo para mais informações sobre o que pode ser substituído.
AIContextProvider Estado
Uma AIContextProvider instância está associada a um agente e a mesma instância seria usada para todas as sessões.
Isto significa que o AIContextProvider não deve armazenar nenhum estado específico da sessão na instância do provedor.
O AIContextProvider pode ter uma referência a um cliente do serviço de memória num campo, mas não deve ter um id para o conjunto específico de memórias num campo.
Em vez disso, o AIContextProvider pode armazenar quaisquer valores específicos da sessão, como IDs de memória, mensagens ou qualquer outra coisa relevante no AgentSession. Todos os métodos virtuais em AIContextProvider recebem uma referência ao atual AIAgent e AgentSession.
Para permitir o armazenamento fácil do estado tipado no AgentSession, é fornecida uma classe utilitária:
// First define a type containing the properties to store in state
internal class MyCustomState
{
public string? MemoryId { get; set; }
}
// Create the helper
var sessionStateHelper = new ProviderSessionState<MyCustomState>(
// stateInitializer is called when there is no state in the session for this AIContextProvider yet
stateInitializer: currentSession => new MyCustomState() { MemoryId = Guid.NewGuid().ToString() },
// The key under which to store state in the session for this provider. Make sure it does not clash with the keys of other providers.
stateKey: this.GetType().Name,
// An optional jsonSerializerOptions to control the serialization/deserialization of the custom state object
jsonSerializerOptions: myJsonSerializerOptions);
// Using the helper you can read state:
MyCustomState state = sessionStateHelper.GetOrInitializeState(session);
Console.WriteLine(state.MemoryId);
// And write state:
sessionStateHelper.SaveState(session, state);
Implementação simples AIContextProvider
A implementação AIContextProvider simples normalmente sobrepõe-se a dois métodos:
- AIContextProvider.ProvideAIContextAsync - Carregar dados relevantes e devolver instruções, mensagens ou ferramentas adicionais.
- AIContextProvider.StoreAIContextAsync - Extrair quaisquer dados relevantes de novas mensagens e armazenar.
Aqui está um exemplo de um simples AIContextProvider que se integra com um serviço de memória.
internal sealed class SimpleServiceMemoryProvider : AIContextProvider
{
private readonly ProviderSessionState<State> _sessionState;
private readonly ServiceClient _client;
public SimpleServiceMemoryProvider(ServiceClient client, Func<AgentSession?, State>? stateInitializer = null)
: base(null, null)
{
this._sessionState = new ProviderSessionState<State>(
stateInitializer ?? (_ => new State()),
this.GetType().Name);
this._client = client;
}
public override string StateKey => this._sessionState.StateKey;
protected override ValueTask<AIContext> ProvideAIContextAsync(InvokingContext context, CancellationToken cancellationToken = default)
{
var state = this._sessionState.GetOrInitializeState(context.Session);
if (state.MemoriesId == null)
{
// No stored memories yet.
return new ValueTask<AIContext>(new AIContext());
}
// Find memories that match the current user input.
var memories = this._client.LoadMemories(state.MemoriesId, string.Join("\n", context.AIContext.Messages?.Select(x => x.Text) ?? []));
// Return a new message that contains the text from any memories that were found.
return new ValueTask<AIContext>(new AIContext
{
Messages = [new ChatMessage(ChatRole.User, "Here are some memories to help answer the user question: " + string.Join("\n", memories.Select(x => x.Text)))]
});
}
protected override async ValueTask StoreAIContextAsync(InvokedContext context, CancellationToken cancellationToken = default)
{
var state = this._sessionState.GetOrInitializeState(context.Session);
// Create a memory container in the service for this session
// and save the returned id in the session.
state.MemoriesId ??= this._client.CreateMemoryContainer();
this._sessionState.SaveState(context.Session, state);
// Use the service to extract memories from the user input and agent response.
await this._client.StoreMemoriesAsync(state.MemoriesId, context.RequestMessages.Concat(context.ResponseMessages ?? []), cancellationToken);
}
public class State
{
public string? MemoriesId { get; set; }
}
}
Implementação avançada AIContextProvider
Uma implementação mais avançada poderia optar por sobrepor os seguintes métodos:
- AIContextProvider.InvokingCoreAsync - Chamado antes do agente invocar o LLM e permitir a modificação da lista de mensagens de pedido, ferramentas e instruções.
- AIContextProvider.InvokedCoreAsync - Chamado depois de o agente ter invocado o LLM e permite o acesso a todas as mensagens de pedido e resposta.
AIContextProvider fornece implementações base de InvokingCoreAsync e InvokedCoreAsync.
A InvokingCoreAsync implementação base faz o seguinte:
- Filtra a lista de mensagens de entrada apenas para mensagens passadas ao agente pelo chamador. Tenha em atenção que este filtro pode ser substituído através do parâmetro
provideInputMessageFilterno construtorAIContextProvider. - chamadas
ProvideAIContextAsynccom as mensagens de pedido filtradas, ferramentas e instruções existentes. - carimba todas as mensagens devolvidas por
ProvideAIContextAsynccom informação de origem, indicando que estas mensagens provêm deste fornecedor de contexto. - funde as mensagens, ferramentas e instruções devolvidas por
ProvideAIContextAsynccom as existentes, para produzir a entrada que será usada pelo agente. Mensagens, ferramentas e instruções são adicionadas às existentes.
A InvokedCoreAsync base faz o seguinte:
- verifica se a execução falhou e, em caso afirmativo, retorna sem fazer mais nenhum processamento.
- Filtra a lista de mensagens de entrada apenas para mensagens passadas ao agente pelo chamador. Tenha em atenção que este filtro pode ser substituído através do parâmetro
storeInputMessageFilterno construtorAIContextProvider. - Passa as mensagens de pedido filtradas e todas as mensagens de resposta para
StoreAIContextAsyncarmazenamento.
É possível sobrepor estes métodos para implementar um AIContextProvider, no entanto, isso requer que o implementador realize ele mesmo a funcionalidade base de forma apropriada.
Aqui está um exemplo de tal implementação.
internal sealed class AdvancedServiceMemoryProvider : AIContextProvider
{
private readonly ProviderSessionState<State> _sessionState;
private readonly ServiceClient _client;
public AdvancedServiceMemoryProvider(ServiceClient client, Func<AgentSession?, State>? stateInitializer = null)
: base(null, null)
{
this._sessionState = new ProviderSessionState<State>(
stateInitializer ?? (_ => new State()),
this.GetType().Name);
this._client = client;
}
public override string StateKey => this._sessionState.StateKey;
protected override async ValueTask<AIContext> InvokingCoreAsync(InvokingContext context, CancellationToken cancellationToken = default)
{
var state = this._sessionState.GetOrInitializeState(context.Session);
if (state.MemoriesId == null)
{
// No stored memories yet.
return new AIContext();
}
// We only want to search for memories based on user input, and exclude chat history or other AI context provider messages.
var filteredInputMessages = context.AIContext.Messages?.Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External);
// Find memories that match the current user input.
var memories = this._client.LoadMemories(state.MemoriesId, string.Join("\n", filteredInputMessages?.Select(x => x.Text) ?? []));
// Create a message for the memories, and stamp it to indicate where it came from.
var memoryMessages =
[new ChatMessage(ChatRole.User, "Here are some memories to help answer the user question: " + string.Join("\n", memories.Select(x => x.Text)))]
.Select(m => m.WithAgentRequestMessageSource(AgentRequestMessageSourceType.AIContextProvider, this.GetType().FullName!));
// Return a new merged AIContext.
return new AIContext
{
Instructions = context.AIContext.Instructions,
Messages = context.AIContext.Messages.Concat(memoryMessages),
Tools = context.AIContext.Tools
};
}
protected override async ValueTask InvokedCoreAsync(InvokedContext context, CancellationToken cancellationToken = default)
{
if (context.InvokeException is not null)
{
return;
}
var state = this._sessionState.GetOrInitializeState(context.Session);
// Create a memory container in the service for this session
// and save the returned id in the session.
state.MemoriesId ??= this._client.CreateMemoryContainer();
this._sessionState.SaveState(context.Session, state);
// We only want to store memories based on user input and agent output, and exclude messages from chat history or other AI context providers to avoid feedback loops.
var filteredRequestMessages = context.RequestMessages.Where(m => m.GetAgentRequestMessageSourceType() == AgentRequestMessageSourceType.External);
// Use the service to extract memories from the user input and agent response.
await this._client.StoreMemoriesAsync(state.MemoriesId, filteredRequestMessages.Concat(context.ResponseMessages ?? []), cancellationToken);
}
public class State
{
public string? MemoriesId { get; set; }
}
}
from typing import Any
from agent_framework import AgentSession, ContextProvider, SessionContext
class UserPreferenceProvider(ContextProvider):
def __init__(self) -> None:
super().__init__("user-preferences")
async def before_run(
self,
*,
agent: Any,
session: AgentSession,
context: SessionContext,
state: dict[str, Any],
) -> None:
if favorite := state.get("favorite_food"):
context.extend_instructions(self.source_id, f"User's favorite food is {favorite}.")
async def after_run(
self,
*,
agent: Any,
session: AgentSession,
context: SessionContext,
state: dict[str, Any],
) -> None:
for message in context.input_messages:
text = (message.text or "") if hasattr(message, "text") else ""
if isinstance(text, str) and "favorite food is" in text.lower():
state["favorite_food"] = text.split("favorite food is", 1)[1].strip().rstrip(".")
Observação
ContextProvider e HistoryProvider são as classes base canónicas de Python.
Os fornecedores de contexto também podem adicionar middleware de chat ou função para a invocação atual, chamando context.extend_middleware(self.source_id, middleware). O agente achata essas adições com context.get_middleware() e aplica-as na ordem do fornecedor antes de invocar o cliente de chat.
Seleção dinâmica de ferramentas
Os fornecedores de contexto podem adicionar ferramentas para a invocação atual com context.extend_tools(self.source_id, tools). Para o carregamento progressivo de ferramentas durante um ciclo de invocação de funções, consulte o exemplo dynamic_tool_exposure. Para pacotes de ferramentas geridas, veja Microsoft Foundry Toolbox.
Fornecedor de histórico personalizado
Os fornecedores de histórico são fornecedores de contexto especializados para carregar/armazenar mensagens.
from collections.abc import Sequence
from typing import Any
from agent_framework import HistoryProvider, Message
class DatabaseHistoryProvider(HistoryProvider):
def __init__(self, db: Any) -> None:
super().__init__("db-history", load_messages=True)
self._db = db
async def get_messages(
self,
session_id: str | None,
*,
state: dict[str, Any] | None = None,
**kwargs: Any,
) -> list[Message]:
key = (state or {}).get("history_key", session_id or "default")
rows = await self._db.load_messages(key)
return [Message.from_dict(row) for row in rows]
async def save_messages(
self,
session_id: str | None,
messages: Sequence[Message],
*,
state: dict[str, Any] | None = None,
**kwargs: Any,
) -> None:
if not messages:
return
if state is not None:
key = state.setdefault("history_key", session_id or "default")
else:
key = session_id or "default"
await self._db.save_messages(key, [m.to_dict() for m in messages])
Importante
Em Python, podes configurar vários fornecedores de histórico, mas só um deve usar load_messages=True.
Utilize prestadores adicionais para diagnósticos/avaliações com load_messages=False e store_context_messages=True para que capturem o contexto de outros prestadores em conjunto com a entrada/saída.
Se precisar que a história local persista em torno de cada chamada de modelo num ciclo de ferramentas, veja Armazenamento.
Exemplo de padrão:
primary = DatabaseHistoryProvider(db)
audit = InMemoryHistoryProvider("audit", load_messages=False, store_context_messages=True)
agent = Agent(client=OpenAIChatClient(), context_providers=[primary, audit])
Defina um fornecedor de contexto personalizado com um Provide callback:
import (
"context"
"github.com/microsoft/agent-framework-go/agent"
"github.com/microsoft/agent-framework-go/message"
)
provider := agent.NewContextProvider(agent.ContextProviderConfig{
SourceID: "user_memory",
Provide: func(ctx context.Context, invoking agent.InvokingContext) ([]*message.Message, []agent.Option, error) {
return nil, []agent.Option{agent.WithInstructions("User prefers short answers.")}, nil
},
})
Os fornecedores de contexto podem ler e escrever o estado da sessão:
Provide: func(ctx context.Context, invoking agent.InvokingContext) ([]*message.Message, []agent.Option, error) {
session, _ := agent.GetOption(invoking.Options, agent.WithSession)
var state MyState
_, _ = session.Get("my_key", &state)
return nil, nil, nil
},
Store: func(ctx context.Context, invoked agent.InvokedContext) error {
session, _ := agent.GetOption(invoked.Options, agent.WithSession)
session.Set("my_key", updatedState)
return nil
},