> ## Documentation Index
> Fetch the complete documentation index at: https://docs.strattum.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Montar a ontologia

> Como dizer à Strattum quais entidades existem nos seus dados e como elas se ligam: pelo Construtor ou editando o YAML.

A ontologia diz à Strattum o que existe nos seus dados e como as coisas se ligam: um **cliente** abre **chamados**, um **contato** trabalha numa **empresa**. Com ela, a Strattum monta o grafo da Memory, que junta o mesmo cliente visto em sistemas diferentes e deixa os assistentes de IA responderem perguntas sobre ele.

A ontologia fica na tela **Ontologia** do Console. Só administradores a alteram.

## O jeito recomendado: o Construtor

Na tela **Ontologia**, clique em **Abrir o Construtor**. Ele pergunta sobre o seu negócio, olha as tabelas dos seus conectores e propõe a ontologia pronta. Você revisa a proposta, aceita e aplica.

O Construtor aparece quando está habilitado na sua instalação. Se o painel disser que ele está indisponível, fale com quem administra a Strattum, ou monte a ontologia à mão, como explicado abaixo.

## Fazer à mão

A ontologia é um arquivo YAML com três partes:

* **`nodes`**: os tipos de coisa que existem, como cliente, empresa ou chamado. Cada um vem de uma tabela.
* **`edges`**: as ligações entre eles, como "o chamado foi aberto pelo cliente".
* **`timeline`**: eventos com data, que aparecem na linha do tempo de uma entidade.

### Um exemplo completo

Imagine um CRM, com as tabelas de contatos e de atividades, e um sistema de suporte, com as tabelas de solicitantes e de chamados. A mesma pessoa está cadastrada nos dois sistemas. A ontologia abaixo:

* junta o contato do CRM e o solicitante do suporte num **cliente só**, pelo e-mail;
* cria os chamados e liga cada um a quem o abriu;
* coloca as atividades do CRM na linha do tempo do cliente.

```yaml theme={null}
nodes:
  - label: Customer                     # o tipo, em PascalCase
    source: clean/crm_contacts          # a tabela que alimenta este tipo
    connector: hubspot                  # de qual conector a tabela vem
    id_field: external_id               # a coluna que identifica cada linha
    er_fields: [email, phone]           # colunas que reconhecem o mesmo cliente em outros sistemas
    properties: [external_id, email, phone, name]   # colunas que entram no grafo

  - label: Customer                     # o mesmo tipo, vindo de outra fonte
    source: clean/support_requesters
    connector: zendesk
    id_field: requester_id              # o id do solicitante no suporte
    er_fields: [email]                  # o e-mail liga este cliente ao do CRM
    properties: [requester_id, email, name, plan]

  - label: Ticket
    source: clean/support_tickets
    id_field: external_id
    properties: [external_id, subject, status, requester_email, created_at]

edges:
  - type: REQUESTED_BY                  # o nome da ligação, em MAIÚSCULAS
    source: clean/support_tickets       # a tabela onde a ligação aparece
    from:
      label: Ticket
      join_key: external_id             # cada linha é o próprio chamado
    to:
      label: Customer
      match_field: email                # procura o cliente pelo e-mail...
      source_column: requester_email    # ...usando esta coluna do chamado

timeline:
  - event_type: crm_activity
    source: clean/crm_activities
    entity_join: "contact_id -> Customer.external_id"    # a coluna que aponta para o cliente
    timestamp_field: created_at
    properties: [activity_type, notes]
```

### Como o cliente das duas fontes vira um só

Os dois itens de `nodes` têm o mesmo `label`, `Customer`, e cada um lê uma tabela. Quando uma linha do CRM e uma do suporte têm o mesmo e-mail, a Strattum as reconhece como a mesma pessoa e cria uma entidade só, com as informações das duas:

| Origem | Linha |
| - | - |
| CRM (`clean/crm_contacts`) | `external_id: c-17`, `email: ana@empresa.com.br`, `phone: +5511999999999`, `name: Ana Souza` |
| Suporte (`clean/support_requesters`) | `requester_id: z-904`, `email: Ana@Empresa.com.br`, `plan: premium` |
| **Cliente no grafo** | `Ana Souza`, com e-mail, telefone, plano e os ids dos dois sistemas |

O e-mail com maiúsculas no suporte não atrapalha, porque a Strattum [normaliza](#normalizadores) os identificadores antes de comparar.

Para juntar fontes de um mesmo tipo:

* Repita o `label` e mude o `source`. Cada fonte tem o próprio `id_field` e as próprias `properties`.
* As fontes precisam ter um identificador em comum em `er_fields`. Ele pode ser direto (as duas têm `email`) ou em cadeia: o CRM compartilha `cpf` com o ERP, e o ERP compartilha `email` com o suporte.
* Se as fontes não têm nenhum identificador em comum, a validação recusa a ontologia, porque os clientes de uma nunca se encontrariam com os da outra.

Três regras resolvem a maior parte dos casos:

1. **`source` começa com `clean/`**, seguido do nome da tabela tratada do conector. Se a tabela vem de uma fonte federada, o prefixo é `fed/`.
2. **Toda coluna citada em `id_field`, `er_fields` ou `indexed_fields` precisa estar em `properties`.**
3. **Use `er_fields` só para colunas que identificam a pessoa ou empresa sozinhas**, como e-mail, telefone, CPF ou CNPJ. É por elas que a Strattum reconhece que o cliente do CRM e o do suporte são a mesma pessoa. Nunca coloque ali uma coluna que se repete, como status ou cidade.

Para ligar dois tipos, use `join_key` quando a tabela já traz o identificador do outro lado, e `match_field` quando a ligação é por um valor como o e-mail.

### Aplicar

1. Na tela **Ontologia**, aba **YAML**, clique em **Editar** e cole ou altere o YAML. O Console valida enquanto você edita.
2. Clique em **Verificar schema** para conferir se as tabelas e colunas existem.
3. Clique em **Salvar rascunho**. Nada muda no grafo ainda.
4. Clique em **Aplicar** e confirme em **Aplicar agora**.

Para voltar atrás, abra o **Histórico**, escolha uma versão anterior e aplique de novo.

## Os campos

O arquivo tem um campo opcional no topo, `version`, que você pode usar para numerar as suas versões. Os demais campos ficam dentro de `nodes`, `edges` e `timeline`.

### Campos de um tipo (`nodes`)

Cada item de `nodes` descreve um tipo de coisa e a tabela de onde ele vem.

| Campo | Para que serve | Exemplo | Obrigatório |
| - | - | - | - |
| `label` | O nome do tipo, em PascalCase (inicial maiúscula, sem espaço, acento nem sublinhado). É o nome que aparece no grafo. | `Customer` | sim |
| `source` | A tabela que alimenta o tipo. Cada linha vira uma entidade. Começa com `clean/` para tabela tratada de conector, ou `fed/` para view de uma fonte federada. | `clean/crm_contacts` | sim |
| `id_field` | A coluna que identifica cada linha dentro dessa tabela, como o id do registro no sistema de origem. | `external_id` | sim |
| `properties` | As colunas que entram no grafo como informação da entidade. Coluna fora dessa lista não entra. | `[external_id, email, name]` | sim |
| `er_fields` | As colunas que reconhecem a mesma entidade em outros sistemas. Duas linhas com o mesmo valor em uma delas viram uma entidade só. | `[email, cpf]` | não |
| `identifier_columns` | Liga um nome de `er_fields` a uma coluna com outro nome nesta tabela. Serve quando um sistema chama o CPF de `documento`, por exemplo. | `{cpf: documento}` | não |
| `normalizers` | Diz como limpar o valor de um identificador antes de comparar. A chave é o nome em `er_fields` ou o `id_field`. Veja a [tabela de normalizadores](#normalizadores). | `{matricula: alnum}` | não |
| `indexed_fields` | Colunas que as pessoas usam para filtrar, como status ou ano. Deixa o filtro mais rápido e não junta entidades. | `[status, year]` | não |
| `connector` | O nome do conector de origem. O Console usa para mostrar o ícone. | `hubspot` | não |
| `connector_instance` | Separa duas conexões do mesmo conector, como duas contas de Salesforce, para que as entidades delas nunca se juntem. Não pode ter `:`. Com uma conexão só, deixe em branco. | `salesforce#vendas` | não |
| `display_tier` | Se o tipo aparece ligado quando você abre o grafo no Console: `entity` aparece (padrão), `activity` e `detail` começam escondidos. Não muda os dados. | `detail` | não |
| `display_color` | A cor do tipo no grafo do Console. Sem ela, o Console escolhe uma cor. | `"#f59e0b"` | não |

#### Identificadores: `id_field` e `er_fields`

O `id_field` diz qual é a linha. O `er_fields` diz quem é a entidade. Um chamado só existe no sistema de suporte, então basta o `id_field`. Um cliente aparece no CRM, no suporte e no ERP, então ganha também `er_fields`, para que a Strattum reconheça que é a mesma pessoa.

Coloque em `er_fields` só colunas que identificam a entidade sozinhas: e-mail, telefone, CPF, CNPJ, placa, matrícula. Uma coluna que se repete entre entidades diferentes, como status, cidade ou cor, juntaria todas elas numa só. Para filtrar por essas colunas, use `indexed_fields`.

Toda coluna citada em `id_field`, `er_fields` e `indexed_fields` precisa estar também em `properties`.

#### Normalizadores

Antes de comparar identificadores, a Strattum limpa os valores, para que `(11) 99999-9999` e `11999999999` sejam o mesmo telefone. Quando a coluna se chama `email`, `phone`, `telefone`, `cpf` ou `cnpj`, a limpeza certa é escolhida pelo nome. Para outro nome, declare em `normalizers`, usando o nome que está em `er_fields`.

| Normalizador | O que faz | Exemplo |
| - | - | - |
| `email` | Minúsculas, sem espaços e sem o `+apelido` | `Ana+x@X.COM` vira `ana@x.com` |
| `phone` | Só dígitos, com `+55` na frente | `(11) 99999-9999` vira `+5511999999999` |
| `cpf` | Só dígitos; descarta o valor se não tiver 11 | `111.222.333-44` vira `11122233344` |
| `cnpj` | Só dígitos; descarta o valor se não tiver 14 | `11.222.333/0001-81` vira `11222333000181` |
| `digits` | Só dígitos | `12.345.678-9` vira `123456789` |
| `alnum` | Só letras e dígitos, em minúsculas. Bom para RG, que pode terminar em X. | `M-123.456` vira `m123456` |
| `upper` | Maiúsculas, sem espaços nas pontas | `ab-12` vira `AB-12` |
| `title` | Primeira letra de cada palavra em maiúscula | `ANA SOUZA` vira `Ana Souza` |
| `text` | Minúsculas, sem espaços nas pontas. É o padrão. | `M-123456` vira `m-123456` |
| `verbatim` | Só tira os espaços das pontas | `Ab-12` vira `Ab-12` |

Exemplo de um cadastro de funcionários em que o CPF está numa coluna chamada `documento` e a matrícula tem letras:

```yaml theme={null}
nodes:
  - label: Employee
    source: clean/hr_staff
    id_field: external_id
    er_fields: [cpf, matricula]
    identifier_columns: {cpf: documento}   # o cpf desta tabela está na coluna documento
    normalizers:
      matricula: alnum                     # cpf já é limpo como CPF pelo nome
    properties: [external_id, documento, matricula, name]
```

### Campos de uma ligação (`edges`)

Cada item de `edges` liga dois tipos. Cada linha da tabela indicada vira uma ligação.

| Campo | Para que serve | Exemplo | Obrigatório |
| - | - | - | - |
| `type` | O nome da ligação, em MAIÚSCULAS com sublinhado. Leia como verbo: o chamado `REQUESTED_BY` o cliente. | `REQUESTED_BY` | sim |
| `source` | A tabela onde a ligação aparece. | `clean/support_tickets` | sim |
| `from` | O lado de onde a ligação sai. | veja abaixo | sim |
| `to` | O lado aonde a ligação chega. | veja abaixo | sim |
| `properties` | Colunas que viram informação da própria ligação, como o canal ou a data. | `[channel]` | não |

Cada lado (`from` e `to`) diz qual tipo procurar e como achar a entidade certa:

| Campo do lado | Para que serve |
| - | - |
| `label` | O tipo desse lado. Precisa existir em `nodes`. |
| `join_key` | A coluna da tabela que traz o `id_field` da entidade desse lado. Use quando a tabela já tem o id do outro sistema, como uma chave estrangeira. |
| `match_field` | A informação da entidade usada para achá-la, como `email`. Use quando a ligação é por um valor, e não por id. |
| `source_column` | Com `match_field`, a coluna da tabela que traz esse valor. |

Cada lado usa `join_key` ou `match_field`, nunca os dois. Exemplo de uma tabela que liga contatos a empresas pelos ids:

```yaml theme={null}
edges:
  - type: WORKS_AT
    source: clean/crm_contact_company    # uma linha por contato e empresa
    from:
      label: Customer
      join_key: customer_external_id     # o id do contato
    to:
      label: Company
      join_key: company_external_id      # o id da empresa
```

### Campos de um evento (`timeline`)

Cada item de `timeline` transforma as linhas de uma tabela em eventos com data na linha do tempo de uma entidade, como reuniões, pedidos ou atividades.

| Campo | Para que serve | Exemplo | Obrigatório |
| - | - | - | - |
| `event_type` | O nome do tipo de evento. | `crm_activity` | sim |
| `source` | A tabela dos eventos. | `clean/crm_activities` | sim |
| `entity_join` | Qual coluna aponta para a entidade dona do evento, no formato `coluna -> Tipo.id_field`. | `"contact_id -> Customer.external_id"` | sim |
| `timestamp_field` | A coluna com a data do evento. O padrão é `created_at`. | `created_at` | não |
| `properties` | Colunas que viram informação do evento. | `[activity_type, notes]` | não |

## Erros comuns

| A mensagem fala de | O que corrigir |
| - | - |
| `must be PascalCase` | O `label` começa com maiúscula e não tem espaço, acento nem sublinhado: `Customer`, não `customer`. |
| `must start with 'clean/', 'fed/' or 'raw/'` | Escreva a fonte com o prefixo: `clean/crm_contacts`, não `crm_contacts`. |
| `must be listed in 'properties'` | Acrescente a coluna citada à lista `properties` do mesmo tipo. |
| `join_key` ou `match_field` | Cada lado de uma ligação precisa de um dos dois, nunca dos dois juntos. |
| `sources that cannot converge` | Duas fontes do mesmo tipo não têm identificador em comum. Acrescente a `er_fields` (e a `properties`) a coluna que liga as duas, como o e-mail. |
| `Tabela não encontrada` (em Verificar schema) | A tabela tratada desse conector ainda não existe. Rode a sincronização do conector, espere terminar e verifique de novo. |

A validação mostra um problema por tipo de cada vez. Depois de corrigir, valide de novo para ver se há outro.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.