How to Integrate Haystack for retail banking with Elasticsearch for AI agents
Combining Haystack for retail banking with Elasticsearch gives you a practical pattern for AI agents that need to answer customer questions from bank knowledge, policy docs, and product content without hallucinating. Haystack handles retrieval and orchestration; Elasticsearch gives you fast, structured search over large retail banking corpora like FAQs, fee schedules, product brochures, and support transcripts.
For retail banking agents, this setup is useful when you need grounded answers for things like card disputes, account opening requirements, mortgage eligibility, or branch-specific policies. The agent can retrieve relevant passages from Elasticsearch and pass them into Haystack components for response generation or decision support.
Prerequisites
- •Python 3.10+
- •An Elasticsearch cluster running locally or in your environment
- •A Haystack installation with the components you plan to use
- •Access to your retail banking documents in JSON, TXT, or PDF format
- •
pipinstalled - •Environment variables ready for:
- •
ELASTICSEARCH_URL - •
ELASTICSEARCH_API_KEYif your cluster requires auth
- •
Install the dependencies:
pip install haystack-ai elasticsearch
If you are using a managed Elasticsearch deployment, confirm the index name and mapping strategy before wiring it into the agent.
Integration Steps
- •Set up the Elasticsearch client and verify connectivity.
from elasticsearch import Elasticsearch
ELASTICSEARCH_URL = "http://localhost:9200"
es = Elasticsearch(ELASTICSEARCH_URL)
health = es.cluster.health()
print("cluster_status:", health["status"])
For production banking workloads, use TLS and API key authentication:
from elasticsearch import Elasticsearch
es = Elasticsearch(
"https://your-es-host:9200",
api_key=("id", "api_key_value"),
verify_certs=True,
)
- •Create an index for retail banking content.
Use a dedicated index for each document family if you need tighter access control. For example, keep product disclosures separate from internal policy notes.
index_name = "retail-banking-docs"
if not es.indices.exists(index=index_name):
es.indices.create(
index=index_name,
mappings={
"properties": {
"content": {"type": "text"},
"title": {"type": "text"},
"doc_type": {"type": "keyword"},
"branch_id": {"type": "keyword"}
}
}
)
print("index_ready:", es.indices.exists(index=index_name))
- •Index your banking documents so Haystack can retrieve them later.
This example uses the Elasticsearch bulk API directly. In a real system, you would batch documents from your CMS, knowledge base, or policy repository.
from elasticsearch.helpers import bulk
docs = [
{
"_index": index_name,
"_id": "faq_001",
"_source": {
"title": "Debit Card Replacement",
"content": "Customers can request a replacement debit card through online banking or by calling support.",
"doc_type": "faq",
"branch_id": "global"
},
},
{
"_index": index_name,
"_id": "policy_014",
"_source": {
"title": "Cash Deposit Limits",
"content": "Daily cash deposit limits may vary by account type and branch policy.",
"doc_type": "policy",
"branch_id": "global"
},
},
]
bulk(es, docs)
es.indices.refresh(index=index_name)
print("documents_indexed:", es.count(index=index_name)["count"])
- •Wire Elasticsearch into Haystack retrieval.
Haystack’s ElasticsearchDocumentStore is the bridge here. It stores documents in Elasticsearch and exposes them to retrievers used by your AI agent pipeline.
from haystack import Document
from haystack.document_stores.elasticsearch import ElasticsearchDocumentStore
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
document_store = ElasticsearchDocumentStore(
hosts=[{"host": "localhost", "port": 9200}],
index=index_name,
)
# Write Haystack documents into the store
haystack_docs = [
Document(
id="faq_001",
content="Customers can request a replacement debit card through online banking or by calling support.",
meta={"title": "Debit Card Replacement", "doc_type": "faq", "branch_id": "global"},
),
Document(
id="policy_014",
content="Daily cash deposit limits may vary by account type and branch policy.",
meta={"title": "Cash Deposit Limits", "doc_type": "policy", "branch_id": "global"},
),
]
document_store.write_documents(haystack_docs)
If you are using newer Haystack pipelines, keep retrieval explicit and small. For example:
from haystack.components.retrievers.in_memory import InMemoryBM25Retriever
retriever = InMemoryBM25Retriever(document_store=document_store)
results = retriever.run(query="How do I replace my debit card?")
print(results)
- •Connect retrieval to an agent flow.
A common production pattern is: user question -> retrieve top passages -> pass context to generator -> return grounded answer. You can plug this into your agent’s tool layer or orchestration layer.
from haystack.components.builders.prompt_builder import PromptBuilder
template = """
Answer the banking question using only the provided context.
Question: {{question}}
Context:
{% for doc in documents %}
- {{ doc.content }}
{% endfor %}
Answer:
"""
prompt_builder = PromptBuilder(template=template)
query = "How do I replace my debit card?"
retrieval_output = retriever.run(query=query)
prompt_output = prompt_builder.run(
question=query,
documents=retrieval_output["documents"],
)
print(prompt_output["prompt"])
At this point, your LLM call goes after prompt_output["prompt"]. Keep generation outside retrieval so you can swap models without touching search logic.
Testing the Integration
Run a direct retrieval test against both systems to confirm indexing and query flow are working.
query = "What are the rules for cash deposit limits?"
retrieval_output = retriever.run(query=query)
for doc in retrieval_output["documents"]:
print(doc.meta["title"], "-", doc.content)
Expected output:
Cash Deposit Limits - Daily cash deposit limits may vary by account type and branch policy.
If you get empty results:
- •Check that the Elasticsearch index contains documents
- •Confirm the document text field is mapped as searchable text
- •Verify Haystack is pointing at the same cluster and index name
- •Refresh the index after bulk writes
Real-World Use Cases
- •
Retail banking customer support agents
- •Answer account servicing questions from approved knowledge sources.
- •Ground responses in policy text instead of model memory.
- •
Internal banker copilot
- •Retrieve product eligibility rules, fee schedules, and compliance notes.
- •Help branch staff answer customer questions faster with consistent language.
- •
Dispute and fraud triage assistants
- •Search incident playbooks and case-handling procedures.
- •Surface relevant next steps based on issue type and product line.
This integration works because it separates responsibilities cleanly. Elasticsearch handles fast search over regulated content; Haystack turns those search results into agent-ready context for reliable answers.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit