Integrations
LlamaIndex
Web search as a LlamaIndex tool, and Lineage as a node postprocessor that trims retrieved nodes to the passages that answer the query.
1 min read ยท Updated 14 Sept 2026
On this page
Retrieved nodes are long, and a chunk cut from its page often names no one. "He said" and "last year" reach the model with nothing to resolve them. Flux adds live search to your agent and rewrites each node as the passages that answer the query, with the names and dates filled in.
Search toolGive your agent live web results it can quote and cite.Lineage postprocessorCut retrieved nodes down to the passages that answer the question.
Build it
Install
Shellpip install llama-index-core llama-index-llms-openai requestsexport FLUX_API_KEY="<your key>"Give your agent web search
A plain function is a tool. Your model plans and answers, and calls Flux for anything current.
Pythonimport asyncioimport osimport requestsFLUX = "https://fluxsearch.io/api/v1"HEADERS = {"Authorization": f"Bearer {os.environ['FLUX_API_KEY']}"}from llama_index.core.agent.workflow import FunctionAgentfrom llama_index.llms.openai import OpenAIdef web_search(query: str) -> str: """Search the live web. Returns passages with provenance and their source URLs.""" response = requests.post( f"{FLUX}/search", headers=HEADERS, json={"query": query, "max_results": 5, "enrich": 3}, timeout=120, ) response.raise_for_status() passages = [ f"{passage['enriched_text']} ({result['url']})" for result in response.json()["results"] for passage in (result["lineage"] or {}).get("results", []) ] return "\n\n".join(passages) or "No passages found."agent = FunctionAgent(tools=[web_search], llm=OpenAI(model="gpt-5-mini"))async def main(): print(await agent.run("Who runs Barclays?"))asyncio.run(main())Trim retrieved nodes
Wrap Lineage as a
BaseNodePostprocessorand pass it to any query engine.Pythonimport osimport requestsFLUX = "https://fluxsearch.io/api/v1"HEADERS = {"Authorization": f"Bearer {os.environ['FLUX_API_KEY']}"}from llama_index.core.postprocessor.types import BaseNodePostprocessorfrom llama_index.core.schema import NodeWithScore, TextNodeclass FluxLineage(BaseNodePostprocessor): def _postprocess_nodes(self, nodes, query_bundle=None): if query_bundle is None: return nodes kept = [] for node in nodes: response = requests.post( f"{FLUX}/provenance", headers=HEADERS, json={"text": node.node.get_content(), "query": query_bundle.query_str}, timeout=120, ) response.raise_for_status() for passage in response.json()["results"]: text = TextNode(text=passage["enriched_text"], metadata=node.node.metadata) kept.append(NodeWithScore(node=text, score=passage["score"])) return keptquery_engine = index.as_query_engine(node_postprocessors=[FluxLineage()])
Call Flux as an LLM
For a direct answer with no agent, use OpenAILike. Flux does not call tools, so leave function calling off.
Python
import osfrom llama_index.llms.openai_like import OpenAILikeflux = OpenAILike( model="flux-search-1", api_base="https://fluxsearch.io/api/v1", api_key=os.environ["FLUX_API_KEY"], is_chat_model=True, is_function_calling_model=False,)print(flux.complete("Who is the chief executive of Barclays?"))Next steps
LangChainWeb search as a LangChain tool, and Lineage as a document compressor that keeps only the passages that answer the question.Vercel AI SDKFlux as tools your AI SDK agent calls for live search and Lineage, or as a provider for grounded answers.API referenceBrowse every endpoint and see exactly what each one returns.