Skip to content

Feature/rag router agent#458

Open
Subhajitdas99 wants to merge 9 commits intoGetBindu:mainfrom
Subhajitdas99:feature/rag-router-agent
Open

Feature/rag router agent#458
Subhajitdas99 wants to merge 9 commits intoGetBindu:mainfrom
Subhajitdas99:feature/rag-router-agent

Conversation

@Subhajitdas99
Copy link
Copy Markdown
Contributor

@Subhajitdas99 Subhajitdas99 commented Apr 18, 2026

Summary

  • Problem: No example demonstrating how to build a RAG-based agent with intelligent routing across multiple knowledge sources in Bindu.
  • Why it matters: Developers need practical examples to understand how agents can reason, route, and act within Bindu’s ecosystem.
  • What changed: Added a new example agent (rag_router_agent) implementing intent classification, database routing, and context-aware response generation using LLM.
  • What did NOT change (scope boundary): No modifications to Bindu core logic, APIs, storage, scheduler, or existing features.

Change Type (select all that apply)

  • Feature
  • Documentation

Scope (select all touched areas)

  • Documentation

Linked Issue/PR

  • Closes # (N/A)
  • Related # (N/A)

User-Visible / Behavior Changes

  • Added a new example agent under examples/rag_router_agent/

  • Demonstrates:

    • Intent-based routing (finance, legal, tech)
    • Retrieval-Augmented Generation (RAG)
    • Structured response output

Security Impact (required)

  • New permissions/capabilities? → No
  • Secrets/credentials handling changed? → No
  • New/changed network calls? → No
  • Database schema/migration changes? → No
  • Authentication/authorization changes? → No

Verification

Environment

  • OS: Windows 11
  • Python version: 3.12
  • Storage backend: InMemoryStorage
  • Scheduler backend: InMemoryScheduler

Steps to Test

  1. Navigate to examples/rag_router_agent/

  2. Set OPENROUTER_API_KEY

  3. Run:

    python test_local.py
    
  4. Optionally run:

    python agent.py
    

Expected Behavior

  • Query is classified into intent (e.g., finance)
  • Correct database is selected
  • Relevant documents are retrieved
  • LLM generates context-aware answer

Actual Behavior

  • Verified correct routing and response generation

  • Output includes:

    • answer
    • intent
    • db_used

Evidence (attach at least one)

  • Test output / logs

Example output:

{
  "answer": "GST is a tax applied on goods and services...",
  "intent": "finance",
  "db_used": "db/finance.txt"
}

Human Verification (required)

  • Verified scenarios:

    • Finance query routing
    • Correct document retrieval
    • LLM response generation
  • Edge cases checked:

    • No matching documents
    • Invalid input handling
  • What you did NOT verify:

    • Multi-agent (A2A) communication
    • Production deployment scenarios

Compatibility / Migration

  • Backward compatible? → Yes
  • Config/env changes? → No
  • Database migration needed? → No

Failure Recovery (if this breaks)

  • How to disable/revert:

    • Remove examples/rag_router_agent/ directory
  • Files/config to restore:

    • None (isolated example)
  • Known bad symptoms:

    • None expected (non-intrusive addition)

Risks and Mitigations

  • Risk: Example may not cover all real-world edge cases

    • Mitigation: Clearly documented as a basic reference implementation

Checklist

  • Tests pass (local validation)
  • Pre-commit hooks assessed (commit bypassed due to unrelated repo test issue)
  • Documentation updated
  • Security impact assessed
  • Human verification completed
  • Backward compatibility considered

Summary by CodeRabbit

  • New Features

    • Added a RAG Router Agent example: intent-based routing (finance, legal, tech), simple retriever, domain agents, structured JSON responses (answer, intent, agent_used, db_used, docs_used), and a runnable local demo (requires an API key).
  • Documentation

    • Added SKALE integration notes: supported networks, upstream requirements, and a step‑by‑step safe integration path.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds SKALE integration notes to payment docs and introduces a new RAG Router Agent example that implements intent classification, DB routing, keyword-based retrieval, domain-agent delegation, and LLM-driven answer generation returning structured JSON.

Changes

Cohort / File(s) Summary
Documentation
docs/PAYMENT.md
Added "SKALE Integration Notes" describing current upstream x402 network validation/token-chain mappings (lists supported networks), clarifies upstream vs. Bindu RPC responsibilities, enumerates upstream additions required for SKALE, and provides a safe integration path.
RAG Router Agent — Core
examples/rag_router_agent/agent.py, examples/rag_router_agent/README.md, examples/rag_router_agent/test_local.py
New example entrypoint and README: agent.py exposes handler(messages: list[dict]) and Bindu config, validates input, classifies intent, routes DB/agent, retrieves context, delegates to domain agent, calls LLM, and returns structured JSON (answer, intent, agent_used, db_used, docs_used). test_local.py demonstrates local run.
RAG Router Agent — Routing & Retrieval
examples/rag_router_agent/router.py, examples/rag_router_agent/retriever.py
Added classify_intent, route_db, route_agent (maps to domain agents), and retrieve_docs(db_path, query, k=2) — a simple keyword-based scorer that returns top-k matching lines.
RAG Router Agent — Domain Agents & Data
examples/rag_router_agent/agents/finance_agent.py, examples/rag_router_agent/agents/legal_agent.py, examples/rag_router_agent/agents/tech_agent.py, examples/rag_router_agent/db/*.txt
Added simple domain agent functions that format a domain-specific response and three small text files (finance.txt, legal.txt, tech.txt) used as example knowledge sources.

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Agent as RAG Agent\n(agent.py)
    participant Router as Intent Router\n(router.py)
    participant Retriever as Document Retriever\n(retriever.py)
    participant Domain as Domain Agent\n(agents/*)
    participant LLM as OpenRouter LLM
    participant DB as Knowledge DB\n(db/*.txt)

    User->>Agent: Send messages (last contains query)
    activate Agent
    Agent->>Router: classify_intent(query)
    Router-->>Agent: intent
    Agent->>Router: route_db(intent)
    Router-->>Agent: db_path
    Agent->>Retriever: retrieve_docs(db_path, query, k=2)
    Retriever->>DB: Read and score lines
    Retriever-->>Agent: top-k docs
    Agent->>Domain: route_agent(intent) -> domain agent(context, query)
    Domain-->>Agent: agent_response
    Agent->>LLM: compose final prompt (query + agent_response + context)
    LLM-->>Agent: generated result
    Agent-->>User: {answer, intent, agent_used, db_used, docs_used}
    deactivate Agent
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • Paraschamoli

Poem

🐰 I hopped through docs and routes with cheer,

I fetched the lines that users hold dear.
I nudged the router, nudged the LLM too,
A tidy answer hopped out just for you. 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Title is vague and generic, using only a feature branch naming pattern ('Feature/rag router agent') without clearly summarizing the main change or specific functionality being added. Revise title to be more descriptive and specific, e.g., 'Add RAG router agent example with intent-based routing' or 'Add intent-based RAG agent example to examples/'
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed Description is comprehensive and follows the template structure, covering summary, change type, scope, security impact, verification steps, and evidence with example output.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/PAYMENT.md`:
- Around line 273-280: Add a single explicit sentence to the paragraph
clarifying Bindu’s current default RPC mapping: state that the configuration key
rpc_urls_by_network in Bindu defaults to include base-sepolia, base, and
ethereum (and does not include Avalanche by default), so readers won’t confuse
upstream x402 entries with Bindu’s own defaults; update the docs near the
discussion of skale and x402 to mention rpc_urls_by_network and these three
networks by name.

In `@examples/rag_router_agent/agent.py`:
- Around line 64-73: The current try/except around agent.run(result) returns the
raw exception string (variable e) to callers, which may leak provider/config
details; instead, catch exceptions from agent.run, log the full exception
internally using your logger (e.g., logger.exception or similar) and return a
generic error message in the "answer" field (e.g., "An error occurred while
generating the response") while still returning intent, db_path and docs; if
this catch is intentional at the handler boundary, add an explicit lint
rationale comment above the except to justify the broad catch and masking
behavior.
- Around line 84-93: The config dict currently contains a personal email in the
"author" field; replace the hardcoded address in the config (variable name
config, key "author") with a non-sensitive placeholder or read from an
environment variable (e.g., os.getenv("EXAMPLE_AUTHOR", "example@example.com"))
so no personal identifiers are committed; update any README or comments to
indicate contributors should set EXAMPLE_AUTHOR in their environment if needed.
- Around line 21-25: The handler currently only catches KeyError/IndexError
while extracting query from messages[-1]["content"]; update handler to first
validate the message shape: ensure messages is a list and not None, that it has
at least one item, that last_item := messages[-1] is a dict, that "content" in
last_item and isinstance(last_item["content"], str), then assign query =
last_item["content"] or otherwise handle invalid input (raise a descriptive
error or return a safe default); reference the handler function and the query
extraction so you add these checks before the current try/except block.

In `@examples/rag_router_agent/README.md`:
- Around line 15-27: Add a quickstart section to the README that documents the
required local setup: show how to set the OPENROUTER_API_KEY environment
variable on Windows (powershell) and macOS/Linux (bash) and the exact command to
run the example script (python test_local.py). Update README.md near the example
flow (the section containing "User Query → Intent Detection → DB Routing →
Retrieval → LLM Response" and the "🔍 Example") to include these two environment
variable examples and the command to run test_local.py so users can reproduce
the sample locally.

In `@examples/rag_router_agent/retriever.py`:
- Around line 1-15: The retrieve_docs function currently lowercases docs but not
the query and returns top-k even when scores are zero; update retrieve_docs to
normalize the query (e.g., lower().split() or simple tokenization) and compare
against lowercased doc text, compute scores as you already do, then filter out
any (score, doc) pairs with score == 0 before sorting and slicing so only
positively-scored docs (up to k) are returned; adjust use of the scored list and
return expression accordingly to reference retrieve_docs, docs and scored.

In `@examples/rag_router_agent/router.py`:
- Around line 13-14: The route_db function returns a relative path that only
works when the process cwd is the example folder; update route_db to build the
path relative to this module's location (use __file__ /
pathlib.Path(__file__).parent) and join "db" and f"{intent}.txt" so lookups
succeed regardless of process cwd; modify the route_db implementation to compute
the absolute/relative-to-module path using Path(__file__).parent.joinpath("db",
f"{intent}.txt") (or equivalent) to locate files reliably.
- Around line 3-10: The current intent routing lowercases the raw query and uses
substring checks (e.g., checking "act") which misroutes words like "React";
update the classifier to tokenize the query into whole-word tokens (split on
whitespace and strip punctuation or use a word-boundary regex) and then perform
exact-term membership checks against the intent keyword lists (the same lists
currently used in the any(...) checks) so only whole-word matches (e.g., "act"
as a standalone token) map to "legal" while "react" remains "tech"; apply this
change where the query variable is lowercased and the intent branches are
checked.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ff822938-f1df-4c79-b7c5-251df913cae4

📥 Commits

Reviewing files that changed from the base of the PR and between 5cf0a20 and 8fa31a9.

📒 Files selected for processing (9)
  • docs/PAYMENT.md
  • examples/rag_router_agent/README.md
  • examples/rag_router_agent/agent.py
  • examples/rag_router_agent/db/finance.txt
  • examples/rag_router_agent/db/legal.txt
  • examples/rag_router_agent/db/tech.txt
  • examples/rag_router_agent/retriever.py
  • examples/rag_router_agent/router.py
  • examples/rag_router_agent/test_local.py

Comment thread docs/PAYMENT.md
Comment on lines +273 to +280
These upstream `x402` constraints are separate from Bindu's own runtime
configuration, where RPC endpoint configuration can be defined independently.

### What this means

On the Bindu side, the payment middleware and RPC configuration model are
already flexible enough for future network expansion. However, adding `skale`
only in Bindu configuration is not sufficient yet, because the upstream `x402`
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify the currently configured Bindu defaults to avoid network support ambiguity.

Please add one explicit line here that Bindu’s default rpc_urls_by_network currently includes base-sepolia, base, and ethereum (not Avalanche by default). Right now, readers may infer Avalanche is preconfigured because it appears in the upstream list.

Suggested doc patch
 These upstream `x402` constraints are separate from Bindu's own runtime
 configuration, where RPC endpoint configuration can be defined independently.
+As of now, Bindu's default RPC configuration includes `base-sepolia`, `base`,
+and `ethereum`; Avalanche/SKALE require explicit configuration (and SKALE also
+requires upstream `x402` support work).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
These upstream `x402` constraints are separate from Bindu's own runtime
configuration, where RPC endpoint configuration can be defined independently.
### What this means
On the Bindu side, the payment middleware and RPC configuration model are
already flexible enough for future network expansion. However, adding `skale`
only in Bindu configuration is not sufficient yet, because the upstream `x402`
These upstream `x402` constraints are separate from Bindu's own runtime
configuration, where RPC endpoint configuration can be defined independently.
As of now, Bindu's default RPC configuration includes `base-sepolia`, `base`,
and `ethereum`; Avalanche/SKALE require explicit configuration (and SKALE also
requires upstream `x402` support work).
### What this means
On the Bindu side, the payment middleware and RPC configuration model are
already flexible enough for future network expansion. However, adding `skale`
only in Bindu configuration is not sufficient yet, because the upstream `x402`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/PAYMENT.md` around lines 273 - 280, Add a single explicit sentence to
the paragraph clarifying Bindu’s current default RPC mapping: state that the
configuration key rpc_urls_by_network in Bindu defaults to include base-sepolia,
base, and ethereum (and does not include Avalanche by default), so readers won’t
confuse upstream x402 entries with Bindu’s own defaults; update the docs near
the discussion of skale and x402 to mention rpc_urls_by_network and these three
networks by name.

Comment thread examples/rag_router_agent/agent.py Outdated
Comment thread examples/rag_router_agent/agent.py
Comment thread examples/rag_router_agent/README.md Outdated
Comment thread examples/rag_router_agent/retriever.py Outdated
Comment thread examples/rag_router_agent/router.py Outdated
Comment thread examples/rag_router_agent/router.py Outdated
@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Added a small README improvement with example output + run instructions to make it easier to try locally.

Happy to extend this into:

  • multi-agent routing (router → domain agents via A2A)
  • vector DB (FAISS/Chroma)
  • confidence-based routing

Would love feedback on where this fits best.

@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Noticed CI unit tests are failing, but this seems unrelated to my changes.

This PR only adds an example under examples/ and does not modify core modules.

Locally verified:

  • Intent routing works
  • Retrieval pipeline works
  • LLM responses generated correctly

Happy to adjust if needed.

@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Thanks for the detailed feedback—this is really helpful!

I’ll address the suggestions around:

  • input validation
  • safer error handling
  • path resolution
  • retrieval improvements

Will push updates shortly.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
examples/rag_router_agent/retriever.py (1)

11-24: ⚠️ Potential issue | 🟠 Major

Use document tokens for scoring instead of substring checks.

Line 20 still treats any query token found inside a larger word as a match, so short terms can return irrelevant context and bypass the “no relevant information” path.

Proposed fix
     # 🔤 Normalize query (fix punctuation + case issues)
-    query_words = re.findall(r"\w+", query.lower())
+    query_words = set(re.findall(r"\w+", query.lower()))
 
     scored = []
 
     for doc in docs:
-        doc_lower = doc.lower()
+        doc_words = set(re.findall(r"\w+", doc.lower()))
 
         # 📊 Compute score (token-based match)
-        score = sum(1 for word in query_words if word in doc_lower)
+        score = len(query_words & doc_words)
 
         # ❗ Filter irrelevant docs (IMPORTANT FIX)
         if score > 0:
-            scored.append((score, doc))
+            scored.append((score, doc.strip()))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/retriever.py` around lines 11 - 24, The current
scoring uses substring checks (word in doc_lower) which matches tokens inside
larger words; instead, tokenize each document into normalized tokens and do
exact token membership checks: create doc_words (e.g., using re.findall(r"\w+",
doc.lower())) and a set_doc_words for fast lookup, then compute score as sum(1
for word in query_words if word in set_doc_words) before appending to scored;
update references to doc_lower and score logic accordingly to ensure only
whole-token matches count.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@examples/rag_router_agent/retriever.py`:
- Around line 11-24: The current scoring uses substring checks (word in
doc_lower) which matches tokens inside larger words; instead, tokenize each
document into normalized tokens and do exact token membership checks: create
doc_words (e.g., using re.findall(r"\w+", doc.lower())) and a set_doc_words for
fast lookup, then compute score as sum(1 for word in query_words if word in
set_doc_words) before appending to scored; update references to doc_lower and
score logic accordingly to ensure only whole-token matches count.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 216dca32-4ef8-4df9-967e-5b778487b5d0

📥 Commits

Reviewing files that changed from the base of the PR and between 2f598a1 and e851d2e.

📒 Files selected for processing (1)
  • examples/rag_router_agent/retriever.py

@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Addressed all review feedback:

  • added robust input validation in handler
  • improved intent classification using token-based matching (avoids substring issues)
  • resolved DB path handling using absolute paths
  • improved retrieval with normalization and zero-score filtering
  • updated error handling to avoid exposing internal details
  • removed personal email from config (now env-based)

Would love any further feedback!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
examples/rag_router_agent/agent.py (1)

6-7: Sibling imports may break when module is imported from another cwd.

from router import ... / from retriever import ... resolve only when examples/rag_router_agent/ is on sys.path (e.g., running python agent.py from that dir, or test_local.py located alongside). Importing agent from a parent directory or as part of a larger harness will raise ModuleNotFoundError. Since this file is used as an example and its companion test_local.py imports handler from here, consider making the module location self-resolving.

♻️ Proposed fix
 import os
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent))
+
 from bindu.penguin.bindufy import bindufy
 from agno.agent import Agent
 from agno.models.openai import OpenAIChat

 from router import classify_intent, route_db
 from retriever import retrieve_docs
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/agent.py` around lines 6 - 7, The sibling imports
in agent.py (from router import classify_intent, route_db and from retriever
import retrieve_docs) can break when agent is imported from a different CWD;
update agent.py to resolve its companion modules reliably by either converting
to package-relative imports (e.g., from .router import classify_intent, route_db
and from .retriever import retrieve_docs) if you make examples a package, or add
a short robust sys.path bootstrap at the top that computes the
examples/rag_router_agent directory from __file__ and inserts it into sys.path
before importing router/retriever so classify_intent, route_db and retrieve_docs
always resolve for imports like test_local.py importing handler.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/rag_router_agent/agent.py`:
- Line 112: The file is missing a trailing newline causing the pre-commit hook
to fail; add a single newline at EOF immediately after the final call
bindufy(config, handler) so the file ends with a newline, then run pre-commit
locally to verify the end-of-file-fixer passes before pushing.
- Around line 78-87: The except block around agent.run(prompt) is swallowing all
exceptions; change it to capture the exception (e.g., except Exception as e) and
log the full error/stack trace (using logging.exception or a module-level
logger) before returning the generic error response so failures (bad
OPENROUTER_API_KEY, network, rate limits) are debuggable; update references in
the block that return {"answer": ..., "intent": intent, "db_used": db_path,
"docs_used": docs} to keep behavior identical while ensuring the exception is
recorded (reference: agent.run, result, prompt, intent, db_path, docs).

---

Nitpick comments:
In `@examples/rag_router_agent/agent.py`:
- Around line 6-7: The sibling imports in agent.py (from router import
classify_intent, route_db and from retriever import retrieve_docs) can break
when agent is imported from a different CWD; update agent.py to resolve its
companion modules reliably by either converting to package-relative imports
(e.g., from .router import classify_intent, route_db and from .retriever import
retrieve_docs) if you make examples a package, or add a short robust sys.path
bootstrap at the top that computes the examples/rag_router_agent directory from
__file__ and inserts it into sys.path before importing router/retriever so
classify_intent, route_db and retrieve_docs always resolve for imports like
test_local.py importing handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4f1bf22-e051-457f-8921-5191dc44bb7f

📥 Commits

Reviewing files that changed from the base of the PR and between e851d2e and 535fdcf.

📒 Files selected for processing (6)
  • examples/rag_router_agent/agent.py
  • examples/rag_router_agent/db/finance.txt
  • examples/rag_router_agent/db/legal.txt
  • examples/rag_router_agent/db/tech.txt
  • examples/rag_router_agent/router.py
  • examples/rag_router_agent/test_local.py
✅ Files skipped from review due to trivial changes (4)
  • examples/rag_router_agent/db/tech.txt
  • examples/rag_router_agent/db/finance.txt
  • examples/rag_router_agent/db/legal.txt
  • examples/rag_router_agent/test_local.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • examples/rag_router_agent/router.py

Comment thread examples/rag_router_agent/agent.py Outdated
Comment on lines +78 to +87
try:
result = agent.run(prompt)
answer = result.content if hasattr(result, "content") else str(result)
except Exception:
return {
"answer": "Error generating response. Please try again.",
"intent": intent,
"db_used": db_path,
"docs_used": docs,
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Log the swallowed exception so failures are debuggable.

Returning a generic "Error generating response." is correct for the caller (addresses the earlier leakage concern), but currently the underlying error (bad OPENROUTER_API_KEY, network failure, provider rate limit, etc.) is silently dropped — making the example very hard to troubleshoot. At minimum, log the exception internally. This also lets you silence Ruff BLE001 with an explicit rationale.

🛠️ Proposed fix
+import logging
 import os
 from bindu.penguin.bindufy import bindufy
 from agno.agent import Agent
 from agno.models.openai import OpenAIChat

 from router import classify_intent, route_db
 from retriever import retrieve_docs
+
+logger = logging.getLogger(__name__)
     try:
         result = agent.run(prompt)
         answer = result.content if hasattr(result, "content") else str(result)
-    except Exception:
+    except Exception:  # noqa: BLE001 - keep handler response structured at the service boundary
+        logger.exception("agent.run failed for intent=%s db=%s", intent, db_path)
         return {
             "answer": "Error generating response. Please try again.",
             "intent": intent,
             "db_used": db_path,
             "docs_used": docs,
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try:
result = agent.run(prompt)
answer = result.content if hasattr(result, "content") else str(result)
except Exception:
return {
"answer": "Error generating response. Please try again.",
"intent": intent,
"db_used": db_path,
"docs_used": docs,
}
try:
result = agent.run(prompt)
answer = result.content if hasattr(result, "content") else str(result)
except Exception: # noqa: BLE001 - keep handler response structured at the service boundary
logger.exception("agent.run failed for intent=%s db=%s", intent, db_path)
return {
"answer": "Error generating response. Please try again.",
"intent": intent,
"db_used": db_path,
"docs_used": docs,
}
🧰 Tools
🪛 Ruff (0.15.10)

[warning] 81-81: Do not catch blind exception: Exception

(BLE001)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/agent.py` around lines 78 - 87, The except block
around agent.run(prompt) is swallowing all exceptions; change it to capture the
exception (e.g., except Exception as e) and log the full error/stack trace
(using logging.exception or a module-level logger) before returning the generic
error response so failures (bad OPENROUTER_API_KEY, network, rate limits) are
debuggable; update references in the block that return {"answer": ..., "intent":
intent, "db_used": db_path, "docs_used": docs} to keep behavior identical while
ensuring the exception is recorded (reference: agent.run, result, prompt,
intent, db_path, docs).


# 🚀 Start agent only when run directly
if __name__ == "__main__":
bindufy(config, handler) No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

CI failing: add trailing newline at end of file.

The end-of-file-fixer pre-commit hook rewrote this file in CI and failed the job. Append a newline after line 112 and re-run pre-commit locally (pre-commit run --files examples/rag_router_agent/agent.py) before pushing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/agent.py` at line 112, The file is missing a
trailing newline causing the pre-commit hook to fail; add a single newline at
EOF immediately after the final call bindufy(config, handler) so the file ends
with a newline, then run pre-commit locally to verify the end-of-file-fixer
passes before pushing.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (5)
examples/rag_router_agent/agents/tech_agent.py (1)

1-2: Unused query parameter.

query is accepted but never used in the response. If the signature is intentional for uniform dispatch from route_agent, consider prefixing it with _ or adding a brief comment to document the convention; otherwise the domain agent can't meaningfully differentiate its behavior based on the user's query.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/agents/tech_agent.py` around lines 1 - 2, The
tech_agent function currently accepts a query parameter but never uses it;
either make the parameter explicitly unused by renaming it to _query (or add a
comment like "# query kept for uniform dispatch") to document the convention, or
update tech_agent to incorporate the query into its output (e.g., include the
query in the returned string) so the agent can differentiate responses; locate
the function named tech_agent and apply one of these fixes to resolve the unused
parameter warning.
examples/rag_router_agent/router.py (2)

5-13: Intent classifier has no tech keywords and falls through for unrelated queries.

Any query without finance/legal tokens silently maps to "tech", so "What's the weather today?" will be classified as tech and route to db/tech.txt. That's acceptable for an example, but consider either (a) adding explicit tech keywords and returning an "unknown"/None intent for no-match (letting handler short-circuit with a "no relevant domain" message), or (b) documenting the default-to-tech behavior in the README so users aren't surprised.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/router.py` around lines 5 - 13, The classify_intent
function currently defaults every non-finance/legal query to "tech", which
misroutes unrelated queries; update classify_intent to either include explicit
tech keywords (e.g., "computer", "program", "api", "server", "network") so tech
is matched intentionally, or change it to return a sentinel like None/"unknown"
on no match and update the caller/handler to short-circuit and respond with a
"no relevant domain" message; reference the classify_intent function in your
changes and ensure any dependent routing logic checks for the new None/"unknown"
value before selecting db/tech.txt.

25-28: Top-level imports placed mid-file and relying on sys.path containing the example dir.

Two concerns:

  1. Imports are below code rather than at the top of the module — Ruff/isort/PEP 8 would flag this (E402).
  2. from agents.finance_agent import finance_agent only resolves when examples/rag_router_agent is on sys.path (i.e., running python agent.py from that directory). Running from the repo root or via a different launcher will ImportError. Since route_db was fixed to be cwd-independent via __file__, it's inconsistent to leave the agent imports cwd-dependent.
Suggested fix

Move imports to the top and make them robust to cwd. One option using an __init__.py in agents/ and a path shim:

 import os
 import re
+import sys
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+if BASE_DIR not in sys.path:
+    sys.path.insert(0, BASE_DIR)
+
+from agents.finance_agent import finance_agent
+from agents.legal_agent import legal_agent
+from agents.tech_agent import tech_agent
@@
-# 📁 Resolve base directory safely
-BASE_DIR = os.path.dirname(os.path.abspath(__file__))
@@
-# 🤖 Import domain agents (A2A delegation)
-from agents.finance_agent import finance_agent
-from agents.legal_agent import legal_agent
-from agents.tech_agent import tech_agent
-
-
 # 🔀 Route to correct agent
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/router.py` around lines 25 - 28, Move the three
domain-agent imports (finance_agent, legal_agent, tech_agent) to the top of the
module and stop relying on the current working directory being on sys.path;
either make the agents directory a proper package (add an __init__.py) so you
can use stable absolute imports like from agents.finance_agent import
finance_agent, or add a small deterministic path shim right before the imports
that appends the project root (computed from
Path(__file__).resolve().parents[...] ) to sys.path so the imports always
resolve regardless of CWD, keeping this behavior consistent with the route_db
__file__-based fix.
examples/rag_router_agent/agents/legal_agent.py (1)

1-2: Same unused query as the other domain agents.

All three domain agents (finance_agent, legal_agent, tech_agent) are near-identical stubs that only echo context with a different prefix. For an example demonstrating A2A delegation, consider collapsing them into a single parameterized helper (e.g., make_domain_agent(name)) or having each actually use query to shape its response — otherwise the "multi-agent routing" aspect is cosmetic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/agents/legal_agent.py` around lines 1 - 2, The
three near-identical stubs finance_agent, legal_agent, and tech_agent ignore the
query parameter; replace them with a single parameterized factory (e.g.,
make_domain_agent(name)) that returns an agent function which uses both query
and context to produce a name-prefixed response, or alternatively update each
existing function (finance_agent, legal_agent, tech_agent) to incorporate the
query into the returned string so routing is meaningful; locate the functions by
name in the diff and either implement make_domain_agent(name) to generate the
agent closures or modify each agent to reference the query when building its
response.
examples/rag_router_agent/agent.py (1)

6-7: Module imports assume cwd is examples/rag_router_agent/.

from router import ... and from retriever import ... only resolve when the example directory is on sys.path. If bindufy or a future launcher imports this file from elsewhere, both imports fail. For an example this is acceptable, but documenting it in the README ("run from examples/rag_router_agent/") or adding a sys.path shim (as suggested for router.py) would prevent confused users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/rag_router_agent/agent.py` around lines 6 - 7, The imports in
agent.py (classify_intent, route_db, route_agent, retrieve_docs) assume the
example directory is on sys.path; add the same sys.path shim used in router.py
at the top of agent.py so these relative module imports work when the file is
executed or imported from elsewhere (or alternatively add a one-line README note
instructing users to run from examples/rag_router_agent/). Specifically, add the
sys.path insertion that prepends the example directory to sys.path before the
from router import ... and from retriever import ... lines so classify_intent,
route_db, route_agent and retrieve_docs resolve reliably.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/rag_router_agent/agent.py`:
- Around line 11-18: The Agent is being constructed at import time using
OpenAIChat(api_key=os.getenv("OPENROUTER_API_KEY")) which can be None when the
env var is unset; add an explicit startup check that reads
os.getenv("OPENROUTER_API_KEY") into a variable, validate it's non-empty, and
raise or log a clear error (or exit) before constructing OpenAIChat/Agent; also
ensure the response-generation path does not swallow the underlying exception so
the missing API key is visible to users (adjust the error handling where
responses are generated to re-raise or include the underlying error).

---

Nitpick comments:
In `@examples/rag_router_agent/agent.py`:
- Around line 6-7: The imports in agent.py (classify_intent, route_db,
route_agent, retrieve_docs) assume the example directory is on sys.path; add the
same sys.path shim used in router.py at the top of agent.py so these relative
module imports work when the file is executed or imported from elsewhere (or
alternatively add a one-line README note instructing users to run from
examples/rag_router_agent/). Specifically, add the sys.path insertion that
prepends the example directory to sys.path before the from router import ... and
from retriever import ... lines so classify_intent, route_db, route_agent and
retrieve_docs resolve reliably.

In `@examples/rag_router_agent/agents/legal_agent.py`:
- Around line 1-2: The three near-identical stubs finance_agent, legal_agent,
and tech_agent ignore the query parameter; replace them with a single
parameterized factory (e.g., make_domain_agent(name)) that returns an agent
function which uses both query and context to produce a name-prefixed response,
or alternatively update each existing function (finance_agent, legal_agent,
tech_agent) to incorporate the query into the returned string so routing is
meaningful; locate the functions by name in the diff and either implement
make_domain_agent(name) to generate the agent closures or modify each agent to
reference the query when building its response.

In `@examples/rag_router_agent/agents/tech_agent.py`:
- Around line 1-2: The tech_agent function currently accepts a query parameter
but never uses it; either make the parameter explicitly unused by renaming it to
_query (or add a comment like "# query kept for uniform dispatch") to document
the convention, or update tech_agent to incorporate the query into its output
(e.g., include the query in the returned string) so the agent can differentiate
responses; locate the function named tech_agent and apply one of these fixes to
resolve the unused parameter warning.

In `@examples/rag_router_agent/router.py`:
- Around line 5-13: The classify_intent function currently defaults every
non-finance/legal query to "tech", which misroutes unrelated queries; update
classify_intent to either include explicit tech keywords (e.g., "computer",
"program", "api", "server", "network") so tech is matched intentionally, or
change it to return a sentinel like None/"unknown" on no match and update the
caller/handler to short-circuit and respond with a "no relevant domain" message;
reference the classify_intent function in your changes and ensure any dependent
routing logic checks for the new None/"unknown" value before selecting
db/tech.txt.
- Around line 25-28: Move the three domain-agent imports (finance_agent,
legal_agent, tech_agent) to the top of the module and stop relying on the
current working directory being on sys.path; either make the agents directory a
proper package (add an __init__.py) so you can use stable absolute imports like
from agents.finance_agent import finance_agent, or add a small deterministic
path shim right before the imports that appends the project root (computed from
Path(__file__).resolve().parents[...] ) to sys.path so the imports always
resolve regardless of CWD, keeping this behavior consistent with the route_db
__file__-based fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7749f739-8948-4dad-87df-dac8df40563e

📥 Commits

Reviewing files that changed from the base of the PR and between 535fdcf and 80231fc.

📒 Files selected for processing (6)
  • examples/rag_router_agent/README.md
  • examples/rag_router_agent/agent.py
  • examples/rag_router_agent/agents/finance_agent.py
  • examples/rag_router_agent/agents/legal_agent.py
  • examples/rag_router_agent/agents/tech_agent.py
  • examples/rag_router_agent/router.py
✅ Files skipped from review due to trivial changes (1)
  • examples/rag_router_agent/README.md

Comment thread examples/rag_router_agent/agent.py
@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Extended this agent from a single RAG pipeline into a multi-agent system.

Key upgrade:

  • Router now delegates queries to domain-specific agents (finance, legal, tech)
  • Each agent processes context independently
  • Final response is synthesized using LLM

This introduces a simple A2A-style coordination pattern, where agents act as modular components rather than a single monolithic responder.

Happy to extend this further into full agent-to-agent communication using Bindu protocol if aligned.

@Subhajitdas99
Copy link
Copy Markdown
Contributor Author

Addressed final review comments:

  • improved intent classification (explicit tech keywords + unknown intent handling)
  • updated domain agents to use query for meaningful responses
  • added safe handling for unknown intents and agent routing
  • ensured routing and retrieval logic is consistent and robust

Happy to iterate further if needed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant