Skip to content

Complaints

Solution

A regulator does not ask what a complaint looks like today. They ask what you knew, and when you knew it, at each step of the process. Telha keeps every version of a complaint record, so "what was the state of complaint X on date Y" has a precise, provable answer instead of a reconstruction from memory.

The state questions complaints handling needs to answer

  • What was the state of complaint X (status, root cause, assigned owner) on date Y?
  • Which complaints breached their regulatory response window, and by how long?
  • What did we know about the root cause at the time the initial response was sent, versus what we know now?
  • Who recorded the resolution, and does the record match what the customer was actually told?
  • Which complaints have an undated or conflicting intake record that has never been resolved?
  • Between two conflicting accounts of the same complaint, which one is the steward-resolved version, and what happened to the other?

The audit trail is the point

A complaint's record is never overwritten. A correction to root cause or resolution writes a new version; the prior version stays reconstructable at its original transaction time. That append-only guarantee, described in the tritemporal model, is what lets you answer a regulator's question about what was believed at each prior step, not just the current, tidied-up state.

What to connect

Source Shipped connector What it feeds
Salesforce Salesforce connector Complaint/case records, root cause fields, resolution status, as format=json records
Email Exchange connector Intake correspondence and regulatory notifications, ingested as format=email
Slack Slack connector Internal investigation threads, ingested as format=json (SLACK_THREAD)
Intake forms and investigation reports (PDF/DOCX) Uploaded via /v1/ingest (docling) Root-cause writeups and regulatory filings, dated at their source-record time
Identity Entra ID connector Verified investigator and steward identity, for clarification routing, quorum, and RBAC

Example queries

All examples run against POST /v1/query. See the query language reference for the full grammar.

Open complaints past a severity threshold with no assigned owner
{
  "find": "COMPLAINT",
  "where": {
    "status": { "$eq": "open" },
    "severity": { "$gte": 3 },
    "owner": { "$exists": false }
  },
  "limit": 100
}
Every open complaint at severity 3 or above sitting without an assigned owner, a worklist for triage.

The exact state of a complaint on a past date
{
  "find": "COMPLAINT",
  "where": { "complaintNumber": { "$eq": "CMP-2026-0417" } },
  "atValidTime": "2026-05-02T00:00:00Z"
}
Reconstructs status, root cause, and owner for complaint CMP-2026-0417 exactly as they stood on May 2, regardless of edits made since.

What was believed about root cause before a later correction
{
  "find": "COMPLAINT",
  "where": { "complaintNumber": { "$eq": "CMP-2026-0417" } },
  "atValidTime": "2026-05-02T00:00:00Z",
  "atTxTime": "2026-05-04T00:00:00Z"
}
Pins both clocks: the complaint's state on May 2, as Telha had it recorded by May 4, before a subsequent root-cause correction. This is what the response letter drafted on May 4 would have been based on.

Complaints whose response window may have breached
{
  "find": "COMPLAINT",
  "where": {
    "$and": [
      { "status": { "$in": ["open", "escalated"] } },
      { "responseDueDate": { "$lt": "2026-07-01T00:00:00Z" } }
    ]
  },
  "expand": ["OWNED_BY"]
}
Finds complaints still open or escalated past their due date, expanded to the assigned owner, a first pass at identifying SLA breaches.

A verified answer in practice

Question posed to /v1/generate: "What was the root cause of complaint CMP-2026-0417 as understood on the date the initial response was sent, and has it changed since?"

{
  "question": "What was the root cause of CMP-2026-0417 as understood on the date the initial response was sent, and has it changed since?",
  "query": { "find": "COMPLAINT", "where": { "complaintNumber": { "$eq": "CMP-2026-0417" } } },
  "atValidTime": "2026-05-02T00:00:00Z",
  "expandDepth": 1
}
{
  "draft": "As of the initial response on May 2, 2026, the recorded root cause was a labeling error in the shipping process [S1]. A subsequent investigation update on May 9, 2026 revised the root cause to a packaging defect upstream of labeling [S2]; the May 2 record remains the version the initial response was based on.",
  "verification": {
    "status": "verified",
    "claims": [
      { "text": "recorded root cause was a labeling error in the shipping process", "verdict": "supported", "span": "S1" },
      { "text": "revised the root cause to a packaging defect upstream of labeling", "verdict": "supported", "span": "S2" }
    ]
  }
}

S1 traces to the complaint record's root-cause field as it stood at the queried valid time, the version underlying the May 2 letter. S2 traces to the investigator's written update in the case system that superseded it. Both spans, and both fact versions, remain independently reconstructable per the tritemporal model; nothing about the May 9 correction erases what the record said on May 2, which is exactly what a regulator asking "what did you know when you responded" needs.

When the intake record is undated or conflicting

A scanned intake form with no legible date, or two staff members logging different incident dates for the same complaint, triggers a clarification rather than a silent guess: a best-guess date is applied at reduced confidence, and a one-tap card routes to the complaint's recorded author or owner to confirm. High-severity or regulatory-relevant complaints can be configured to require quorum, more than one confirmation, before the date binds.

Evidence and permissions

  • Provenance for regulators. Every fact in a complaint's history, including superseded versions, carries provenance to the exact source span, so a regulatory response can cite not just what you concluded but the document and byte range it came from at each stage.
  • RBAC for sensitive records. Complaint records often name individuals and involve sensitive allegations; access is deny-by-default, mapped from Entra groups, so only the investigation team and compliance roles can read a given case.
  • Field-level encryption. Fields declared classified (complainant personal details, medical or safety specifics) are encrypted in the app layer before core ever sees them, and are excluded from indexing and vector search as a result.
  • Clarifications carry accountability. A clarification answer binds to the responder's verified Entra identity, never a chat display name, and a steward's resolution of conflicting accounts is itself recorded append-only, with every prior conflicting answer still visible in the record. See Clarifications.