Ligar
Os sinais são a funcionalidadesignals do espaço, desligada por padrão e ligada no documento features pelo papel security. Com ela desligada, um item interaction no lote é recusado, POST /v1/constraints responde 404 e uma leitura de contexto que pede include: ["constraints"] recebe o contexto sem o bloco. As interações chegam dentro do registro do turno, quando o espaço grava turnos, ou como itens do lote quando não.
Interações
Uma interação é o que a pessoa foi mostrada ou fez, em oito tipos:
A exposição tem um momento canônico:
delivered_at, quando a lista chegou ao cliente, nunca quando uma ferramenta devolveu os resultados nem quando o modelo os nomeou. Ela recebe um id (um UUIDv7 que o SDK cria na entrega) e cada item tem uma posição na lista inteira; “ver mais” é a mesma lista com a página seguinte. Um item conta como exposto quando a posição dele está entre as visíveis, ou até o maior max_index_seen de um seen da mesma exposição. method diz como a Niadra soube: bridge pela ponte da interface, otel por um span niadra.exposure, ou tool_result, inferido do que uma ferramenta devolveu, que conta mais do que a pessoa viu e nunca serve à atribuição por linha. shown guarda os valores que o item mostrou nos campos que o tipo acompanha ou deixa afirmar, e é contra eles que a leitura de estado diz depois o que mudou desde que a pessoa viu.
Compras, entregas, devoluções e “ficou” não são interações: vêm dos desfechos do ciclo de vida dos objetos que os registram, nunca do que um agente diz. Uma preferência nunca é inferida: source é stated (a pessoa disse), tool_args (o SDK a capturou dos argumentos de uma chamada de ferramenta) ou correction (a pessoa corrigiu uma inferência). A Niadra nunca deriva afinidade ou interesse de uma interação com um objeto cujo tipo ou campo é sensível; desses, guarda só o tipo e uma contagem. As interações cruas ficam 45 dias para a medição e depois só como agregados.
O bloco de restrições
O bloco chega ao agente uma vez por turno, com o contexto (include: ["constraints"]), ou por POST /v1/constraints, para um cliente e, se quiser, renderizado para uma ferramenta. Ele tem uma version (cv_ e um digest do conteúdo, que o registro do turno cita) e:
O bloco passa pelo portão de verificação do contexto da mesma leitura: quando o contexto ou os turnos ao vivo retiveram algo até a identidade ser mais verificada, o bloco não diz nada do cliente.
POST /v1/constraints, sozinha, é uma leitura de programa, com comprovante próprio, e não passa pelo portão.
O que pode entrar: uma restrição rígida vem só do que a pessoa disse; uma inferência nunca vira rígida, e um negativo inferido do comportamento é no máximo brando. Um atributo que a pessoa não disse (acquired, kept, returned_for_size, inferred) se aplica só when_asked: um tamanho inferido só vale quando a pessoa pede “o meu tamanho”. A fala de agora vence: quando uma restrição rígida dita agora choca com uma dita antes, o bloco mantém a nova e reporta o par em conflicts; entre uma dita e uma inferida, fica a dita. As duas entradas de um conflito ficam no bloco, para o registro do turno citar qualquer uma, e kept diz qual vale. Um choque entre duas regras da empresa é mantido pela posição e devolvido à empresa como problema de dados. Uma restrição de sessão dura no máximo 24 horas, e uma de turno nunca chega ao servidor.
Vinculações de ferramenta
As vinculações de uma ferramenta ficam no documento de configuraçãotool-bindings do espaço, do papel integration: uma por ferramenta e fonte (sources vazio vale para todas as fontes), com args, que argumento leva que campo (attr como tipo.campo, param, transform, negation.param, ops); results, onde o resultado traz objetos de um tipo (path, type, namespace, id) e que chave de cada item guarda que campo (fields); e capabilities: overfetch (a ferramenta devolve mais do que pediram, e o SDK filtra o residual), relax_flag (onde o resultado diz que a ferramenta relaxou o pedido), dry_run_param (o argumento que faz uma chamada não mudar nada, para o contrafactual) e mask_output (o SDK mascara na saída os campos que a chave não pode ler).
GET /v1/sdk/profile serve em tool_bindings as vinculações da fonte que chama, sem sources. O SDK as usa para uma ferramenta sem binding no código: mede o bloco por ela, roda o contrafactual por ela e, quando o código não define mask_output, segue capabilities.mask_output; uma vinculação escrita no código vence a servida. POST /v1/constraints com tool devolve o bloco já renderizado para essa ferramenta em rendered, no modo de aviso, pela vinculação da fonte que chama, sem mudar version; uma ferramenta que o espaço não vincula para essa fonte responde 422.
Renderizar para uma ferramenta
O SDK renderiza o bloco para cada ferramenta pelas vinculações dela: que argumento leva que atributo (attr, param, transform, negation.param, ops) e se a ferramenta busca com sobra. in e eq vão para o parâmetro, not_in e ne para o parâmetro de negação, as comparações só quando ops as lista; uma restrição que nenhum argumento expressa é residual, filtrada dos resultados pelo SDK quando a ferramenta busca com sobra, e sem imposição quando não, o que a renderização diz. No modo de aviso (o padrão), a chamada vai como está e o SDK devolve as sugestões; no modo de aplicação, ele acrescenta um parâmetro sugerido só quando a chamada o deixou de fora e tudo por trás dele pode ser injetado (uma restrição rígida dita, de turno ou sessão, sem conflito; um atributo dito), nunca sobrepõe um argumento que a chamada definiu, nunca injeta um tamanho inferido nem uma restrição persistente. Quando a chamada põe no próprio argumento de uma restrição um valor que ela recusa, vale o da chamada, e o par é reportado como conflito.
Enviado não é aplicado: uma ferramenta pode relaxar um filtro por conta própria. Depois da chamada, o SDK lê os resultados e conta, sobre as restrições rígidas enviadas, results_checked, violations, unverifiable (os que não quebram nenhuma, mas não têm o campo de uma) e relaxed. A medida é “enviado, verificável, violado”, nunca só “enviado”; as contagens vão ao registro do turno e ao aproveitamento (constraints, por fonte e agente). Uma ferramenta decorada com @Niadra.tool(..., binding=...) em Python, ou niadra.tool(name, fn, { binding }) em TypeScript, faz essa medição sozinha, e uma sem binding no código a faz pela vinculação servida no perfil; niadra.constraints.render em Python e renderConstraints() e honoredConstraints() em TypeScript expõem a renderização e a contagem. O exemplo do contrafactual de uma ferramenta vinculada está em examples/tool_counterfactual.py e examples/tool-counterfactual.ts.
Beneficiários e presentes
Toda interação levafor: self (o padrão), beneficiary:<id> (uma pessoa sob o perfil do cliente, como um dependente) ou gift. Os sinais ficam separados por for: o que uma pessoa compra para um dependente nunca vira o gosto dela, e o bloco de um beneficiário traz as entradas dele, porque o tamanho de quem vai usar decide. Um presente vai para um balde descartável e nunca vira atributo do cliente. Uma entrega em outro endereço nunca é tomada como beneficiário por si: o bloco pergunta for_whom em ask. Veja Identidade e verificação.
Inferências e o perfil revisável
Uma inferência é uma coisa que os sinais inferem sobre o cliente, com o que a sustenta: uma afinidade (soft_constraint quando o bloco já a leva como entrada branda, affinity quando ainda não), um tamanho inferido dos desfechos (attribute) ou um interesse por um objeto (interest). A evidência é em contagens: exposição efetiva (ponderada pela posição, 1 / log2(pos + 1)), sinal ponderado, eventos, sessões e ganho; um item mostrado muitas vezes e nunca escolhido vira um negativo implícito, brando. A derivação roda quando o item pendente mais antigo chega a 5 minutos ou quando a sessão fica 1 minuto em silêncio; uma passagem noturna ajusta os priores com o que o espaço viu em 90 dias, só de valores vistos por ao menos 10 pessoas. O que o cliente disse não é inferência e não aparece aqui.
O cliente pode ver, corrigir e apagar cada inferência, pela sua equipe: GET /v1/profiles/{profile_id}/inferences lista cada uma com origem, evidência, confiança, finalidades de uso e data; /correct troca a inferência pelo que o cliente diz, como preferência ou atributo declarado, e a apaga; DELETE deixa uma lápide, e a mesma evidência nunca a infere de novo. Uma oposição ao perfilamento (POST /v1/profiles/{profile_id}/traits/opt-out) para a derivação. No Console, a aba Inferências do perfil mostra tudo isso, para o papel security.
Um pedido de revisão (POST /v1/profiles/{profile_id}/review-requests) leva ao encarregado de proteção de dados da controladora o pedido de um titular de revisar uma decisão automatizada, com a explicação montada dos comprovantes: os ids, tipos, superfícies, regras, versões e entradas deles, por referência, nunca conteúdo pessoal. A decisão da controladora é registrada uma vez (/resolve), e os webhooks review_request.created e review_request.resolved avisam. Os pedidos ficam ao menos 395 dias depois de resolvidos, como obrigação legal, e um apagamento do titular os conta em retained. Veja Privacidade.
Experimentos por elemento
O espaço pode medir o que cada elemento do bloco faz: um experimento no documentomeasurement tira, por braço, o bloco de restrições, os sinais brandos inferidos, os tamanhos inferidos ou o bloco de estado, e compara o que as pessoas fizeram depois. Fontes críticas nunca vão a um braço de controle, e o grupo de controle da memória não recebe bloco nenhum. Antes de um experimento, o contrafactual de ferramenta diz se o elemento muda o que a ferramenta devolve, a partir dos turnos gravados. Veja Desfechos e atribuição.
Próximos passos
Tipos de objeto e estado
os campos e as famílias de atributo que uma preferência nomeia.
Desfechos e atribuição
da exposição ao pedido, pelo token de exposição.
Bloco de restrições
a referência de
POST /v1/constraints.Agentes de varejo
listas, tamanhos e “nada em preto” numa loja.

