LlamaIndex is an index-first framework for structuring and querying private knowledge bases. Connecting ODEN introduces temporal public web retrieval directly into LlamaIndex's indexing hierarchy without requiring custom scraping middleware.
As a LlamaIndex FunctionTool#
Expose ODEN as a callable tool for LlamaIndex OpenAIAgent or ReActAgent instances:
import os, requests
from llama_index.core.tools import FunctionTool
def query_live_web(search_topic: str) -> str:
"""Query current public web intelligence, returning a concise summary and validated references."""
endpoint = "https://api.oden-api.com/search"
auth_header = {"Authorization": f"Bearer {os.environ['ODEN_KEY']}"}
payload = {"query": search_topic, "include_snippets": True, "depth": "advanced"}
response = requests.post(endpoint, headers=auth_header, json=payload, timeout=25)
response.raise_for_status()
payload_data = response.json()["results"]
formatted_sources = "\n".join(
f"• {item['title']} - {item['url']} (confidence: {item['score']:.2f})"
for item in payload_data["citations"]
)
return f"Synthesized Finding:\n{payload_data.get('answer','')}\n\nAttributed Citations:\n{formatted_sources}"
oden_tool = FunctionTool.from_defaults(
fn=query_live_web,
name="live_internet_research",
description="Fetches verified, up-to-date web information with source citations."
)
As a custom LlamaIndex retriever#
Transform ODEN citations directly into native NodeWithScore objects for seamless inclusion in composable query engines:
import os, requests
from llama_index.core.retrievers import BaseRetriever
from llama_index.core.schema import NodeWithScore, TextNode
class OdenWebRetriever(BaseRetriever):
def _retrieve(self, query_bundle):
headers = {"Authorization": f"Bearer {os.environ['ODEN_KEY']}"}
req_body = {
"query": query_bundle.query_str,
"include_snippets": True,
"depth": "advanced"
}
resp = requests.post("https://api.oden-api.com/search", headers=headers, json=req_body, timeout=25)
resp.raise_for_status()
nodes_with_scores = []
for cit in resp.json()["results"]["citations"]:
text_chunk = cit.get("snippet") or f"{cit['title']}: {cit['url']}"
meta_info = {"title": cit["title"], "source_url": cit["url"]}
node = TextNode(text=text_chunk, metadata=meta_info)
nodes_with_scores.append(NodeWithScore(node=node, score=float(cit["score"])))
return nodes_with_scores
SubQuestionQueryEngine for multi-hop research#
For complex research questions that require decomposing a query into sub-problems, pair ODEN with LlamaIndex's SubQuestionQueryEngine:
from llama_index.core.query_engine import SubQuestionQueryEngine
from llama_index.core.tools import QueryEngineTool, ToolMetadata
# Wrap the ODEN retriever into a dedicated query engine
oden_engine = custom_query_engine_from_retriever(OdenWebRetriever())
tools = [
QueryEngineTool(
query_engine=oden_engine,
metadata=ToolMetadata(
name="live_web_engine",
description="Searches the live public internet for current technical and news events."
)
),
QueryEngineTool(
query_engine=internal_vector_engine,
metadata=ToolMetadata(
name="internal_docs_engine",
description="Searches company private knowledge base and internal engineering wikis."
)
)
]
sub_engine = SubQuestionQueryEngine.from_defaults(query_engine_tools=tools)
response = sub_engine.query("Compare our internal Q3 roadmap goals with emerging regulatory requirements in the EU.")
Custom node post-processing#
Use LlamaIndex's node postprocessors to filter citation nodes by confidence score:
from llama_index.core.postprocessor import SimilarityPostprocessor
# Prune retrieved citation nodes with score below 0.65
postprocessor = SimilarityPostprocessor(similarity_cutoff=0.65)
filtered_nodes = postprocessor.postprocess_nodes(nodes)
Asynchronous query execution with aquery#
For modern async microservices built with FastAPI or asyncio event loops, execute LlamaIndex query engines asynchronously:
# Non-blocking query execution in asynchronous event loops
response = await sub_engine.aquery(
"Synthesize the current status of EU generative AI model safety benchmarks."
)
print(str(response))
Notes#
- The tool is best for agents that decide when to search; the retriever is best for query engines that expect nodes.
scoremaps straight ontoNodeWithScore, so LlamaIndex ranking works out of the box.- Combine
OdenWebRetrieverwith your own index retriever for hybrid private + web retrieval.
FAQ#
Can I combine ODEN with a LlamaIndex vector index?#
Yes. Use a router or a composable retriever: your vector index for private data, OdenWebRetriever for the live web.
Does ODEN return LlamaIndex nodes directly?#
No — it returns JSON. The OdenWebRetriever above maps that JSON to NodeWithScore in a few lines.
Which is better, tool or retriever?#
Tool for agentic flows where the model chooses to search; retriever for deterministic query engines. Many apps use both.