Adicionar um serviço¶
Fonte do catálogo¶
Os quinze nomes canônicos e os campos obrigatórios estão em src/core/domain/services.py. ServiceName é uma classe de constantes, não um enum. REQUIRED_FIELDS usa as strings canônicas como chaves e conjuntos imutáveis de nomes de campos como valores.
build_qualificacao_system_prompt() importa esse catálogo e _service_table() o renderiza no prompt. O dispatcher valida a proposta de conclusão do agente antes de avançar para DATA_COLLECT. Portanto, adicionar somente uma descrição na KB não cria um serviço reconhecido pelo domínio.
1. Definir o contrato de qualificação¶
Antes da implementação, defina nome canônico, aplicação no negócio, campos sempre obrigatórios, condições que exigem dados adicionais e critérios de handoff. Não adicione preços, prazos ou serviços sem fonte de negócio aprovada.
O exemplo de qPCR já implementado ilustra o contrato:
# src/core/domain/services.py
ServiceName.QPCR # "qPCR"
REQUIRED_FIELDS[ServiceName.QPCR]
# microrganismo_alvo, tipo_amostra, quantidade_amostras,
# quantidade_alvos, urgencia
Um novo serviço exigirá uma constante e uma entrada equivalente em REQUIRED_FIELDS. Use campos de domínio estáveis; se o nome do serviço mudar depois, sessões históricas e projeções CRM ainda podem conter a string antiga.
2. Acrescentar regras condicionais¶
conditional_required_fields(service, data) recebe o serviço e dados parciais. Hoje adiciona literatura_previa em Genotipagem com modalidade='pcr_eletroforese', e dois campos profissionais em GoYou quando tipo_profissional='nutricionista'.
Inclua regras novas nessa função e testes das condições verdadeiras e falsas. missing_required_fields() considera None, texto em branco e coleções vazias como ausentes; booleano False é uma resposta válida. O validador atual verifica presença, não todos os tipos/faixas científicas de cada campo. Se precisar dessas validações, trate-as como mudança de domínio explícita.
Serviço desconhecido
missing_required_fields() devolve um conjunto vazio para serviço desconhecido. Isso não significa qualificação concluída: o chamador deve verificar is_known_service() primeiro, como o dispatcher faz.
3. Adaptar o agente responsável¶
A Qualificação é responsável pelos dados técnicos. Edite src/core/agents/qualificacao/system_prompt.py para regras específicas e perguntas, mantendo o catálogo renderizado e os códigos atuais. A Triagem identifica segmento/intenção; a Coleta recebe o serviço e os campos técnicos já coletados para preparar o cadastro.
O segmento não é um atributo validado em REQUIRED_FIELDS. Se o novo serviço for restrito a um segmento, diferencie uma orientação no prompt de uma validação programática. Não documente uma restrição rígida se ela existir apenas em linguagem natural.
Uma proposta de conclusão qPCR compatível usa servico e qualification_data, conforme o dispatcher:
{"s":2,"servico":"qPCR","qualification_data":{"microrganismo_alvo":"Salmonella","tipo_amostra":"solo","quantidade_amostras":2,"quantidade_alvos":1,"urgencia":false}}Já tenho os dados técnicos. Vamos ao cadastro?
Confira o contrato completo antes de reutilizar o exemplo em fixtures.
4. Atualizar conhecimento e descoberta¶
Se o serviço exigir instruções extensas, use um Context Package. A função de módulo _discover(), usada por InMemoryKnowledgeBase, importa módulos de src/core/knowledge_base/packages/ com uma constante CONTENT. O ID é o nome do módulo em maiúsculas; um arquivo novo_assunto.py produziria NOVO_ASSUNTO.
Adicione a descrição, palavras-chave e aliases em src/core/knowledge_base/discovery.py. Sem essa metadata, o package continua descoberto, mas o agente vê apenas seu ID no catálogo. Revise os packages de portfólio, exclusões, requisitos e orçamento afetados, em vez de duplicar regras contraditórias.
Se houver overrides ativos no DynamoDB, eles podem sobrepor o arquivo versionado. Confira os recursos de administração e publique a nova versão pelos procedimentos autorizados. Alterar arquivos locais não invalida automaticamente um override remoto.
5. Criar regressões¶
| Camada | Arquivo atual de referência | Evidência esperada |
|---|---|---|
| Catálogo | tests/unit/domain/test_services.py |
Nome reconhecido, campos completos e condicionais corretos |
| Prompt | tests/unit/agents/test_system_prompts.py |
Serviço aparece e regras não quebram formato/segurança |
| Dispatcher | tests/unit/application/test_action_mapping.py |
Incompleto permanece; completo permite coleta |
| Caso de uso | tests/unit/application/test_process_message_use_case.py |
Estado, histórico, IDs e ausência de efeito indevido |
| Payload comercial | tests/unit/application/test_confirm_action.py |
Serviço/campos chegam às integrações no formato esperado |
| Replay | tests/fixtures/conversations/ |
Percurso do cliente chega ao estado final declarado |
Execute os paths de teste explicitamente:
python -m pytest tests/unit/domain/test_services.py tests/unit/agents/test_system_prompts.py tests/unit/application/test_action_mapping.py -q
python -m pytest tests/integration/test_fixture_replay.py -q
Uma fixture deve incluir uma resposta simulada para cada invocação, inclusive encadeamento Triagem → Qualificação e pedidos s=99 no mesmo turno. O runner consome a lista na ordem; uma resposta faltante pode causar falha que parece erro do agente, mas é do roteiro.
6. Fechar a alteração¶
Atualize serviços, packages e instruções de operação afetadas. Revise o impacto em resumo, handoff e CRM: a aceitação no catálogo não garante que relatórios comerciais já saibam agrupar o nome novo. Mantenha a alteração de catálogo separada de habilitar um provider ou fazer deploy.
Fontes: src/core/domain/services.py, src/core/application/action_mapping.py, src/core/agents/qualificacao/system_prompt.py, src/core/knowledge_base/repository.py, src/core/knowledge_base/discovery.py e testes da tabela.