Responses
- Citations live in
- output[] → message → output_text.annotations[]
- Sources live in
- output[] → file_search_call.results[]
Recommended. Streaming sends one annotation.added event per citation and the full results in response.completed.
Calypso Context · Citations
A grounded answer carries inline citations anchored to the text by character offsets, and a structured list of the sources it drew on: source number, label, page, modality, and a signed link to open the original. Your app renders references without parsing the answer.
The example
Native mode keeps the response fully OpenAI-shaped: annotations on the text, sources in file_search_call.results. Nothing to parse, nothing vendor-specific to learn.
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["CALYPSO_API_KEY"],
base_url="https://api.calypso.so/v1")
resp = client.responses.create(
model="calypso-agent",
input="What is our refund policy?",
metadata={"citation_compat": "native", "sources_appendix": "omit"},
)
print(resp.output_text)
for item in resp.output:
if item.type == "file_search_call":
for r in item.results:
a = r.attributes
print(f"[{a['source_index']}] {a['label']}") # refund_policy_2026.pdf (p. 4)Two surfaces
Both endpoints carry citations. Responses exposes the full structured surface; Chat Completions is limited to the url_citation shape that spec defines.
Recommended. Streaming sends one annotation.added event per citation and the full results in response.completed.
File and media sources map to url_citation with a signed URL when one exists and the filename as title. When streaming, annotations arrive in a final chunk.
The attributes
The same attributes appear on Responses results and on Search results. Build your source list from them directly.
| source_index | Stable, 1-based source number that matches the [n] order in the text. Use it for badges and the list. |
|---|---|
| label | Display-ready, for example refund_policy_2026.pdf (p. 4). Falls back to the filename. |
| page_number · page_label · locator_label | Where in the document, when known. PDFs cite the page; other documents cite the file. |
| modality · mime_type | text, multimodal, or image, and the MIME type. An image citation points at the image itself. |
| access_url · media_id | A signed URL to open the original when one is available, and media identifiers for previews. |
| text · excerpt · preview | The quoted evidence the answer drew on, plus structured excerpt and preview descriptors. |
How it works
Call Responses with calypso-agent or a named agent. Retrieval runs against its buckets and the evidence comes back with the answer.
Each annotation carries start_index and end_index. Place your [n] markers from the offsets, numbered by source_index.
Render the source list from the attributes, and link each entry to its access_url so a reader can check the page.
Rendering
01
Use start_index and end_index to place references. Do not parse [n] tokens out of the text.
02
It is stable, 1-based, and consistent with citation order. Use it for badges and the list.
03
Apply annotations in descending start_index order so earlier insertions do not shift later offsets.
04
Render a sources panel only when grounded_sources_state is available. hidden means policy suppresses sources; missing and none mean there is nothing to show.
From the docs
| Model | OpenAI annotations: citation objects anchored to the text by character offsets; the answer text stays plain |
|---|---|
| Responses | output[] → message → output_text.annotations[] · output[] → file_search_call.results[] |
| Chat Completions | choices[0].message.annotations[] (url_citation) + "Sources:" appendix |
| Compatibility modes | metadata.citation_compat: legacy | native · metadata.sources_appendix: include | omit |
| Streaming event | response.output_text.annotation.added |
| Page-level citations | PDFs, which are read as page images; images cite the image; other documents cite the file |
| Grounding states | available · hidden · missing · none |
Questions and answers
Keep reading
PDFs, images, pages, and data. What it reads and how it gets in.
Scoped, durable source memory. Provision by slug, bind to agents.
One default, any number of named agents with their own scope and policy.
Retrieval without generation: the passages an answer would cite, ranked.
Yours, isolated: no training on your data, export or delete any time, keys with explicit scopes.
The reference this page is written from, with every endpoint and field.
Start today
Load a bucket, ask calypso-agent, and render the source list from the first response.