Visão Geral
O decorador
@human_feedback requer CrewAI versão 1.8.0 ou superior. Certifique-se de atualizar sua instalação antes de usar este recurso.@human_feedback permite fluxos de trabalho human-in-the-loop (HITL) diretamente nos CrewAI Flows. Ele permite pausar a execução do flow, apresentar a saída para um humano revisar, coletar seu feedback e, opcionalmente, rotear para diferentes listeners com base no resultado do feedback.
Isso é particularmente valioso para:
- Garantia de qualidade: Revisar conteúdo gerado por IA antes de ser usado downstream
- Portões de decisão: Deixar humanos tomarem decisões críticas em fluxos automatizados
- Fluxos de aprovação: Implementar padrões de aprovar/rejeitar/revisar
- Refinamento interativo: Coletar feedback para melhorar saídas iterativamente
Início Rápido
Aqui está a maneira mais simples de adicionar feedback humano a um flow:Code
- Executar
generate_contente retornar a string - Exibir a saída para o usuário com a mensagem de solicitação
- Aguardar o usuário digitar o feedback (ou pressionar Enter para pular)
- Passar um objeto
HumanFeedbackResultparaprocess_feedback
O Decorador @human_feedback
Parâmetros
Uso Básico (Sem Roteamento)
Quando você não especificaemit, o decorador simplesmente coleta o feedback e passa um HumanFeedbackResult para o próximo listener:
Code
Roteamento com emit
Quando você especificaemit, o decorador se torna um roteador. O feedback livre do humano é interpretado por um LLM e mapeado para um dos outcomes especificados:
Code
"needs_revision", que dispara review_content novamente via or_() — criando um loop de revisão. O loop continua até que o outcome seja "approved" ou "rejected".
HumanFeedbackResult
O dataclassHumanFeedbackResult contém todas as informações sobre uma interação de feedback humano:
Code
Acessando em Listeners
Quando um listener é disparado por um método@human_feedback com emit, ele recebe o HumanFeedbackResult:
Code
Acessando o Histórico de Feedback
A classeFlow fornece dois atributos para acessar o feedback humano:
last_human_feedback
Retorna oHumanFeedbackResult mais recente:
Code
human_feedback_history
Uma lista de todos os objetosHumanFeedbackResult coletados durante o flow:
Code
Exemplo Completo: Fluxo de Aprovação de Conteúdo
Aqui está um exemplo completo implementando um fluxo de revisão e aprovação de conteúdo:Combinando com Outros Decoradores
O decorador@human_feedback funciona com @start(), @listen() e or_(). Ambas as ordens de decoradores funcionam — o framework propaga atributos em ambas as direções — mas os padrões recomendados são:
Code
Padrão de self-loop
Para criar um loop de revisão, o método de revisão deve escutar ambos um gatilho upstream e seu próprio outcome de revisão usandoor_():
Code
"revise", o flow roteia de volta para review (porque ele escuta "revise" via or_()). Quando o outcome é "approved", o flow continua para publish. Isso funciona porque o engine de flow isenta roteadores da regra “fire once”, permitindo que eles re-executem em cada iteração do loop.
Roteadores encadeados
Um listener disparado pelo outcome de um roteador pode ser ele mesmo um roteador:Code
Limitações
- Métodos
@start()executam uma vez: Um método@start()não pode fazer self-loop. Se você precisa de um ciclo de revisão, use um método@start()separado como ponto de entrada e coloque o@human_feedbackem um método@listen(). - Sem
@start()+@listen()no mesmo método: Esta é uma restrição do framework de Flow. Um método é ou um ponto de início ou um listener, não ambos.
Melhores Práticas
1. Escreva Mensagens de Solicitação Claras
O parâmetromessage é o que o humano vê. Torne-o acionável:
Code
2. Escolha Outcomes Significativos
Ao usaremit, escolha outcomes que mapeiem naturalmente para respostas humanas:
Code
3. Sempre Forneça um Outcome Padrão
Usedefault_outcome para lidar com casos onde usuários pressionam Enter sem digitar:
Code
4. Use o Histórico de Feedback para Trilhas de Auditoria
Acessehuman_feedback_history para criar logs de auditoria:
Code
5. Trate Feedback Roteado e Não Roteado
Ao projetar flows, considere se você precisa de roteamento:Feedback Humano Assíncrono (Não-Bloqueante - Human in the loop)
Por padrão,@human_feedback bloqueia a execução aguardando entrada no console. Para aplicações de produção, você pode precisar de feedback assíncrono/não-bloqueante que se integre com sistemas externos como Slack, email, webhooks ou APIs.
A Abstração de Provider
Use o parâmetroprovider para especificar uma estratégia customizada de coleta de feedback:
Code
Tratando Flows Pausados
Ao usar um provider assíncrono,kickoff() retorna um objeto HumanFeedbackPending em vez de lançar uma exceção:
Code
Retomando um Flow Pausado
Quando o feedback chega (ex: via webhook), retome o flow:Code
Tipos Principais
PendingFeedbackContext
O contexto contém tudo necessário para retomar:Code
Exemplo Completo de Flow Assíncrono
Code
Melhores Práticas para Feedback Assíncrono
- Verifique o tipo de retorno:
kickoff()retornaHumanFeedbackPendingquando pausado—não precisa de try/except - Use o método resume correto: Use
resume()em código síncrono,await resume_async()em código assíncrono - Armazene informações de callback: Use
callback_infopara armazenar URLs de webhook, IDs de tickets, etc. - Implemente idempotência: Seu handler de resume deve ser idempotente por segurança
- Persistência automática: O estado é automaticamente salvo quando
HumanFeedbackPendingé lançado e usaSQLiteFlowPersistencepor padrão - Persistência customizada: Passe uma instância de persistência customizada para
from_pending()se necessário
Aprendendo com Feedback
O parâmetrolearn=True habilita um ciclo de feedback entre revisores humanos e o sistema de memória. Quando habilitado, o sistema melhora progressivamente suas saídas aprendendo com correções humanas anteriores.
Como Funciona
- Após o feedback: O LLM extrai lições generalizáveis da saída + feedback e as armazena na memória com
source="hitl". Se o feedback for apenas aprovação (ex: “parece bom”), nada é armazenado. - Antes da próxima revisão: Lições HITL passadas são recuperadas da memória e aplicadas pelo LLM para melhorar a saída antes que o humano a veja.
Exemplo
Code
Configuração
Decisões de Design Principais
- Mesmo LLM para tudo: O parâmetro
llmno decorador é compartilhado pelo mapeamento de outcome, destilação de lições e pré-revisão. Não é necessário configurar múltiplos modelos. - Saída estruturada: Tanto a destilação quanto a pré-revisão usam function calling com modelos Pydantic quando o LLM suporta, com fallback para parsing de texto caso contrário.
- Armazenamento não-bloqueante: Lições são armazenadas via
remember_many()que executa em uma thread em segundo plano — o flow continua imediatamente. - Degradação graciosa: Se o LLM falhar durante a destilação, nada é armazenado. Se falhar durante a pré-revisão, a saída bruta é mostrada. Nenhuma falha bloqueia o flow.
- Sem escopo/categorias necessários: Ao armazenar lições, apenas
sourceé passado. O pipeline de codificação infere escopo, categorias e importância automaticamente.
learn=True requer que o Flow tenha memória disponível. Flows obtêm memória automaticamente por padrão, mas se você a desabilitou com _skip_auto_memory, o aprendizado HITL será silenciosamente ignorado.Documentação Relacionada
- Visão Geral de Flows - Aprenda sobre CrewAI Flows
- Gerenciamento de Estado em Flows - Gerenciando estado em flows
- Persistência de Flows - Persistindo estado de flows
- Roteamento com @router - Mais sobre roteamento condicional
- Input Humano na Execução - Input humano no nível de task
- Memória - O sistema unificado de memória usado pelo aprendizado HITL
