Add Evidence to Text Responses
The evidence stream wraps the attributed completion stream and reconstructs semantic evidence from it: it detects the output kind early, segments the visible text into stable claims, and links every claim to the context sources that ground it. The underlying completion chunks are preserved, so you can render streaming text exactly as before.
Stream claims with grounding scores
- TypeScript
- Python
for await (const event of client.chat.completions.streamWithEvidence({
messages: [{ role: "user", content: "Summarize the incident report." }],
maxTokens: 256,
topKAttributions: 12,
})) {
if (event.type === "completion_chunk") {
render(event.chunk); // unchanged streaming text
}
if (event.type === "claim_evidence") {
console.log(
event.evidence.text,
event.evidence.verdict,
event.evidence.groundingScore,
event.evidence.sources.map((source) => source.sourceId),
);
}
if (event.type === "response_evidence") {
console.log("overall:", event.evidence.overallGrounding);
}
}
from invera_sdk import ChatMessage, CompletionRequest
request = CompletionRequest(
messages=[ChatMessage("user", "Summarize the incident report.")],
max_tokens=256,
top_k_attributions=12,
)
for event in client.chat.completions.stream_with_evidence(request):
if event.type == "completion_chunk":
render(event.chunk) # unchanged streaming text
if event.type == "claim_evidence":
print(
event.evidence.text,
event.evidence.verdict,
event.evidence.grounding_score,
[source.source_id for source in event.evidence.sources],
)
if event.type == "response_evidence":
print("overall:", event.evidence.overall_grounding)
Event order
output_kind— emitted once, as soon as the kind of the first output is observed (textortool_call). Use it to pick a rendering surface early. A response may still continue with the other kind; the final report then saysmixed.completion_chunk— every attributed chunk, passed through unchanged.claim_evidence— emitted whenever a claim becomes stable (at sentence boundaries, newlines, or themax_claim_charslimit).tool_call_evidence— emitted after each completed tool call (see Validate and gate tool calls).response_evidence— one final report with all claims, all tool calls, the overall grounding, and arequires_reviewflag.
Reading a claim verdict
Without a verifier, verdicts describe attribution grounding only — how strongly the generated words trace back to context — and are deliberately not presented as factual verification:
| Verdict | Meaning |
|---|---|
grounded | Grounding score at or above 0.65. |
partially_grounded | Grounding score between 0.3 and 0.65. |
ungrounded | Grounding score below 0.3. |
How the grounding score is composed is documented in Evidence and verdicts.
Optional: semantic verification
A host-provided verifier (for example an entailment model or an LLM judge)
receives each claim with its sources and can promote the verdict to
supported or overturn it to contradicted:
- TypeScript
- Python
const events = client.chat.completions.streamWithEvidence(request, {
verifier: async ({ claim, sources }) => ({
relation: (await entails(sources, claim)) ? "entails" : "unknown",
score: 0.9,
}),
});
from invera_sdk import EvidenceOptions, SemanticVerification
def verify(input):
relation = "entails" if entails(input.sources, input.claim) else "unknown"
return SemanticVerification(relation, 0.9)
events = client.chat.completions.stream_with_evidence(
request, EvidenceOptions(verifier=verify)
)
A contradicts or entails relation with a score of at least 0.5 takes
precedence over the attribution-based verdict; claims judged this way report
method as attribution_and_verifier.