Ganchos de agente

O Agent Hooks é uma funcionalidade de primeira classe do Agent Framework para aplicar controles de governança e runtime em pontos bem definidos na execução de um agente. Ele implementa o contrato AGENT-HOOKS-0.1 neutro da estrutura, de modo que mecanismos de política, gateways de aprovação, proteções orçamentárias, filtros de conteúdo e controles de saída podem ter como destino uma superfície de controle comum.

Important

Agent Hooks é um plano de controle, não um plano de telemetria. Cada interceptador retorna um veredicto. No enforce modo, a estrutura atua nesse veredito; no evaluate_only modo, registra o veredicto sem alterar a execução. Use observabilidade para rastreamento passivo, métricas e logs.

O Agent Hooks ainda não está disponível para .NET. Use o middleware do agente, a aprovação da ferramenta e a segurança do agente para adicionar controles de runtime aos agentes de .NET.

Agent Hooks é experimental em Python. A fábrica emite um ExperimentalWarning quando usado pela primeira vez e sua API pode ser alterada antes da disponibilidade geral.

Quando usar Agent Hooks

Use os Agent Hooks quando controles desenvolvidos de forma independente precisarem compartilhar um contrato único, compartilhado e aplicável em toda a entrada do agente, as chamadas ao modelo, as chamadas a ferramentas e a saída final.

Capacidade Use-o para
Ganchos de agente Decisões de política padronizadas, transformações, aprovações, orçamentos e controles de saída em todo o ciclo de vida do agente.
Middleware de agente Comportamento transversal específico da aplicação que não precisa do contrato do Agent Hooks nem de suas garantias centrais de execução.
Segurança do agente com o FIDES Políticas e rótulos determinísticos de fluxo de informações para conteúdo não confiável ou confidencial.
Aprovação da ferramenta Confirmação humana de chamadas individuais da ferramenta de função.
Observabilidade Rastros passivos, métricas e logs que não controlam a execução.

O que o Agent Framework impõe

Quando você adiciona o Agent Hooks a um agente, o Agent Framework aplica um limite de imposição coordenado entre execuções de agente, chamadas de modelo e chamadas de ferramenta. O runtime fornece as seguintes garantias:

  • Falha ao fechar: Uma negação bloqueia a ação protegida. Contextos inválidos, decisões inválidas, falhas no interceptor e falhas de aplicação não contornam os controles silenciosamente.
  • Transformação de gravação de retorno: Uma transformação altera as mensagens originais, os argumentos da ferramenta, os resultados da ferramenta ou a resposta final que a execução de fato usa. Se uma transformação não puder ser aplicada, a execução falhará.
  • Streaming com buffer: Nenhuma atualização da resposta é enviada ao chamador até que a resposta completa do modelo e a saída final passem pelos respectivos pontos de interceptação.
  • Persistência condicionada ao veredicto: A persistência aguarda o veredicto que a abrange. A persistência padrão após a execução aguarda output; a persistência do histórico por chamada de serviço aguarda cada post_model_call.
  • Concluir a instalação do pacote: As partes de agente, chat e função são instaladas como uma unidade, portanto, um limite de imposição incompleto não pode ser configurado acidentalmente.

O contrato é cooperativo, e não uma barreira de isolamento entre processos. Os interceptores são executados no processo do host e recebem o conteúdo necessário para tomar decisões. Registre apenas interceptores de sua confiança.

Instalar ganchos de agente

Instale o extra opcional agent-hooks para o pacote principal:

pip install "agent-framework-core[agent-hooks]"

Se você usar uv:

uv add "agent-framework-core[agent-hooks]"

A agent-hooks-sdk dependência é importada lentamente. A importação agent_framework não carrega o SDK, a menos que você crie um pacote de middleware do Agent Hooks.

Note

O agent-hooks extra intencionalmente não está incluído em agent-framework-core[all]. Instale-o explicitamente quando quiser habilitar essa superfície de controle experimental.

Adicionar um interceptor

Um interceptador recebe um agent_hooks.AgentContext (o mapeamento de contexto definido pela especificação, e não o agent_framework.AgentContext usado pelo middleware do agente) e retorna um veredito. O interceptador a seguir bloqueia a saída final que contém a palavra secret. O exemplo pressupõe client ser um cliente de chat do Agent Framework já configurado.

from agent_framework import Agent, create_agent_hooks_middleware
from agent_hooks import ALLOW, AgentContext, InterceptionBlocked, Verdict


class SecretEgressGuard:
    def intercept(self, context: AgentContext) -> Verdict:
        if (
            context["interception_point"] == "output"
            and "secret" in str(context["target"]).lower()
        ):
            return Verdict.deny(
                reason="secret_in_output",
                message="The final response contains restricted content.",
            )
        return ALLOW


hooks = create_agent_hooks_middleware(
    {"secret-egress": SecretEgressGuard()},
)

agent = Agent(
    client=client,
    instructions="You are a helpful assistant.",
    middleware=[hooks],
)

try:
    response = await agent.run("Summarize the account details.")
except InterceptionBlocked as exc:
    print(f"Blocked: {exc.result.verdict.reason}")

Passe o pacote como um elemento na lista middleware do agente. Instale exatamente um pacote do Agent Hooks em cada agente.

Pontos de interceptação

O Agent Framework emite automaticamente os pontos de interceptação aplicáveis:

Ponto de interceptação Quando é emitido Alvo da transformação
agent_startup Antes da primeira entrada de dados em uma sessão do Agent Hooks Não transformável
input Quando uma solicitação externa entra no agente Conteúdo e função de entrada
pre_model_call Antes de cada solicitação de modelo Mensagens enviadas para o modelo
post_model_call Após cada resposta completa do modelo Conteúdo da resposta, chamadas de ferramenta executadas pelo framework e razão de término
pre_tool_call Antes de cada invocação de ferramenta executada pelo framework Argumentos da ferramenta
post_tool_call Após uma ferramenta ter sucesso ou falhar Resultado da ferramenta
output Antes que a resposta final chegue ao chamador Conteúdo da resposta final
agent_shutdown Quando a sessão do Agent Hooks é concluída, falha ou é cancelada Não transformável

Uma execução que chama uma ferramenta normalmente emite:

agent_startup input → → pre_model_call → → post_model_callpre_tool_call → → post_tool_call → → post_model_callpre_model_call → → → outputagent_shutdown

Veredictos

O contrato tem três decisões: allow, denye transform. O SDK do Python também fornece funções auxiliares para avisos e negações passíveis de suspensão.

Resultado API de Python Behavior
Permitir ALLOW ou Verdict(decision=Decision.ALLOW) Continue com o alvo inalterado.
Permitir com aviso Verdict.warn(...) Continue e inclua o aviso no registro de interceptação.
Negar Verdict.deny(...) Bloqueie a ação protegida.
Negar aprovação pendente Verdict.escalate(...) Bloqueie a menos que o resolvedor de aprovação configurado retorne um veredicto de licença.
Transformar Verdict(decision=Decision.TRANSFORM, transform=Transform(...)) Reescreva um valor em $target, em seguida, continue com o valor reescrito.

O nível de execução e o nível do modelo nega o aumento InterceptionBlocked e impede que o resultado protegido atinja o chamador ou o próximo estágio. Em um ponto de integração da ferramenta, uma política de negação impede a ação da ferramenta ou descarta seu resultado e retorna ao modelo um erro de controle contendo o motivo da política, sem o payload do destino negado. Isso permite que o loop do agente continue. Uma falha no host ou na aplicação interrompe a execução.

Aplicar uma transformação

Um caminho de transformação deve começar em $target. Por exemplo, um interceptor pode substituir o conteúdo da resposta final:

from agent_hooks import ALLOW, AgentContext, Decision, Transform, Verdict


class OutputRedactor:
    def intercept(self, context: AgentContext) -> Verdict:
        if context["interception_point"] != "output":
            return ALLOW

        return Verdict(
            decision=Decision.TRANSFORM,
            reason="redacted_output",
            transform=Transform(
                path="$target.content",
                value="[Response removed by policy]",
            ),
        )

As transformações são aplicadas aos valores do Agent Framework Content, preservando o conteúdo avançado compatível em vez de reduzir cada valor a texto sem formatação. Um caminho malformado ou uma substituição incompatível falha ao fechar em vez de continuar com o valor original.

Aprovação da ferramenta e transformações de argumentos

A aprovação de ferramentas do Agent Framework e o ponto de extensão para aprovação do Agent Hooks são mecanismos separados. Para uma ferramenta de função com approval_mode="always_require", o Agent Framework cria a solicitação de aprovação humana antes da execução do middleware da função. Uma pre_tool_call transformação pode, portanto, alterar argumentos depois que o usuário aprovou os valores originais.

Aviso

Não transforme argumentos em ferramentas que usam approval_mode="always_require" em pre_tool_call. Transforme a chamada da ferramenta em post_model_call para que a solicitação de aprovação do framework contenha os valores transformados, ou retorne Verdict.escalate(...) em pre_tool_call e resolva a aprovação por meio de Agent Hooks resolver.

Streaming e persistência

O Agent Hooks mantém a API de streaming, mas usa semântica de saída em buffer. O Agent Framework monta a resposta completa do modelo, emite post_model_call, monta a resposta final do agente e emite output antes de liberar as atualizações. Se um dos pontos negar a resposta, o chamador não receberá atualizações parciais.

Esse comportamento troca a latência por token pela garantia de saída em modo de falha segura. Uma transformação de saída também se reflete nas atualizações liberadas ao chamador posteriormente.

A persistência é condicionada pelo ponto de interceptação que cobre a operação de persistência:

  • Por padrão, o histórico e outros trabalhos do provedor após a execução esperam pelo output veredicto. Uma saída negada não é mantida e uma transformação de saída é mantida após a transformação.
  • Quando você define require_per_service_call_history_persistence=True no construtor Agent ou em client.as_agent(...), cada troca de modelo é persistida depois que a decisão de post_model_call permitir isso. Uma negação posterior output não reverte esse histórico já permitido.
  • Para a persistência padrão após a execução, as tentativas de repetição ficam condicionadas à decisão final output. Em vez disso, o modo por chamada de serviço persiste cada resposta do modelo que passa por post_model_call.

Important

Se o conteúdo do modelo não deve se tornar persistente, aplique essa política em post_model_call quando require_per_service_call_history_persistence=True. Uma política apenas de saída protege o que chega ao chamador, mas não remove retroativamente as trocas com o modelo já permitidas e persistidas em post_model_call.

Sessões e registros de auditoria

Por padrão, cada execução de agente cria uma sessão do Agent Hooks. agent_startup e agent_shutdown delimitam a execução, e os registros recebem um ID de sessão com uma sequência monotonicamente crescente.

Use record_sink para receber cada InterceptionRecord:

records = []

hooks = create_agent_hooks_middleware(
    {"secret-egress": SecretEgressGuard()},
    record_sink=records.append,
)

Os registros de interceptação capturam a decisão, o motivo, o resumo do interceptor, o modo, a identidade e a sequência sem copiar a carga interceptada no registro de auditoria. O interceptor em si ainda recebe o contexto completo.

Cobrir várias execuções com uma única sessão

Use create_agent_hooks_middleware_from_emitter() quando o aplicativo mantém uma sessão do Agent Hooks de longa duração, como uma conversa com um registro de aprovações:

from agent_framework import Agent, create_agent_hooks_middleware_from_emitter
from agent_hooks import AgentContextBuilder, InterceptionEmitter


emitter = InterceptionEmitter().register(SecretEgressGuard())
builder = AgentContextBuilder(
    agent_id="support-agent",
    framework="agent-framework",
    session_id="conversation-42",
)

hooks = create_agent_hooks_middleware_from_emitter(emitter, builder)
agent = Agent(client=client, middleware=[hooks])

await emitter.emit(builder.agent_startup(tools_registered=[]))
await agent.run("First turn")
await agent.run("Second turn")
await emitter.emit(builder.agent_shutdown(reason="completed"))

Nessa forma, o aplicativo configura o emissor e é responsável pela inicialização, pelo encerramento e pela limpeza em caso de erro. O middleware emite os pontos por execução de input até output.

Configurar a imposição

create_agent_hooks_middleware() aceita os seguintes controles:

Parâmetro Purpose
interceptors Uma sequência de interceptadores ou um mapeamento de nome para interceptador. Pelo menos um é obrigatório.
resolver Resolve negações passíveis de reversão por meio de um canal de aprovação. Sem quem a resolva, a negação permanece em vigor.
mode "enforce" aplica veredictos. "evaluate_only" registra o que aconteceria, mas permite todas as ações.
composition Seleciona como vários veredictos de interceptador são combinados.
identity_provider Produz identidades de contexto associadas ao conteúdo. O padrão é "jcs-sha256".
timeout Tempo limite por interceptador e resolvedor para chamadas aguardadas. O padrão é cinco segundos. Um interceptor ou resolver síncrono que bloqueia o loop de eventos não pode ser interrompido por este tempo limite.
record_sink Recebe cada registro de interceptação sem payload.

A composição padrão é sequencial first_deny com aprovação configurada para interromper a dobra. Portanto, a ordem do interceptor é importante: coloque controles que sempre devem ser executados antes dos controles que podem solicitar aprovação. Consulte a lista de verificação de produção do Agent Hooks antes de selecionar outro perfil de composição.

Implantar com o modo apenas de avaliação

Use evaluate_only para medir o comportamento da política antes da imposição:

hooks = create_agent_hooks_middleware(
    {"secret-egress": SecretEgressGuard()},
    mode="evaluate_only",
    record_sink=records.append,
)

Nesse modo, os interceptores são executados e os registros incluem seus veredictos, mas nenhuma ação é bloqueada ou transformada. Não descreva uma implantação evaluate_only como governança imposta.

Regras de composição

Coloque o pacote primeiro na lista de middleware do agente, para que ele forme a camada de aplicação mais externa:

agent = Agent(
    client=client,
    middleware=[
        create_agent_hooks_middleware([SecretEgressGuard()]),
        application_middleware,
    ],
)

Siga estas regras:

  • Instale exatamente um pacote do Agent Hooks por agente. Os pacotes empilhados são rejeitados.
  • Mantenha o pacote intacto. Seu middleware para agente, chat e funções não pode ser instalado separadamente.
  • Instale o pacote em Agent, não diretamente em um cliente de chat nem por meio de um provedor de contexto.
  • O middleware posicionado antes do bundle está fora da fronteira de aplicação. Considere a posição externa como confiança externa.
  • Dê a cada agente aninhado seu próprio pacote quando seu modelo interno e atividade de ferramentas também precisarem de interceptação.

Limitações atuais

  • Python somente: os Ganchos do Agente ainda não foram implementados nos SDKs de .NET ou Go.
  • API experimental: As assinaturas de fábrica e o comportamento podem ser alterados antes da disponibilidade geral.
  • Streaming com buffer: As atualizações não são liberadas token por token, porque o resultado precisa estar completo antes de uma decisão fail-closed.
  • Ferramentas hospedadas: As ferramentas executadas por um provedor de modelos não passam pela interface de invocação de funções do Agent Framework. Suas chamadas e saídas são apresentadas em post_model_call, mas pre_tool_call e post_tool_call não podem bloquear a execução no servidor do provedor.
  • Limite de cooperação: O Agent Hooks não isola os interceptadores em sandbox nem protege contra um host hostil. Caminhos de código que contornam o pipeline do agente protegido não estão cobertos.
  • A disponibilidade do interceptor afeta a disponibilidade do agente: No modo de imposição, uma falha ou tempo limite do interceptor bloqueia a ação protegida por design.

Para informações sobre implantação em produção, causas de falha e orientações sobre alertas, consulte o runbook operacional do Agent Hooks.

O Agent Hooks ainda não está disponível para o Go. Use o middleware do agente, a aprovação da ferramenta e a segurança do agente para adicionar controles de runtime aos agentes do Go.

Próximas Etapas