Skip to content
Dashboard

Ask what to do with a Q&A entry

POST/v2/training_data/oracle

Checks a proposed Q&A without writing. Optional externalId or an existing normalized question addresses a target. Changed content is compared with that entry even if retrieval or excludeIds misses it. The judge continues past agreement to detect later contradictions; uncertainty takes precedence over agreement. Another agreeing Q&A remains visible for duplicate review.

Actions: create means no overlap found in checked candidates; update_target refers to existing; update_qna refers to target; review_qna / review_article / review_file require review of the source; skip means an identical payload or already-covered answer. existing and Q&A candidates include revisions: use PATCH expectedRevision for a subsequent reviewed update.

The evidence is bounded: retrieval can miss knowledge, document excerpts omit context, and checks observe changing data. checkTruncated reports verification shortlist or text limits and yields unclear unless a contradiction was found. False does not imply exhaustive coverage or factual correctness. Inspect full sources before promotion. Dependencies failing returns 503; this endpoint never writes.

Header ParametersExpand Collapse
"Featurebase-Version": optional "2026-08-19.orbit" or "2026-01-01.nova" or "2025-12-12.clover"
One of the following:
"2026-08-19.orbit"
"2026-01-01.nova"
"2025-12-12.clover"
Body ParametersJSONExpand Collapse
answer: string

The answer the entry would give. Compared by the judge, never used as a search query.

minLength1
maxLength100000
questions: array of string

Question variants this answer applies to (1–50). Phrase them the way customers ask.

answerFormat: optional "markdown" or "html"

Format of answer. markdown (default) is stored as-is; html is converted to markdown.

One of the following:
"markdown"
"html"
excludeIds: optional array of string

Q&A entry / training file IDs to omit from retrieval. The addressed Q&A entry is still compared when its content changes.

externalId: optional string

Stable identity of the would-be Q&A entry. The oracle only reads; it never creates or updates it.

minLength1
maxLength255
title: optional string

Short label for the would-be entry (also used as a search query)

minLength1
maxLength500
ReturnsExpand Collapse
Oracle object { action, candidates, checkTruncated, 7 more }
action: "create" or "update_target" or "update_qna" or 4 more

Suggested next step. create: no overlap found in the checked candidates; verify the source before writing. update_target: an entry already carries one of these questions (existing) and should be updated with this content — use PATCH with expectedRevision from existing to bind the write to this check. update_qna: an existing Q&A entry already answers this with the same facts — merge into it (target) instead of adding a second one. review_qna / review_article / review_file: an existing item (target) contradicts this answer or the judge could not decide — a human should pick the right fact and fix the source. skip: the knowledge already exists (an article or file answers it, or the payload is identical to the entry that already carries the question); nothing to write.

One of the following:
"create"
"update_target"
"update_qna"
"review_qna"
"review_article"
"review_file"
"skip"
candidates: array of KnowledgeMatchCandidate { id, externalId, kind, 8 more }

Retrieved items and the addressed entry (first when present), at most 10. Excerpts are partial evidence.

id: string

ID of the existing item

externalId: string

The item’s source identity, for training files and Q&A

kind: "qna" or "training_file" or "help_center_article"

What kind of knowledge item matched: a Q&A entry, a training file / crawled page, or a live help-center article.

One of the following:
"qna"
"training_file"
"help_center_article"
questions: array of string

Question variants, for Q&A entries

revision: number

Q&A revision compared by the judge; null for other kinds. Use with PATCH expectedRevision.

section: string

Heading breadcrumb of the matching section, for training files

similarity: number

Cosine similarity between the query and item. Calibrate any threshold using representative examples; it is not a correctness or contradiction score. null when the item was found by keywords only. Arrays are already ordered closest first.

source: string

The item’s source label, for Q&A entries and training files

text: string

Excerpt of the existing content the judge compared against (Q&A answer, matching document section, or article body), up to 1200 characters plus an ellipsis when cut.

title: string

Title of the existing item

url: string

Public URL of the item when it has one

checkTruncated: boolean

A candidate or text budget limited verification (including clipped proposed answers or Q&A answers). This yields unclear unless a contradiction was already found. False does not mean the entire workspace was exhaustively checked.

existing: object { id, question, revision }

The Q&A entry addressed by externalId or a normalized question, including its checked revision, or null

id: string

Q&A entry ID

question: string

Matching question from your request, or its first question when addressed by externalId

revision: number

Revision of the addressed entry at check time. Use with PATCH expectedRevision.

judged: array of object { candidateId, kind, reason, verdict }

Per-candidate judge verdicts, in the order they were judged. Judging continues after agreement or uncertainty and stops on a contradiction. The addressed entry is always compared when its content changes. Only shortlisted candidates are judged, so this is usually shorter than candidates.

candidateId: string

ID of the judged candidate

kind: "qna" or "training_file" or "help_center_article"

What kind of knowledge item matched: a Q&A entry, a training file / crawled page, or a live help-center article.

One of the following:
"qna"
"training_file"
"help_center_article"
reason: string

The judge’s one-line explanation

verdict: "same_topic" or "contradicts" or "different" or "unclear"

The judge’s verdict for this candidate

One of the following:
"same_topic"
"contradicts"
"different"
"unclear"
object: "oracle"

Object type identifier

reason: string

One or two sentences explaining the action, from the judge when it ran

target: KnowledgeMatchCandidate { id, externalId, kind, 8 more }

The existing item the action refers to, with its excerpt; null for create / update_target. For a different verdict the closest miss is candidates[0].

timings: object { judgeCalls, judgeMs, retrievalMs }

Where the time went

judgeCalls: number

Number of judge calls made

judgeMs: number

Time spent in the judge

retrievalMs: number

Time spent searching

verdict: "same_topic" or "contradicts" or "different" or 2 more

How the closest existing item relates to the entry. same_topic: it answers the same customer question (the entry would be a duplicate, rewording, or updated version). contradicts: same question, incompatible facts. different: a different question, even if the wording overlaps. unclear: the judge could not decide. no_match: nothing similar was found.

One of the following:
"same_topic"
"contradicts"
"different"
"unclear"
"no_match"

Ask what to do with a Q&A entry

curl https://do.featurebase.app/v2/training_data/oracle \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $FEATUREBASE_API_KEY" \
    -d '{
          "answer": "You can request a refund within 30 days from **Settings → Billing**.",
          "questions": [
            "How do I request a refund?",
            "Can I get my money back?"
          ],
          "answerFormat": "markdown",
          "excludeIds": [
            "67ec1234abcd5678ef901235"
          ],
          "title": "Refund requests"
        }'
{
  "action": "review_article",
  "candidates": [
    {
      "id": "67ec1234abcd5678ef901236",
      "externalId": null,
      "kind": "qna",
      "questions": [
        "How do I request a refund?"
      ],
      "revision": 1,
      "section": null,
      "similarity": 0.61,
      "source": null,
      "text": "You can request a refund within 30 days from **Settings → Billing**.",
      "title": "Refund requests",
      "url": null
    }
  ],
  "checkTruncated": true,
  "existing": {
    "id": "67ec1234abcd5678ef901234",
    "question": "How long do refunds take?",
    "revision": 1
  },
  "judged": [
    {
      "candidateId": "67ec1234abcd5678ef901236",
      "kind": "qna",
      "reason": "Both answer how to request a refund.",
      "verdict": "same_topic"
    }
  ],
  "object": "oracle",
  "reason": "The new entry says 14 days; the article says 30 days.",
  "target": {
    "id": "67ec1234abcd5678ef901236",
    "externalId": null,
    "kind": "qna",
    "questions": [
      "How do I request a refund?"
    ],
    "revision": 1,
    "section": null,
    "similarity": 0.61,
    "source": null,
    "text": "You can request a refund within 30 days from **Settings → Billing**.",
    "title": "Refund requests",
    "url": null
  },
  "timings": {
    "judgeCalls": 1,
    "judgeMs": 610,
    "retrievalMs": 420
  },
  "verdict": "same_topic"
}
Returns Examples
{
  "action": "review_article",
  "candidates": [
    {
      "id": "67ec1234abcd5678ef901236",
      "externalId": null,
      "kind": "qna",
      "questions": [
        "How do I request a refund?"
      ],
      "revision": 1,
      "section": null,
      "similarity": 0.61,
      "source": null,
      "text": "You can request a refund within 30 days from **Settings → Billing**.",
      "title": "Refund requests",
      "url": null
    }
  ],
  "checkTruncated": true,
  "existing": {
    "id": "67ec1234abcd5678ef901234",
    "question": "How long do refunds take?",
    "revision": 1
  },
  "judged": [
    {
      "candidateId": "67ec1234abcd5678ef901236",
      "kind": "qna",
      "reason": "Both answer how to request a refund.",
      "verdict": "same_topic"
    }
  ],
  "object": "oracle",
  "reason": "The new entry says 14 days; the article says 30 days.",
  "target": {
    "id": "67ec1234abcd5678ef901236",
    "externalId": null,
    "kind": "qna",
    "questions": [
      "How do I request a refund?"
    ],
    "revision": 1,
    "section": null,
    "similarity": 0.61,
    "source": null,
    "text": "You can request a refund within 30 days from **Settings → Billing**.",
    "title": "Refund requests",
    "url": null
  },
  "timings": {
    "judgeCalls": 1,
    "judgeMs": 610,
    "retrievalMs": 420
  },
  "verdict": "same_topic"
}