Highlight widget citations
After retrieving widget data, attribute outputs to their sources. Build cite(...)
entries and stream them with citations(...)
so Workspace shows a citations panel next to the answer.
Reference implementation in this GitHub repository.

Architecture
This pattern extends "Parse widget data" by adding attribution. After data retrieval, emit citations to show provenance in Workspace.
agents.json
configuration with widget-dashboard-select
feature enabled:
return JSONResponse(content={
"vanilla_agent_raw_widget_data_citations": {
"endpoints": {"query": "http://localhost:7777/v1/query"},
"features": {
"streaming": True,
"widget-dashboard-select": True,
"widget-dashboard-search": False,
},
}
})
Query flow
- Early exit: fetch widget data when human message contains
widgets.primary
- On subsequent tool message:
- Process widget data and include in LLM context
- Match widget UUIDs from tool
input_arguments
torequest.widgets.primary
- Build
cite()
objects for each data source used - Stream citations with
citations()
after LLM response
- Citations appear in Workspace UI panel for source verification
OpenBB AI SDK
cite(widget, input_arguments, extra_details)
: CreatesCitation
objectscitations(citation_list)
: EmitsCitationCollectionSSE
eventsCitation
: Links outputs to data sources with metadataSourceInfo
: Provides detailed source attribution data
Core logic
Build citations by matching the tool input arguments to widgets in the request:
from openbb_ai import cite, citations
from openbb_ai.models import Citation, CitationHighlightBoundingBox
async def execution_loop():
# ... stream LLM response ...
# Build citations after response
citations_list = []
# Process tool message to find data sources
for message in request.messages:
if message.role == "tool":
for widget_data_request in message.input_arguments["data_sources"]:
# Match widget by UUID
matching_widgets = [
w for w in request.widgets.primary
if str(w.uuid) == widget_data_request["widget_uuid"]
]
if matching_widgets:
widget = matching_widgets[0]
citation = cite(
widget=widget,
input_arguments=widget_data_request["input_args"],
extra_details={
"Widget Name": widget.name,
"Data Source": widget.type,
"Parameters Used": widget_data_request["input_args"]
}
)
citations_list.append(citation)
# Emit citations for UI display
if citations_list:
yield citations(citations_list).model_dump()