Uma caixa de entrada de aprovações humanas para tarefas de IA deve guardar pedidos de decisão com versão, responsável, prazo e ação exata a executar. Cada decisão precisa se referir ao conteúdo que a pessoa realmente revisou. Se destinatário, valor, arquivo ou outro parâmetro relevante mudar, a aprovação anterior deixa de liberar a execução e o item deve voltar à revisão.
Para implementar isso, modele a solicitação de aprovação como um registro próprio, separado da tarefa do agente e do envio de notificações. O backend valida a autoridade do revisor, grava a decisão e só depois libera um executor que confere novamente a autorização. O projeto abaixo é uma recomendação de arquitetura para construir essa fila com estados e histórico verificáveis.
Resumo rápido
- Mostre o conteúdo concreto da ação, com destinatários, parâmetros e consequências.
- Vincule a decisão a uma versão imutável da proposta.
- Separe revisão concluída de execução concluída.
- Trate expiração, alteração do conteúdo e troca de revisor explicitamente.
- Preserve um histórico de decisões e resultados sem copiar segredos.
Da interrupção do agente a uma fila de trabalho
Interromper um fluxo para pedir autorização resolve apenas uma parte do problema. Alguém ainda precisa encontrar o pedido, entender o contexto e saber se pode decidir. O time também precisa descobrir quais pedidos venceram, quais perderam validade e quais já foram aprovados, mas continuam aguardando execução.
Os padrões de human-in-the-loop para agentes explicam onde inserir a intervenção humana. Aqui, o foco é o objeto operacional que permanece depois da interrupção: uma solicitação identificável, consultável e vinculada a uma ação específica. Um comentário solto no chat não fornece sozinho essas propriedades.
Frameworks oferecem peças para suspender e retomar tarefas. A documentação de interrupts do LangGraph descreve pausas com persistência de estado e retomada por identificação de thread. A documentação de callbacks no AWS Step Functions mostra a espera por uma resposta externa usando um token de tarefa. Esses mecanismos não substituem a definição dos revisores e das regras de negócio.
Recomendo começar com uma fila central e filtros por empresa, equipe responsável, tipo de ação e prazo. O número de cartões é menos útil que a identificação do próximo trabalho possível: pendente comigo, pendente sem responsável, proposta alterada e aprovado aguardando execução devem aparecer como situações distintas.
Modelo de dados: solicitação, versão e decisão
Uma estrutura inicial pode separar quatro entidades: solicitação, proposta versionada, decisão e tentativa de execução. A solicitação informa por que o agente parou. A proposta contém o que será feito. A decisão registra quem avaliou determinada versão. A tentativa informa se o efeito externo aconteceu. Essa divisão evita apagar o passado quando a proposta precisa mudar.
| Grupo de campos | Conteúdo recomendado | Função |
|---|---|---|
| Identidade | approval_id, tenant_id, task_id, action_id | Localizar o pedido e isolar empresas |
| Proposta | payload_ref, payload_version, payload_digest | Fixar a versão e detectar alterações |
| Roteamento | reviewer_id, reviewer_group, assignment_version | Identificar quem pode decidir agora |
| Validade | created_at, expires_at, policy_version | Aplicar prazo e política verificáveis |
| Decisão | decision, decided_by, decided_at, reason | Preservar a manifestação humana |
| Execução | execution_state, idempotency_key, external_ref | Controlar o efeito e sua reconciliação |
Use um identificador opaco para a solicitação. Inclua a empresa em todas as consultas e verificações de autorização, mesmo que o identificador pareça difícil de adivinhar. Uma pessoa pode ter acesso à tarefa original e, ainda assim, não possuir autoridade para aprovar seu envio ou alteração financeira.
O payload é o conjunto de parâmetros da ação. Recomendo guardar uma cópia imutável ou referência a objeto versionado, com controle de acesso. Um digest é um resumo criptográfico para comparação; ele ajuda a detectar diferença, mas não prova sozinho quem aprovou. A decisão precisa vir de uma sessão autenticada e ser conferida pelo servidor.
Defina uma representação estável antes de calcular esse resumo. Campos em ordem diferente não deveriam gerar uma nova proposta sem mudança de significado. Por outro lado, destinatário adicional, anexo substituído e limite financeiro alterado precisam participar da comparação. Documente quais campos são materiais para aquele tipo de ação.
Estados que preservam o sentido da revisão
Para a revisão, recomendo os estados pending, reviewed, stale, expired e cancelled. Pending significa que ainda falta uma decisão válida. Reviewed significa que a revisão terminou, com resultado separado de aprovação ou rejeição. Stale indica que o conteúdo ou suas premissas mudaram. Expired encerra a janela de decisão. Cancelled registra a retirada do pedido.
Não use reviewed como sinônimo de enviado. Uma decisão aprovada pode estar aguardando o executor, enquanto uma rejeitada nunca deve entrar nessa fila. Mantenha estados de execução próprios, como queued, running, succeeded, failed e uncertain. O último representa uma tentativa cujo efeito externo ainda precisa ser confirmado.
Uma mudança material deve criar nova versão e tornar a anterior stale, inclusive quando ela já tiver aprovação. Preserve a decisão histórica, mas retire sua capacidade de liberar o executor. A recomendação é coerente com a orientação da OWASP sobre autorização de transações, que trata alterações nos dados e a necessidade de uma verificação final antes da execução.
Prazo para decidir e prazo para executar podem ser diferentes. Por exemplo, a empresa pode admitir revisão até o fim do expediente, mas exigir uma revalidação se a execução ficar para o dia seguinte. Esses intervalos são decisões operacionais, não valores universais. Mostre ambos quando existirem e valide o prazo no servidor no instante da transição.
Não dependa somente de uma rotina periódica para marcar expiração. Mesmo que a atualização visual esteja atrasada, o endpoint de decisão deve recusar um pedido vencido. Ao gerar nova solicitação, relacione-a à anterior e mostre o motivo da reabertura. Um link antigo deve apresentar o estado atual, sem restaurar a validade anterior.
Revisor, tela de decisão e vínculo com a ação exata
O cartão resumido deve mostrar tipo de ação, empresa, responsável, idade e prazo. Ao abrir, apresente os parâmetros efetivos e os elementos usados para justificar a proposta. Para uma mensagem, mostre o texto completo, destinatários e anexos. Para alteração de cadastro, mostre valores anteriores e propostos. Um resumo gerado pela IA pode ajudar, mas não deve ocultar o conteúdo executável.
Inclua botões distintos para aprovar, rejeitar e solicitar ajustes, com confirmação proporcional à consequência da ação. Pedir ajustes produz nova versão; não altera silenciosamente o conteúdo aprovado. Exiba também mudanças desde a revisão anterior, deixando claro se a pessoa está analisando uma proposta completamente nova ou apenas uma correção localizada.
Recomendo enviar ao backend o identificador, a versão da proposta e a versão da atribuição que estavam na tela. O servidor relê o registro, confirma que continua pendente, verifica a autoridade atual e compara as versões. Se outro revisor já decidiu ou o conteúdo mudou, a resposta deve informar o conflito e solicitar atualização da tela.
Uma atualização condicional no banco permite que apenas uma decisão vença a disputa. Grave a decisão e o evento que liberará o executor em uma transação, ou use uma caixa de saída transacional. Essa caixa guarda o evento no mesmo compromisso do banco e permite publicá-lo depois. Assim, uma queda entre aprovar e notificar não perde a liberação.
A troca de revisor também merece evento próprio, com origem, destino e motivo. Depois da reatribuição, uma aba antiga do responsável anterior não pode continuar decidindo pela atribuição passada. Reavalie a autoridade no momento da decisão. Se a política permitir revisão por grupo, documente se qualquer integrante decide ou se há exigência de mais de uma pessoa.
No executor, compare novamente action_id, versão, digest, prazo e política aplicável. Confira também as precondições do destino, como a versão do cadastro. A aprovação de atualizar um contato não libera a atualização de outro, mesmo que o texto da proposta pareça parecido. As permissões do agente continuam valendo depois da revisão humana.
Exemplo: uma agência de eventos em Curitiba
Imagine uma agência de eventos em Curitiba que usa IA para preparar propostas comerciais. O exemplo é ilustrativo. O agente reúne serviços e redige o e-mail, mas o envio ao cliente depende da coordenadora comercial. Cada solicitação guarda o destinatário, o texto, os anexos e a versão da proposta de preços.
A coordenadora abre a caixa de entrada e encontra o pedido pending. Enquanto revisa, o fornecedor altera um item da proposta. O backend gera outra versão, marca a anterior stale e mostra as diferenças. O clique na aba antiga é recusado por conflito de versão, com uma mensagem explicando o que mudou e oferecendo a revisão atualizada.
Se a coordenadora sair de férias, o gestor reatribui os pedidos pendentes a uma pessoa autorizada. Essa troca não aprova os pedidos nem altera seus destinatários. O histórico conserva quem recebeu a tarefa inicialmente e quem decidiu depois. Uma notificação enviada à coordenadora anterior passa a abrir apenas o estado atualizado, sujeito ao acesso que ela ainda tiver.
Após a aprovação válida, o executor confere que o anexo corresponde à versão revisada e inicia o envio com identificador estável. Se perder a resposta do serviço de e-mail, o pedido fica com execução uncertain até a consulta ou conciliação adequada. A tela informa que a revisão terminou e que o envio ainda não foi confirmado, evitando um segundo clique por engano.
Para operar a fila, acompanhe idade dos pendentes, itens sem responsável, expirações e conflitos de versão. Evite reduzir a avaliação ao volume de aprovações. Uma decisão rápida sem acesso ao conteúdo completo pode esconder um problema de interface ou de roteamento. Essas métricas são recomendações de acompanhamento, sem presumir ganhos para o negócio ilustrado.
Erros comuns
Guardar só um campo approved. Ele não explica quem decidiu, qual versão foi revisada e se a execução aconteceu. Separe resultado da revisão, identidade do revisor e estado do efeito externo.
Aprovar pelo link recebido sem nova verificação. Encaminhamento de notificações não pode transferir autoridade. O link localiza o pedido; a sessão e a política do backend determinam quem pode decidir.
Retomar o agente e repetir efeitos anteriores. A documentação do LangGraph alerta que o nó interrompido reinicia na retomada. Planeje etapas idempotentes e isole efeitos externos antes da interrupção. Teste o comportamento do mecanismo usado, sem presumir que a execução continuará exatamente da linha pausada.
Copiar dados sensíveis para toda notificação. Prefira uma descrição mínima e acesso autenticado ao conteúdo. A orientação de logging da OWASP também ajuda a selecionar o que registrar: eventos precisam ser investigáveis sem incluir tokens, senhas ou exposição desnecessária de dados pessoais.
Não testar concorrência. Simule dois revisores decidindo juntos, mudança do payload durante a leitura e expiração durante o clique. O artigo sobre testes de agentes de IA complementa esses cenários. A expectativa deve incluir recusa explícita do pedido desatualizado e preservação de uma única decisão válida.
Perguntas frequentes
Pending e reviewed bastam para a primeira versão?
Podem ser o núcleo, mas ainda será necessário representar rejeição, expiração e perda de validade. Se esses casos ficarem escondidos em comentários, o executor terá dificuldade para distinguir uma decisão válida de um pedido que deveria permanecer bloqueado.
Uma aprovação pode autorizar várias ações?
Pode, se o conjunto estiver explicitamente listado e versionado. Defina se a decisão é indivisível ou por item. Adicionar uma ação depois da revisão exige outra decisão, pois ela não fazia parte do conjunto apresentado.
Quem pode reatribuir o revisor?
Uma identidade autorizada pela política da empresa. Recomendo separar a permissão de reatribuir da permissão de aprovar. Registre a mudança e valide o novo responsável, impedindo que a troca seja usada para contornar a autoridade exigida.
É preciso guardar todo o payload nos logs?
Não. Guarde a proposta versionada em armazenamento protegido e registre referências no histórico operacional. A trilha deve permitir recuperar o conteúdo revisado para usuários autorizados, com regras próprias de acesso e retenção.
Como tratar uma aprovação que venceu antes do envio?
Bloqueie a execução e aplique a política de revalidação. Se for necessário revisar novamente, crie uma solicitação relacionada à anterior. Preserve a decisão antiga como histórico, sem apresentá-la como autorização atual.