Modificar um agente¶
Localização e caminho de execução¶
| Agente | Builder de prompt | Estados relacionados |
|---|---|---|
| Triagem | src/core/agents/triagem/system_prompt.py → build_triagem_system_prompt |
TRIAGE |
| Qualificação | src/core/agents/qualificacao/system_prompt.py → build_qualificacao_system_prompt |
QUALIFYING |
| Coleta | src/core/agents/coleta/system_prompt.py → build_coleta_system_prompt |
DATA_COLLECT, CONFIRM |
AgentInvokerImpl em src/core/agents/invoker.py escolhe o builder, insere packages, aplica override, acrescenta regras fixas e monta mensagens. O resultado do LLM retorna ao caso de uso; o agente não grava no banco ou envia WhatsApp diretamente.
1. Encontrar o prompt efetivo¶
Antes de editar, confira se há override ativo em VersionedResourceRepository. _apply_prompt_override() usa o arquivo como fallback, ou substitui {{default_prompt}} pelo conteúdo padrão quando esse marcador existe no override.
_with_runtime_guards() acrescenta identidade, contexto de instância/segmento/intenção, restrições de promessa de prazo e regras de mudança de assunto após o override. Em contexto de saúde humana, há restrições adicionais. Uma edição em um override não remove essas guardas.
Os overrides administrativos são validados estruturalmente por validate_resource_update() em admin_tools.py, mas a presença de {"s" ou {{default_prompt}} não comprova a qualidade nem a compatibilidade de todas as respostas possíveis. Trate alteração de conteúdo como uma mudança que precisa de regressão.
2. Preservar o contrato de saída¶
Toda saída precisa começar com {, conter JSON com s inteiro e ser seguida pelo texto destinado ao cliente quando o código pedir resposta. O parser não aceita cumprimento antes do JSON nem code fence envolvendo a resposta.
{"s":1}Qual é o tipo de amostra?
{"s":99,"context_needed":"SAMPLE_INSTRUCTIONS"}
s=99 pede um package; s=97 inicia a confirmação de mudança de assunto; s=98 é processado pelo fluxo de mudança de sessão. Não invente um código no prompt sem alterar os enums/validação, o dispatcher e os testes correspondentes. Códigos de ação descreve o significado por agente, pois o mesmo valor pode ter efeitos diferentes.
O caso de uso tem reparo de formato e fallback de handoff. Isso recupera algumas falhas; não transforma um prompt incompatível em uma mudança segura. Uma saída sintaticamente válida ainda pode ter campo desconhecido, serviço não reconhecido ou transição ilegal.
3. Respeitar histórico e contexto¶
invoke() filtra o histórico pelo session_id. Mensagens INBOUND viram user, OUTBOUND viram assistant, eventos SYSTEM não são reenviados e mensagens marcadas superseded são excluídas. O invocador evita acrescentar novamente o último texto de usuário quando já está no histórico.
Uma reinvocação no mesmo turno pode receber client_message=None. Os dados atualizados estão no histórico, na sessão ou nos packages injetados. Não escreva um prompt que dependa de sempre receber uma nova mensagem de usuário após cada resposta s=99.
O catálogo de descoberta contém descrições curtas, não toda a KB. O agente solicita conteúdo adicional somente quando necessário. Revisões de conhecimento devem manter coerência entre CONTENT, metadata de descoberta e os campos já qualificados/coletados.
4. Escolher a camada certa¶
| Mudança desejada | Camada |
|---|---|
| Clareza da pergunta, tom e concisão | Prompt e src/core/agents/whatsapp_style.py |
| Novo campo obrigatório de um serviço | domain/services.py, prompt e dispatcher |
| Nova ação ou estado | Domínio + action_mapping.py + caso de uso + persistência |
| Novo modelo ou reasoning effort | Settings/factory/SAM; cliente OpenAI |
| Novo conteúdo científico/comercial | Package e fonte de conhecimento aprovada |
| Regra que nunca pode ser sobreposta por admin | Guarda programática/runtime, com testes específicos |
Não use o prompt para prometer uma validação que o código não implementa. Também não torne uma pergunta livre em escrita automática externa sem definir idempotência, estado e autorização do fluxo.
5. Validar antes da chamada real¶
python -m pytest tests/unit/agents/test_system_prompts.py tests/unit/agents/test_invoker.py -q
python -m pytest tests/unit/application/test_parser.py tests/unit/application/test_action_mapping.py -q
python -m pytest tests/unit/application/test_process_message_use_case.py -q
python -m pytest tests/integration/test_fixture_replay.py -q
Os testes de prompt verificam regras e conteúdo; os de invocador verificam montagem e encaminhamento. Parser/dispatcher/use case verificam o efeito do contrato, e replay verifica uma conversa roteirizada. Nenhum deles prova que uma nova versão do modelo vai sempre obedecer. O teste real marcado integration requer chave, custo e avaliação separada, conforme integração.
6. Criar uma fixture de regressão¶
Reduza o problema a uma conversa fictícia que exponha o erro. Inclua todos os llm_responses na ordem em que serão consumidos e os invariantes suportados pelo runner (state, segment, service_identified, handoff_reason, demands_recorded). Não use uma expectativa arbitrária que o runner ignore.
Para uma mudança de assunto, cubra a confirmação e a criação da nova sessão; para s=99, inclua o pedido de package e a resposta seguinte; para handoff, confira que o fluxo para de chamar agentes no atendimento humano. O guia de fixtures mostra o formato completo.
Rollback¶
Uma mudança em arquivo pode ser revertida no Git e implantada de novo. Uma versão dinâmica exige restaurar/desativar o recurso correto no repository administrativo. Verifique o prompt renderizado depois da restauração e mantenha o caso de regressão. Reverter um prompt não remove mensagens já enviadas nem desfaz alterações externas realizadas em turnos anteriores.
Fontes: src/core/agents/invoker.py, src/core/application/agent_invoker.py, src/core/application/parser.py, src/core/application/admin_tools.py, src/core/application/process_message_use_case.py, src/core/knowledge_base/repository.py e testes citados.