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

# Sistemas, objetos e ações

> Eventos de CRM, ERP e help desk, objetos de negócio e as ações que fecham pendências.

A Niadra é a memória de todos os agentes da empresa: os que atendem o cliente e os que trabalham por dentro, no CRM, no ERP, no help desk, na cobrança e nos pedidos. Para isso, a memória recebe três coisas além das conversas: os **eventos de sistema** que os seus sistemas já emitem, os **objetos de negócio** a que eles se referem e as **ações** que os agentes fazem nesses sistemas. É assim que o agente de voz sabe às 14h07 o que o agente de cobrança fez às 14h06.

## Eventos de sistema

Um evento de sistema é uma mudança de estado num sistema de registro: pedido criado, fatura contestada, ticket reaberto, pagamento recusado. Ele entra como `kind: "system_event"`, com `speaker` igual a `system` e um `canonical_type`, como `invoice.credited`, além dos campos estruturados em `fields`.

Há três portas de entrada:

| Porta                                       | Quando usar                                                                                                                                                                                                             |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Webhook genérico](/guides/system-webhooks) | O sistema já manda webhook. Você aponta para `POST /v1/ingest/webhook/{source_id}`, e um mapeamento versionado transforma o payload em evento                                                                           |
| Importação de arquivo                       | O sistema não tem webhook e exporta arquivos: mande um JSONL de itens do lote para [`POST /v1/ingest/files`](/api/ingest-files), com até 512 MB, e acompanhe por [`GET /v1/ingest/files/{import_id}`](/api/ingest-file) |
| API                                         | O seu código já sabe do evento e manda pelo SDK ou por `POST /v1/batch`                                                                                                                                                 |

<CodeGroup>
  ```python Python theme={null}
  from niadra import Niadra, system_id

  niadra = Niadra()

  niadra.track({
      "kind": "system_event",
      "channel": "erp",
      "canonical_type": "invoice.credited",
      "idempotency_key": "erp-inv-0823-credit-1",
      "handles": [system_id("crm", "48213")],
      "object_refs": [{"type": "invoice", "namespace": "erp", "id": "0823"}],
      "speaker": {"role": "system"},
      "fields": {"amount": 40.0, "currency": "USD"},
  })
  ```

  ```typescript TypeScript theme={null}
  niadra.track({
    kind: "system_event",
    channel: "erp",
    canonical_type: "invoice.credited",
    idempotency_key: "erp-inv-0823-credit-1",
    handles: [handles.systemId("48213", "crm")],
    object_refs: ["invoice:erp:0823"],
    speaker: "system",
    fields: { amount: 40.0, currency: "USD" },
  });
  ```

  ```bash cURL theme={null}
  curl -X POST "https://acme-prod.us-east-1.api.niadra.com/v1/batch" \
    -H "Authorization: Bearer $NIADRA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"items": [{"type": "event", "kind": "system_event", "channel": "erp",
         "canonical_type": "invoice.credited", "idempotency_key": "erp-inv-0823-credit-1",
         "handles": [{"type": "system_id", "value": "48213", "scope": "crm"}],
         "object_refs": [{"type": "invoice", "namespace": "erp", "id": "0823"}],
         "speaker": {"role": "system"}, "fields": {"amount": 40.0, "currency": "USD"},
         "occurred_at": "2026-09-22T17:06:21Z"}]}'
  ```
</CodeGroup>

Evento de sistema é dado estruturado e entra **sem modelo de IA**: o mapeamento extrai tipo, objeto, os ids do cliente, campos e horário. Só tipos mapeados entram na memória, o que protege a memória do volume de um ERP. O payload cru de um tipo não mapeado fica 7 dias guardado para você remapear, e não entra na memória. Texto livre de dentro de um sistema, como a descrição de um ticket, entra como `message` num canal próprio e passa pela extração normal.

Eventos de sistema não entram na cobrança. A unidade continua sendo a conversa ou tarefa.

## Objetos de negócio

Pedido, ticket, fatura, contrato, entrega e assinatura são **objetos**. Cada um é identificado pelo trio `type`, `namespace` e `id`, único no espaço, como `invoice:erp:0823`. Os SDKs aceitam essa forma curta.

O objeto se prende ao cliente pelo id dele naquele sistema, o handle `system_id`, e guarda a linha do tempo de eventos e ações e um **estado derivado**, sempre com `as_of`, a fonte e a referência ao registro de origem. **O valor oficial continua no seu sistema.** A memória guarda o bastante para o agente lembrar e agir, e aponta para a origem. Uma separação de perfis leva os pedidos e as faturas para o dono certo sozinha, porque o objeto está preso ao handle de origem.

Leia um objeto por [`GET /v1/objects/{object_type}/{namespace}/{external_id}`](/api/object) e os eventos e ações dele por [`/timeline`](/api/object-timeline), as duas com o escopo `context` e comprovante. Os ids podem ter barra e dois-pontos. Nos SDKs, `object_state()` e `object_timeline()` em Python, `objectState()` e `objectTimeline()` em TypeScript:

<CodeGroup>
  ```python Python theme={null}
  invoice = niadra.object_state("invoice:erp:0823")
  if invoice:
      print(invoice.state, invoice.as_of, invoice.open_items)
  ```

  ```typescript TypeScript theme={null}
  const { data: invoice } = await niadra.objectState("invoice:erp:0823");
  if (invoice) console.log(invoice.state, invoice.as_of, invoice.open_items);
  ```

  ```bash cURL theme={null}
  curl "https://acme-prod.us-east-1.api.niadra.com/v1/objects/invoice/erp/0823" \
    -H "Authorization: Bearer $NIADRA_API_KEY"
  ```
</CodeGroup>

O seu time de governança vê todos os objetos de um cliente, com as ações sobre eles, por [`GET /v1/profiles/{profile_id}/objects`](/api/profile-objects).

## Ações de agente

Uma ação é o registro do que um agente, interno ou de atendimento, ou um atendente humano fez num sistema: a operação canônica (`credit`, `reschedule`), o objeto, o resultado, a finalidade e, opcionalmente, `closes`, a pendência que a ação cumpre.

<CodeGroup>
  ```python Python theme={null}
  niadra.action(
      "credit",
      subject=system_id("crm", "48213"),
      object="invoice:erp:0823",
      result="$40 credit on the August bill",
      closes={"object": {"type": "invoice", "namespace": "erp", "id": "0823"}, "operation": "dispute"},
      channel="erp",
      task_id="billing-7741",
  )
  ```

  ```typescript TypeScript theme={null}
  niadra.action({
    channel: "erp",
    task_id: "billing-7741",
    handles: [handles.systemId("48213", "crm")],
    object_refs: ["invoice:erp:0823"],
    operation: "credit",
    result: "$40 credit on the August bill",
    closes: { object: { type: "invoice", namespace: "erp", id: "0823" }, operation: "dispute" },
  });
  ```
</CodeGroup>

`closes` aponta a pendência pelo `item_id` ou pelo par objeto e operação, nunca pelos dois. Registrar ação exige o escopo `act` da chave, para aquela operação e aquele tipo de objeto; `track` sozinho não basta. A ação é imutável: uma correção é uma ação nova com `corrects_action_id`.

### Declarada, confirmada, divergente

| Estado      | Quando                                                                                                                                                 |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `declared`  | O agente registrou e o sistema de registro ainda não confirmou. O contexto diz isso: "declarado pela Cobrança às 14h06; o sistema ainda não confirmou" |
| `confirmed` | Chegou o evento do sistema que confirma, como `invoice.credited`. A ação e o evento viram um registro só, e o crédito nunca conta duas vezes           |
| `divergent` | A janela venceu sem confirmação. Você pode ser avisado por [gatilho](/concepts/triggers-and-webhooks)                                                  |

Ação declarada só fecha pendência quando a operação dela está nas `trusted_action_ops` da fonte; ação confirmada sempre fecha. Ações de uma sessão com trecho marcado como injeção de prompt ficam em quarentena: não fecham nada e não aparecem como feitas.

### Fechamento retroativo

A ação pode chegar antes da pendência. Às 14h05 Marina contesta a fatura no app, e a pendência só nasce quando a sessão do app fecha e é extraída, às 14h35. O agente de cobrança age às 14h06. Ao criar a pendência, a Niadra procura ações já aplicadas sobre o mesmo objeto e operação dentro da janela, e a pendência nasce `resolved`, fechada pela ação das 14h06.

## Contexto por tarefa

O agente interno lê o contexto centrado no objeto, com uma view de tarefa e o nível `no_customer`, porque não há cliente presente:

<CodeGroup>
  ```python Python theme={null}
  with niadra.task(
      "billing-7741",
      object="invoice:erp:0823",
      view="task:billing",
      verification="no_customer",
      channel="erp",
  ) as task:
      ctx = task.context()
      # o agente decide e lança o crédito no ERP, com as credenciais dele
      task.action("credit", result="$40 credit on the August bill")
  # ao sair do bloco, o SDK envia task.ended
  ```

  ```typescript TypeScript theme={null}
  const task = niadra.task({
    task_id: "billing-7741",
    channel: "erp",
    object: "invoice:erp:0823",
    view: "task:billing",
    verification: "no_customer",
  });
  const ctx = await task.context();
  // o agente decide e lança o crédito no ERP, com as credenciais dele
  task.action({ operation: "credit", object_refs: ["invoice:erp:0823"], result: "$40 credit on the August bill" });
  await task.end();
  ```
</CodeGroup>

A view de tarefa prioriza os objetos do tipo da tarefa, as pendências ligadas a eles e o que foi dito sobre eles nas conversas. O que a finalidade da fonte não permite fica de fora: o agente de cobrança lê faturas e contestações, não lê pendência técnica.

## O caminho das 14h06

1. **14h05, app:** a contestação entra e, em menos de 1 segundo, está legível e ligada a `invoice:erp:0823`.
2. **14h06, agente de cobrança:** lê o contexto da fatura, recebe a contestação pelo `live`, lança o crédito no ERP e registra a ação.
3. **14h06, ERP:** emite `invoice.credited`; a ação passa a `confirmed`.
4. **Em segundos:** o contexto de voz ganha "feito por outro agente: crédito de 40, confirmado pelo sistema".
5. **14h07, ligação:** o agente de voz diz que o crédito já foi lançado.

Nenhum modelo de IA fica no caminho entre a ação e o contexto de voz. Ação e evento de sistema chegam ao contexto recompilado em menos de 10 segundos.

<Note>
  A Niadra nunca escreve num sistema de registro. Quem age é o agente, com as credenciais dele. Para devolver o desfecho ao CRM, consuma os webhooks `action.recorded` e `open_item.closed`.
</Note>

## Próximos passos

<CardGroup cols={2}>
  <Card title="Agentes internos" href="/guides/internal-agents">
    o guia completo do agente de cobrança.
  </Card>

  <Card title="Webhooks dos seus sistemas" href="/guides/system-webhooks">
    mapeamento e autenticação.
  </Card>

  <Card title="Ler um objeto" href="/api/object">
    estado derivado e pendências abertas.
  </Card>
</CardGroup>
