Arnês de agente

Uma estrutura de suporte do agente é a base que transforma um modelo de linguagem num agente capaz de executar tarefas concretas. Um modelo isolado só pode gerar texto. Para chamar ferramentas, executar tarefas em várias etapas, lembrar-se do que já fez e continuar até a tarefa estar concluída, é necessário um runtime à volta do modelo — e esse runtime é o harness.

Um harness controla o agente: executa o ciclo que chama o modelo e executa as ferramentas que o modelo solicita, gere o histórico de conversas e o contexto para que o modelo se mantenha dentro dos seus limites, aplica políticas de aprovação e segurança antes de serem tomadas ações, e mantém o agente a progredir para a conclusão da tarefa. Assistentes de codificação e agentes autónomos são todos construídos sobre algum tipo de harness — é o motor envolvido no modelo.

O Agent Framework fornece um arnês pronto para que não tenha de construir este andaime sozinho. É um agente opinativo, com baterias, que envolve um cliente de chat com um pipeline agente completo — invocação de funções, gestão de contexto e um conjunto selecionado de ferramentas e fornecedores — ajustado para trabalhos autónomos e de longa duração, como investigação, programação, análise de dados e automação geral de tarefas.

Continuas a fornecer o teu próprio cliente de chat e só configuras as partes que queres alterar. Tudo o resto tem um padrão sensato que podes desativar ou personalizar.

Internamente, o harness do Agent Framework é um agente baseado em cliente de chat (Agentem Python e ChatClientAgent em C#) com um conjunto de funcionalidades do Agent Framework adicionadas. Todas estas funcionalidades estão também disponíveis como funcionalidades autónomas no Agent Framework.

O que compõe o harness do Agent Framework

O Agent Framework reúne as seguintes capacidades num único agente. Cada um está ativado por defeito (a menos que seja indicado como opcional) e pode ser desativado ou personalizado individualmente.

Capacidade Description
Invocação de função Ciclo automático de chamada de ferramentas com limite de iteração configurável.
Persistência do histórico de chamadas por serviço O histórico de chat é guardado após cada chamada individual ao modelo, permitindo a recuperação após falha e a inspeção durante a execução.
Compactação A compactação contexto-janela impede que longos ciclos de chamada de ferramentas sobrecarreguem a janela de contexto. Ativo quando é fornecido um orçamento de tokens (ou uma estratégia personalizada).
Fornecedor de todo Uma lista persistente de tarefas que o agente usa para acompanhar planos de várias etapas.
Provedor do modo de agente Rastreio dos modos planear/executar/personalizado, que estruturam a forma de funcionamento do agente.
Fornecedor de memória de ficheiros Memória de sessão baseada em ficheiros para notas e artefactos que persistem ao longo dos turnos.
Fornecedor de acesso a ficheiros Ferramentas para ler/escrever ficheiros limitadas a um diretório de trabalho.
Aprovação de ferramentas Regras permanentes de aprovação de “Não voltar a perguntar” e autoaprovação heurística para execução segura e não assistida.
OpenTelemetria Observabilidade incorporada seguindo as convenções semânticas da IA generativa.
Pesquisa na Web Uma ferramenta de pesquisa na Web hospedada, adicionada por predefinição.
Fornecedor de competências(opcional) Descobre e carrega progressivamente as Competências do Agente a partir do sistema de ficheiros.
Agentes de fundo(opcional) Delegar trabalho paralelo a subagentes de fundo.
Ambiente de shell(opcional) Execução de comandos de shell e deteção do SO, da shell e do diretório de trabalho.
Looping(opcional) Voltar a invocar o agente até que uma condição de conclusão seja satisfeita.

Criar um agente do Harness

O arnês é exposto como a HarnessAgent classe no Microsoft.Agents.AI namespace (o Microsoft.Agents.AI.Harness pacote). A forma mais simples de criar um é a partir de qualquer IChatClient usando o AsHarnessAgent método de extensão:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

// chatClient is any IChatClient implementation (Foundry, Azure OpenAI, OpenAI, Anthropic, ...).
AIAgent agent = chatClient.AsHarnessAgent();

AgentResponse response = await agent.RunAsync("Plan a weekend trip to Seattle.");
Console.WriteLine(response.Text);

Também pode construir o agente diretamente:

AIAgent agent = new HarnessAgent(chatClient);

Forneça um(a) HarnessAgentOptions para fornecer instruções e ferramentas. As instruções ao nível do arnês (HarnessAgentOptions.HarnessInstructions) descrevem orientações gerais de funcionamento, enquanto as instruções específicas da tarefa ficam em ChatOptions.Instructions. O HarnessAgent é fornecido com instruções predefinidas ao nível da infraestrutura de teste (HarnessAgent.DefaultInstructions), mas pode substituí-las pelas suas, através de HarnessAgentOptions.HarnessInstructions.

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    Name = "research-agent",
    ChatOptions = new ChatOptions
    {
        Instructions = "You are a research assistant focused on academic sources.",
        Tools = [AIFunctionFactory.Create(GetStockPrice)],
    },
});

Permitir a compactação

A compactação impede que ciclos longos de invocação de ferramentas excedam a janela de contexto. Quando não se utiliza o histórico de chat armazenado por inference-service, o padrão InMemoryChatHistoryProvider também é fornecido pelo mesmo fornecedor de compactação, de modo que o histórico de chat armazenado na sessão também seja compactado. Forneça tanto um tamanho máximo de janela de contexto como um tamanho máximo de saída para permitir a estratégia padrão consciente do orçamento dos tokens:

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    MaxContextWindowTokens = 128_000,
    MaxOutputTokens = 16_384,
});

Para usar a sua própria estratégia, defina HarnessAgentOptions.CompactionStrategy; para desligar a compactação, defina DisableCompaction = true.

Personalização e desativação de funcionalidades

Cada funcionalidade predefinida tem uma opção correspondente para a desativar em HarnessAgentOptions, para que possa manter o pipeline que pretende e descartar as restantes:

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    HarnessInstructions = "Custom operating guidelines here.",
    DisableTodoProvider = true,      // No todo list
    DisableAgentModeProvider = true, // No plan/execute modes
    DisableWebSearch = true,         // No hosted web search tool
    DisableFileMemory = true,        // No file-based session memory
});

Outros flags incluem DisableFileAccess, DisableAgentSkillsProvider, DisableToolAutoApproval, e DisableOpenTelemetry. Também pode adicionar os seus próprios fornecedores de contexto através de AIContextProviders e apontar o fornecedor de competências para localizações personalizadas através de AgentSkillsSource.

Looping até terminar

Por defeito, o arnês funciona uma vez por invocação. Forneça uma ou mais instâncias de LoopEvaluator para reinvocar automaticamente o agente até que os avaliadores decidam que o processo está concluído (por exemplo, quando aparece um marcador de conclusão, se verifica um predicado ou um avaliador de IA aprova):

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    LoopEvaluators = [new CompletionMarkerLoopEvaluator("DONE")],
});

O ciclo é aplicado como o decorador Agent mais exterior, pelo que cada iteração constitui uma execução de agente completa, independente, aprovada pelas ferramentas e rastreada.

Agentes de shell e em segundo plano

Para permitir que o agente execute comandos shell, passe um ShellExecutor. Isto adiciona uma ferramenta de execução de shell sujeita a aprovação e um provedor que injeta informação sobre o sistema operativo, a shell e o diretório de trabalho no contexto:

using Microsoft.Agents.AI.Tools.Shell;

// A shell confined to a working directory. Commands require approval by default;
// the deny-list is a UX pre-filter, not a security boundary.
await using var shell = new LocalShellExecutor(new LocalShellExecutorOptions
{
    WorkingDirectory = workingDir,
    ConfineWorkingDirectory = true,
    Policy = new ShellPolicy(denyList: [@"\brm\s+-rf\b", @"\bsudo\b"]),
});

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    ShellExecutor = shell,
});

Para permitir a delegação paralela, passe um conjunto de agentes em segundo plano. O agente pode passar subtarefas para execução simultânea:

AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
    BackgroundAgents = [webSearchAgent, codeAgent],
});

Criar um agente do Harness

A infraestrutura é disponibilizada sob a forma da função de fábrica create_harness_agent, que cria um Agent totalmente configurado a partir de um cliente de chat. A forma mais simples requer apenas um cliente:

from agent_framework import create_harness_agent
from agent_framework.openai import OpenAIChatClient

agent = create_harness_agent(
    OpenAIChatClient(model="gpt-4o"),
)

session = agent.create_session()
response = await agent.run("Plan a weekend trip to Seattle.", session=session)
print(response.text)

As instruções gerais descrevem orientações gerais de funcionamento, enquanto as instruções específicas da tarefa são incluídas em agent_instructions. O harness inclui instruções predefinidas ao nível do harness (DEFAULT_HARNESS_INSTRUCTIONS), que pode substituir através de harness_instructions. Também pode fornecer ferramentas adicionais:

agent = create_harness_agent(
    client=client,
    name="research-agent",
    agent_instructions="You are a research assistant focused on academic sources.",
    tools=get_stock_price,
)

Permitir a compactação

A compactação impede que ciclos longos de invocação de ferramentas excedam a janela de contexto. Forneça tanto o tamanho máximo da janela de contexto do modelo como o tamanho máximo de saída para permitir as estratégias padrão conscientes do orçamento dos tokens:

agent = create_harness_agent(
    client=client,
    max_context_window_tokens=128_000,
    max_output_tokens=16_384,
)

Quando não é fornecido nenhum parâmetro de token nem uma estratégia personalizada, a compactação é automaticamente desativada. Para usar as suas próprias estratégias, passe before_compaction_strategy e/ou after_compaction_strategy; para desligar explicitamente a compactação, defina disable_compaction=True.

Personalização e desativação de funcionalidades

Cada funcionalidade predefinida tem um argumento nomeado correspondente disable_*, pelo que pode manter as partes que pretende e remover as restantes:

agent = create_harness_agent(
    client=client,
    harness_instructions="Custom operating guidelines here.",
    disable_todo=True,         # No todo list
    disable_mode=True,         # No plan/execute modes
    disable_web_search=True,   # No hosted web search tool
    disable_file_memory=True,  # No file-based session memory
)

Outros flags incluem disable_file_access, disable_tool_auto_approval, e disable_compaction. Pode apontar a descoberta de competências para locais personalizados skills_paths e adicionar os seus próprios fornecedores com context_providers.

Looping até terminar

Por defeito, o arnês funciona uma vez por invocação. Passe um predicado loop_should_continue para voltar a invocar o agente automaticamente até o predicado determinar que o processo terminou. Use loop_next_message para controlar o prompt para cada iteração subsequente e loop_max_iterations para limitar o número de passagens:

from agent_framework import create_harness_agent, todos_remaining

agent = create_harness_agent(
    client=client,
    loop_should_continue=todos_remaining(),
    loop_max_iterations=10,
)

O predicado é invocado com argumentos-chave (iteration, last_result, session, agent, e assim sucessivamente); todos_remaining reexecuta o agente enquanto a sua lista de tarefas ainda tem itens em aberto. Para escrever o seu próprio, aceite esses argumentos de palavras-chave — por exemplo, lambda *, last_result, **kwargs: "DONE" not in last_result.text.

Agentes de shell e em segundo plano

Para permitir que o agente execute comandos shell, passe um shell_executor (por exemplo, LocalShellTool de agent-framework-tools). Isto adiciona uma ferramenta de execução de shell com controlo de aprovação, além de um fornecedor que sonda o sistema operativo e o ambiente da shell. O chamador é responsável pelo ciclo de vida do executante:

from agent_framework_tools.shell import LocalShellTool, ShellPolicy

# A shell confined to a working directory. Commands require approval by default;
# the deny-list is a UX pre-filter, not a security boundary.
async with LocalShellTool(
    workdir="./working",
    confine_workdir=True,
    policy=ShellPolicy(denylist=[r"\brm\s+-rf\b", r"\bsudo\b"]),
) as shell:
    agent = create_harness_agent(
        client=client,
        shell_executor=shell,
    )

Para permitir a delegação paralela, forneça uma sequência de agentes em segundo plano. O agente pode passar subtarefas para execução simultânea:

agent = create_harness_agent(
    client=client,
    background_agents=[web_search_agent, code_agent],
)

Note

O suporte da Go para arnês de agente está a chegar em breve. Consulte o repositório Agent Framework Go para o estado mais recente.

Planeia e executa o fluxo de trabalho

O fornecedor do modo agente permite um estilo de trabalho em duas fases que se combina naturalmente com a lista de tarefas:

  1. Modo de planeamento — interativo. O agente faz perguntas esclarecedoras, elabora uma lista de tarefas e um plano, e obtém a sua aprovação antes de realizar trabalhos significativos.
  2. Modo de execução — autónomo. O agente vai tratando da lista de tarefas de forma independente, reportando o progresso à medida que vai avançando.

Embora o fornecedor de modos venha com modos de planear e executar como modos padrão, estes podem ser substituídos por outros modos e instruções personalizadas para cada modo, se necessário.

Um exemplo de UX terminal

O arnês dá-te um agente capaz, mas não determina como as pessoas interagem com ele. Para demonstrar a infraestrutura de ponta a ponta, incluímos uma interface de utilizador de terminal de exemplo — uma consola interativa (TUI) que apresenta em fluxo contínuo a saída do agente, mostra a sua lista de tarefas e o modo atual, apresenta pedidos de aprovação de ferramentas e suporta comandos com barra, como /todos, /mode e /exit.

Importante

Estes projetos de consola são exemplos, não fazem parte do framework lançado. São intencionalmente autocontidos para que possas executá-los tal como estão para explorar a infraestrutura, ou copiá-los para o teu próprio projeto como ponto de partida para construíres a tua própria experiência de terminal.

A aplicação de consola de exemplo do .NET é o projeto Harness.Shared.Console. O seu ponto de entrada é HarnessConsole.RunAgentAsync, levando o seu agente, um prompt provisório e um opcional HarnessConsoleOptions (observadores, manipuladores de comandos com barra, cores de modo):

using Harness.Shared.Console;

await HarnessConsole.RunAgentAsync(agent, userPrompt: "Ask me anything to get started.");

Personalize-o com os seus próprios observadores, formatadores de ferramentas e manipuladores de comandos — ou crie uma derivação como base para a sua própria experiência de terminal. Veja os exemplos do harness .NET.

A consola de exemplo em Python é o pacote console ao lado dos exemplos do harness. O seu ponto de entrada é run_agent_async, que executa uma aplicação baseada em texto:

from console import run_agent_async

await run_agent_async(agent)

Está organizado em torno de observadores, componentes da interface do utilizador e comandos com barra, todos extensíveis através das classes base ConsoleObserver, ToolCallFormatter e CommandHandler (dependem de textual e rich). Executa-o tal como está, ou copia-o para servir de base à tua própria experiência de terminal. Veja os exemplos de harness em Python.

Passos seguintes

Aprofunde-se