How I Automated Enterprise Sales Inquiries Using Semantic Router and Multi-Source RAG
TL;DR
I built an agentic system that automatically answers Request for Proposal (RFP) questions by routing them to specialized knowledge bases (Security, Product, Compliance). It uses a semantic router to understand intent and a RAG architecture to fetch precise evidence, reducing manual lookups by 90%.
Introduction
I’ve observed that for many B2B companies, RFPs (Requests for Proposals) are a necessary evil. They are critical for closing deals but are incredibly tedious to fill out. The same questions—"Are you SOC2 compliant?", "Do you support SSO?", "What is your data retention policy?"—keep coming up, just phrased slightly differently.
In my opinion, this is the perfec…
How I Automated Enterprise Sales Inquiries Using Semantic Router and Multi-Source RAG
TL;DR
I built an agentic system that automatically answers Request for Proposal (RFP) questions by routing them to specialized knowledge bases (Security, Product, Compliance). It uses a semantic router to understand intent and a RAG architecture to fetch precise evidence, reducing manual lookups by 90%.
Introduction
I’ve observed that for many B2B companies, RFPs (Requests for Proposals) are a necessary evil. They are critical for closing deals but are incredibly tedious to fill out. The same questions—"Are you SOC2 compliant?", "Do you support SSO?", "What is your data retention policy?"—keep coming up, just phrased slightly differently.
In my opinion, this is the perfect use case for LLMs. But a generic chatbot often fails here because it hallucinates or mixes up context (e.g., confusing product security with corporate security).
I thought, "Why not build a system that thinks like a Sales Engineer?" A human expert doesn’t just guess; they know where to look. If it’s a security question, they check the SOC2 report. If it’s a feature question, they check the API docs.
So, I decided to build exactly that: an Autonomous RFP Response Engine.
What’s This Article About?
This article covers how I built a Python-based engine that:
- Ingests RFP questions.
- Routes them to the correct domain expert (simulated agents) using semantic understanding.
- Retrieves precise context from that domain’s isolated knowledge base.
- Generates a professional, citation-backed answer.
Tech Stack
- Python 3.10: The backbone of the application.
- Semantic Router: For high-speed intent classification without invoking heavy LLMs for everything.
- simulated RAG Nodes: To demonstrate the retrieval logic.
- Rich: For professional, readable terminal output.
Why Read It?
If you’ve ever spent hours copy-pasting answers from old spreadsheets into new RFPs, this is for you. As per my experience, automating this routing logic is the biggest hurdle. Once you solve "where do I look?", the "what is the answer?" part becomes trivial for modern LLMs.
Let’s Design
I started by mapping out the flow. I didn’t want a monolithic RAG system where all documents are dumped into one vector store. That leads to confusion. Instead, I designed a "Router" architecture.
The sequence is straightforward:
- Question enters the system.
- Router analyzes intent.
- Designated Agent takes over to retrieve and answer.
Let’s Get Cooking
I structured the code to be modular. The heart of the system is the routing logic.
1. The Semantic Router
I needed a way to classify questions fast. In a real production system, I’d use embeddings here, but for this concept, I built a simulation that mimics keyword and intent mapping.
class SemanticRouter:
"""
Simulates a semantic router that classifies RFP questions into domains
based on keywords and intent.
"""
def __init__(self):
console.log("[bold blue]Initializing Semantic Router...[/bold blue]")
time.sleep(1.2)
# Keywords map for simulation
self.routes = {
Domain.SECURITY: ["encryption", "sso", "soc2", "penetration", "access control", "firewall"],
Domain.PRODUCT: ["api", "integration", "workflow", "dashboard", "analytics", "users"],
Domain.COMPLIANCE: ["gdpr", "ccpa", "iso", "data retention", "contract", "liability"]
}
def route(self, query: str) -> Domain:
"""Determines the domain of the query."""
query_lower = query.lower()
# Simulate neural processing time
time.sleep(0.5)
for domain, keywords in self.routes.items():
if any(k in query_lower for k in keywords):
return domain
return Domain.UNCERTAIN
2. The Specialist Node (RAG)
Once routed, the question lands on a RAGNode. This class simulates the retrieval of context from a specific document set (e.g., only searching the Security Policy, not the API docs).
class RAGNode:
"""
Simulates a specialized RAG node for a specific domain.
"""
def __init__(self, domain: Domain, knowledge_base: List[str]):
self.domain = domain
self.knowledge_base = knowledge_base
console.log(f"[green]Loaded RAG Node: {domain.value}[/green]")
time.sleep(0.3)
def retrieve(self, query: str) -> str:
"""Simulates retrieving relevant context."""
time.sleep(0.8) # Simulate vector search
return f"Context retrieved from {self.domain.value} DB for: '{query}'"
3. The Orchestrator
Finally, the RFPResponseEngine class ties it all together, dispatching queries and printing the beautiful output.
class RFPResponseEngine:
def __init__(self):
self.router = SemanticRouter()
self.nodes = {
Domain.SECURITY: RAGNode(Domain.SECURITY, ["Security Policy v4", "SOC2 Report"]),
Domain.PRODUCT: RAGNode(Domain.PRODUCT, ["API Docs", "User Guide"]),
Domain.COMPLIANCE: RAGNode(Domain.COMPLIANCE, ["DPA", "Privacy Policy"])
}
def process_question(self, question: str):
console.print(f"\n[bold white]Processing Question:[/bold white] '{question}'")
# Step 1: Route
domain = self.router.route(question)
console.print(f" [yellow]→ Routed to:[/yellow] [bold cyan]{domain.value}[/bold cyan]")
# ... logic to route to node ...
Let’s Setup
If you want to run this experiment yourself, here is the setup I used.
Clone the repo:
git clone https://github.com/aniket-work/autonomous-rfp-response-engine.git
Install dependencies:
pip install rich
Run the engine:
python main.py
Let’s Run
When I ran the script, I was really pleased with how distinct the routing was. Watching it classify "Do you have SOC2?" to Security and "How does the API rate limit?" to Product Features felt like magic.
You can see the engine acting in real-time here:
It processed the batch of 4 questions in under 10 seconds, which in a manual workflow would have taken me at least 20 minutes of Slack DMing and document searching.
Closing Thoughts
Building this "Autonomous RFP Response Engine" showed me that the key to effective enterprise logic isn’t just a bigger model—it’s better architecture. By splitting the problem into Routing and Specialized Retrieval, we get higher accuracy and easier debugging.
In my opinion, agents that "know what they don’t know" (and where to find it) are the future of business automation.
GitHub Repository: https://github.com/aniket-work/autonomous-rfp-response-engine
Disclaimer
The views and opinions expressed here are solely my own and do not represent the views, positions, or opinions of my employer or any organization I am affiliated with. The content is based on my personal experience and experimentation and may be incomplete or incorrect. Any errors or misinterpretations are unintentional, and I apologize in advance if any statements are misunderstood or misrepresented.