Skip to content

Support assistant

The failure this prevents: a customer asks about refunds after 30 days, your help centre never says, and the assistant invents a policy. Now you either honour a refund policy you never wrote, or you tell a customer your own bot was wrong.

  1. Ingest the help centre. Markdown, HTML, PDFs and a crawled site all work; ingest is idempotent by content hash, so re-running is cheap and safe.

    for path in Path("help-centre").rglob("*.md"):
    rag.ingest(path)
  2. Answer in strict mode — the default.

    response = rag.ask(customer_question)
  3. Branch on the decision, and never paper over a refusal.

    from citenexus.answer.result import Decision
    if response.evidence.decision is Decision.answered:
    src = response.sources[0]
    reply(response.answer, cite=(src.document, src.source_uri))
    else:
    escalate_to_human(customer_question, reason=response.missing_evidence)

The refusal is a feature, and it is routable

Section titled “The refusal is a feature, and it is routable”

A refusal is not a dead end — it is a signal that your documentation has a hole. missing_evidence tells you which one:

response.missing_evidence
# ('no sufficiently relevant evidence found',)

Log every refusal with its question. The result is a ranked list of what your help centre should say next, generated by real customer demand rather than guesswork. That is usually worth more than the answers.

rag.ask("Do you ship to Ireland?", conversation_id="ticket-8891")
rag.ask("How long does it take?", conversation_id="ticket-8891")

Conversation memory is partition-scoped and keyed by conversation_id, so one ticket’s turns can never surface in another’s.

from citenexus.domain.trust import TrustMode
rag.ask(q, mode=TrustMode.strict) # default — refuse unless clearly supported
rag.ask(q, mode=TrustMode.normal) # answer with signals surfaced

For a public-facing bot, keep strict. The cost of a refusal is one escalation; the cost of an invented policy is a support incident and, in a regulated industry, potentially a commitment you have to honour.

Re-ingest is idempotent by content hash, so a nightly sync only re-embeds what actually changed. When a page is retired, revoke it rather than leaving it indexed — a deleted help article that still answers questions is worse than no article:

rag.delete("help/legacy-refund-policy")

See Right to erasure for proving the removal was complete, and Regulated audit for catching pages that were never supposed to be indexed at all.