Pular para conteúdo

Adicionar um serviço

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.