Add multilingual collab agent example - #429
Conversation
Identity-aware agent with automatic language detection for English, Hindi and Bengali. Uses Bindu DID identity, Mem0 persistent memory, DuckDuckGo web search, and 3 structured skills (research, translate, collaborate). Verified working end-to-end: Hindi query receives Hindi response.
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughA new example application is added demonstrating a multilingual collaborative agent built on the Bindu framework. The example includes environment configuration, a Python server implementation, comprehensive documentation, and three skill definitions for research, translation, and collaborative writing tasks supporting English, Hindi, and Bengali. Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant Handler as Request Handler
participant Agent as Agent (Lazy Init)
participant DuckDuckGo as DuckDuckGo Tool
participant Mem0 as Mem0 Tool
participant OpenRouter as OpenRouter Model
Client->>Handler: POST messages (detect language)
Note over Handler: First request:<br/>build_agent() once<br/>asyncio.Lock guard
Handler->>Agent: Load env vars, create Agent<br/>Add DuckDuckGo & Mem0 tools
Agent->>Handler: Agent instance ready
Handler->>Agent: arun(messages)
Agent->>OpenRouter: Query with instructions<br/>(multilingual rules + context)
alt Research Needed
OpenRouter->>Agent: Request research
Agent->>DuckDuckGo: Web search query
DuckDuckGo->>Agent: Search results
end
alt Memory Needed
OpenRouter->>Agent: Access/store memory
Agent->>Mem0: Persist context
Mem0->>Agent: Memory operations
end
OpenRouter->>Agent: Response (match input language)
Agent->>Handler: Response object
Handler->>Client: JSON-RPC response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
The current failing unit-test checks appear unrelated to this example PR. They are coming from existing repo-level issues outside
This PR only adds the new multilingual example under |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
examples/multilingual-collab-agent/main.py (2)
158-166: PotentialNonedereference if agent initialization fails.If
build_agent()raises an exception after_initializedis set toTrue(which it won't in current flow, but could with refactoring), or if the assignment order changes,agentcould remainNonewhen accessed on line 165.Safer initialization pattern
async with _init_lock: if not _initialized: print("🔧 Initializing multilingual agent...") agent = build_agent() - _initialized = True print("✅ Agent initialized") + _initialized = True + if agent is None: + raise RuntimeError("Agent failed to initialize") + response = await agent.arun(messages) return response🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/multilingual-collab-agent/main.py` around lines 158 - 166, The current init block can leave `agent` None if `build_agent()` fails or order changes; change the pattern in the `_init_lock` critical section so you build and assign `agent` first and only set `_initialized = True` after `build_agent()` succeeds, or wrap the build in try/except and on exception ensure `_initialized` remains False (or reset it) and re-raise/log the error; specifically update the section using `_init_lock`, `_initialized`, `build_agent`, and `agent` (and the subsequent call to `agent.arun`) to guarantee `agent` is non-None before use.
40-44: Consider adding error handling for missing/malformed config file.If
agent_config.jsonis missing or contains invalid JSON, the error message may be unclear to users.Proposed improvement
def load_config() -> dict: """Load agent configuration from agent_config.json.""" config_path = Path(__file__).parent / "agent_config.json" - with open(config_path, "r") as f: - return json.load(f) + try: + with open(config_path, "r") as f: + return json.load(f) + except FileNotFoundError: + raise FileNotFoundError( + f"Configuration file not found: {config_path}\n" + "Ensure agent_config.json exists in the example directory." + ) + except json.JSONDecodeError as e: + raise ValueError(f"Invalid JSON in {config_path}: {e}")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/multilingual-collab-agent/main.py` around lines 40 - 44, The load_config function should handle missing or malformed agent_config.json: wrap the open+json.load calls in a try/except that catches FileNotFoundError and json.JSONDecodeError (or ValueError for older Python), and produce a clear error message including the config_path and the underlying exception; then either raise a RuntimeError with that message or call sys.exit(1) so callers get a meaningful failure. Update load_config to reference config_path in the error text and ensure you import json.JSONDecodeError (or handle ValueError) if needed.examples/multilingual-collab-agent/skills/translate/skill.yaml (1)
70-77: Consider documenting where OpenRouter configuration is managed.The documentation mentions that the skill uses "OpenRouter" as the LLM backend, but the manifest doesn't include API configuration details. While this separation is appropriate for a skill manifest, consider adding a brief note indicating where users should configure the OpenRouter API key (e.g., in environment variables or agent_config.json).
📝 Suggested documentation enhancement
overview: | The translate skill provides high-quality translation between English, Hindi, and Bengali using an LLM backend via OpenRouter. Unlike rule-based translators, it understands context and produces natural-sounding output. + + Configuration: Set OPENROUTER_API_KEY in your environment or configure + the LLM provider in agent_config.json. Particularly useful for technical content about Bindu and AI agents where standard translators produce poor results for domain-specific terms.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/multilingual-collab-agent/skills/translate/skill.yaml` around lines 70 - 77, Update the documentation:overview in skill.yaml to add a short note explaining where to configure OpenRouter credentials (e.g., set OPENROUTER_API_KEY as an environment variable or add the key to agent_config.json) so operators know where to place the API key and any region/endpoint settings; reference "OpenRouter" and the existing documentation: overview block to locate the spot to append this guidance.
🤖 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/multilingual-collab-agent/agent_config.json`:
- Around line 23-25: The "agent_trust" entry in the config is invalid (it's set
to the string "low"); remove the "agent_trust" key entirely from
agent_config.json so the system falls back to the default AgentTrust, or
alternatively replace it with a full AgentTrust TypedDict containing the
required fields (identity_provider, inherited_roles,
trust_verification_required, allowed_operations); locate the "agent_trust" key
in the JSON and delete that line to use the default trust configuration.
In `@examples/multilingual-collab-agent/main.py`:
- Around line 173-175: The three print calls that use f-strings but have no
interpolation should drop the unnecessary leading "f": update the print
statements that currently read print(f" Supported languages: English, Hindi
(हिन्दी), Bengali (বাংলা)"), print(f" Model: {os.getenv('MODEL_NAME',
'openai/gpt-4o-mini')}") — note: keep the second as an f-string only if you
intend to interpolate os.getenv; otherwise remove the f and concatenate or
format properly — and print(f" Memory: Mem0 persistent memory enabled") to
regular string prints without the f prefix (or convert the MODEL line to use
string concatenation/format if you want to preserve dynamic MODEL_NAME
retrieval).
- Around line 53-65: The code currently treats mem0_api_key inconsistently—raise
ValueError on missing mem0_api_key but also catches Mem0Tools failures and
continues; instead make Mem0 fully optional: remove the ValueError check for
mem0_api_key, only attempt to append Mem0Tools(api_key=mem0_api_key) to tools
when mem0_api_key is truthy, keep the try/except around Mem0Tools initialization
to log and continue on error, and update the runtime status/logging message that
reports memory availability (the code that prints "Mem0 unavailable: continues
without memory") to reflect whether Mem0 was actually initialized or skipped.
In `@examples/multilingual-collab-agent/README.md`:
- Around line 75-80: The README's `.env` fenced code block lacks a language
specifier; update the block in examples/multilingual-collab-agent/README.md
where the `.env` snippet appears so the opening fence is ```bash (or ```env)
instead of ``` to enable proper syntax highlighting for the OPENROUTER_API_KEY,
MEM0_API_KEY, and MODEL_NAME entries; simply change the code fence surrounding
the `.env` content to include the language specifier.
---
Nitpick comments:
In `@examples/multilingual-collab-agent/main.py`:
- Around line 158-166: The current init block can leave `agent` None if
`build_agent()` fails or order changes; change the pattern in the `_init_lock`
critical section so you build and assign `agent` first and only set
`_initialized = True` after `build_agent()` succeeds, or wrap the build in
try/except and on exception ensure `_initialized` remains False (or reset it)
and re-raise/log the error; specifically update the section using `_init_lock`,
`_initialized`, `build_agent`, and `agent` (and the subsequent call to
`agent.arun`) to guarantee `agent` is non-None before use.
- Around line 40-44: The load_config function should handle missing or malformed
agent_config.json: wrap the open+json.load calls in a try/except that catches
FileNotFoundError and json.JSONDecodeError (or ValueError for older Python), and
produce a clear error message including the config_path and the underlying
exception; then either raise a RuntimeError with that message or call
sys.exit(1) so callers get a meaningful failure. Update load_config to reference
config_path in the error text and ensure you import json.JSONDecodeError (or
handle ValueError) if needed.
In `@examples/multilingual-collab-agent/skills/translate/skill.yaml`:
- Around line 70-77: Update the documentation:overview in skill.yaml to add a
short note explaining where to configure OpenRouter credentials (e.g., set
OPENROUTER_API_KEY as an environment variable or add the key to
agent_config.json) so operators know where to place the API key and any
region/endpoint settings; reference "OpenRouter" and the existing documentation:
overview block to locate the spot to append this guidance.
🪄 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: 6010a247-830c-4432-9ae2-021829971b3c
📒 Files selected for processing (9)
examples/multilingual-collab-agent/.env.exampleexamples/multilingual-collab-agent/.gitignoreexamples/multilingual-collab-agent/README.mdexamples/multilingual-collab-agent/agent_config.jsonexamples/multilingual-collab-agent/main.pyexamples/multilingual-collab-agent/requirements.txtexamples/multilingual-collab-agent/skills/collaborate/skill.yamlexamples/multilingual-collab-agent/skills/research/skill.yamlexamples/multilingual-collab-agent/skills/translate/skill.yaml
| "agent_trust": "low", | ||
| "debug_mode": true, | ||
| "debug_level": 2, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check how agent_trust values are validated/processed in the codebase
echo "=== Searching for agent_trust validation/parsing ==="
rg -n -C3 'agent_trust' --type=py -g '!*test*'
echo ""
echo "=== Checking for 'low' as a valid trust level ==="
rg -n '"low"' bindu/ --type=pyRepository: GetBindu/Bindu
Length of output: 6141
🏁 Script executed:
# Find AgentTrust class definition
echo "=== Finding AgentTrust class definition ==="
rg -n "class AgentTrust" --type=py
echo ""
echo "=== Checking AgentTrust type definition (imports/type hints) ==="
rg -n "AgentTrust" bindu/common/models.py -A 10 | head -60
echo ""
echo "=== Checking if agent_trust is validated in config_validator ==="
rg -n "validate.*agent_trust\|agent_trust.*validate" --type=py -iRepository: GetBindu/Bindu
Length of output: 962
🏁 Script executed:
# Get the full AgentTrust TypedDict definition
echo "=== AgentTrust TypedDict definition ==="
rg -n "class AgentTrust" bindu/common/protocol/types.py -A 30
echo ""
echo "=== How is agent_trust loaded from config in bindufy.py ==="
rg -n "agent_trust" bindu/penguin/bindufy.py -B 5 -A 5 | head -80Repository: GetBindu/Bindu
Length of output: 2560
🏁 Script executed:
# Find TrustLevel definition
echo "=== TrustLevel definition ==="
rg -n "TrustLevel\|class.*Trust.*Level" bindu/common/protocol/types.py -A 10 | head -30
echo ""
echo "=== Check config_validator for how agent_trust is loaded/validated ==="
rg -n "def.*load\|agent_trust.*=" bindu/penguin/config_validator.py -B 3 -A 3 | head -60Repository: GetBindu/Bindu
Length of output: 159
🏁 Script executed:
# Read the full config_validator.py to understand validation logic
echo "=== config_validator.py content ==="
cat -n bindu/penguin/config_validator.py | head -100Repository: GetBindu/Bindu
Length of output: 3841
🏁 Script executed:
# Continue reading config_validator.py to see field type validation
cat -n bindu/penguin/config_validator.py | tail -n +100Repository: GetBindu/Bindu
Length of output: 8764
Remove or correct agent_trust configuration value.
The value "low" is invalid. agent_trust expects either null/omitted (to use default AgentTrust) or a complete AgentTrust TypedDict with required fields: identity_provider, inherited_roles, trust_verification_required, and allowed_operations. For this example configuration, remove the field entirely to use the default trust configuration.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/multilingual-collab-agent/agent_config.json` around lines 23 - 25,
The "agent_trust" entry in the config is invalid (it's set to the string "low");
remove the "agent_trust" key entirely from agent_config.json so the system falls
back to the default AgentTrust, or alternatively replace it with a full
AgentTrust TypedDict containing the required fields (identity_provider,
inherited_roles, trust_verification_required, allowed_operations); locate the
"agent_trust" key in the JSON and delete that line to use the default trust
configuration.
| if not openrouter_api_key: | ||
| raise ValueError("OPENROUTER_API_KEY environment variable is required.") | ||
| if not mem0_api_key: | ||
| raise ValueError( | ||
| "MEM0_API_KEY environment variable is required. " | ||
| "Get your key from: https://app.mem0.ai/dashboard/api-keys" | ||
| ) | ||
|
|
||
| tools = [DuckDuckGoTools()] | ||
| try: | ||
| tools.append(Mem0Tools(api_key=mem0_api_key)) | ||
| except Exception as e: | ||
| print(f"⚠️ Mem0 tools unavailable: {e}. Continuing without memory.") |
There was a problem hiding this comment.
Inconsistent handling of MEM0_API_KEY — required validation contradicts optional fallback.
Lines 55-59 raise a ValueError if MEM0_API_KEY is missing, but lines 62-65 catch exceptions during Mem0 initialization and continue without memory. This creates inconsistent behavior:
- Missing key → crash
- Key provided but init fails → graceful degradation
The skill manifest (collaborate/skill.yaml) documents "Mem0 unavailable: continues without memory", suggesting memory should be fully optional.
Proposed fix — make Mem0 fully optional
if not openrouter_api_key:
raise ValueError("OPENROUTER_API_KEY environment variable is required.")
- if not mem0_api_key:
- raise ValueError(
- "MEM0_API_KEY environment variable is required. "
- "Get your key from: https://app.mem0.ai/dashboard/api-keys"
- )
tools = [DuckDuckGoTools()]
- try:
- tools.append(Mem0Tools(api_key=mem0_api_key))
- except Exception as e:
- print(f"⚠️ Mem0 tools unavailable: {e}. Continuing without memory.")
+ if mem0_api_key:
+ try:
+ tools.append(Mem0Tools(api_key=mem0_api_key))
+ except Exception as e:
+ print(f"⚠️ Mem0 tools unavailable: {e}. Continuing without memory.")
+ else:
+ print("ℹ️ MEM0_API_KEY not set. Running without persistent memory.")Also update line 175 to reflect dynamic memory status:
- print(f" Memory: Mem0 persistent memory enabled")
+ mem0_status = "enabled" if os.getenv("MEM0_API_KEY") else "disabled (no API key)"
+ print(f" Memory: Mem0 persistent memory {mem0_status}")📝 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.
| if not openrouter_api_key: | |
| raise ValueError("OPENROUTER_API_KEY environment variable is required.") | |
| if not mem0_api_key: | |
| raise ValueError( | |
| "MEM0_API_KEY environment variable is required. " | |
| "Get your key from: https://app.mem0.ai/dashboard/api-keys" | |
| ) | |
| tools = [DuckDuckGoTools()] | |
| try: | |
| tools.append(Mem0Tools(api_key=mem0_api_key)) | |
| except Exception as e: | |
| print(f"⚠️ Mem0 tools unavailable: {e}. Continuing without memory.") | |
| if not openrouter_api_key: | |
| raise ValueError("OPENROUTER_API_KEY environment variable is required.") | |
| tools = [DuckDuckGoTools()] | |
| if mem0_api_key: | |
| try: | |
| tools.append(Mem0Tools(api_key=mem0_api_key)) | |
| except Exception as e: | |
| print(f"⚠️ Mem0 tools unavailable: {e}. Continuing without memory.") | |
| else: | |
| print("ℹ️ MEM0_API_KEY not set. Running without persistent memory.") |
🧰 Tools
🪛 Ruff (0.15.7)
[warning] 64-64: 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/multilingual-collab-agent/main.py` around lines 53 - 65, The code
currently treats mem0_api_key inconsistently—raise ValueError on missing
mem0_api_key but also catches Mem0Tools failures and continues; instead make
Mem0 fully optional: remove the ValueError check for mem0_api_key, only attempt
to append Mem0Tools(api_key=mem0_api_key) to tools when mem0_api_key is truthy,
keep the try/except around Mem0Tools initialization to log and continue on
error, and update the runtime status/logging message that reports memory
availability (the code that prints "Mem0 unavailable: continues without memory")
to reflect whether Mem0 was actually initialized or skipped.
| print(f" Supported languages: English, Hindi (हिन्दी), Bengali (বাংলা)") | ||
| print(f" Model: {os.getenv('MODEL_NAME', 'openai/gpt-4o-mini')}") | ||
| print(f" Memory: Mem0 persistent memory enabled") |
There was a problem hiding this comment.
Remove extraneous f prefix from strings without placeholders.
These f-strings contain no interpolation expressions.
Proposed fix
- print(f" Supported languages: English, Hindi (हिन्दी), Bengali (বাংলা)")
+ print(" Supported languages: English, Hindi (हिन्दी), Bengali (বাংলা)")
print(f" Model: {os.getenv('MODEL_NAME', 'openai/gpt-4o-mini')}")
- print(f" Memory: Mem0 persistent memory enabled")
+ print(" Memory: Mem0 persistent memory enabled")📝 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.
| print(f" Supported languages: English, Hindi (हिन्दी), Bengali (বাংলা)") | |
| print(f" Model: {os.getenv('MODEL_NAME', 'openai/gpt-4o-mini')}") | |
| print(f" Memory: Mem0 persistent memory enabled") | |
| print(" Supported languages: English, Hindi (हिन्दी), Bengali (বাংলা)") | |
| print(f" Model: {os.getenv('MODEL_NAME', 'openai/gpt-4o-mini')}") | |
| print(" Memory: Mem0 persistent memory enabled") |
🧰 Tools
🪛 Ruff (0.15.7)
[error] 173-173: f-string without any placeholders
Remove extraneous f prefix
(F541)
[error] 175-175: f-string without any placeholders
Remove extraneous f prefix
(F541)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/multilingual-collab-agent/main.py` around lines 173 - 175, The three
print calls that use f-strings but have no interpolation should drop the
unnecessary leading "f": update the print statements that currently read
print(f" Supported languages: English, Hindi (हिन्दी), Bengali (বাংলা)"),
print(f" Model: {os.getenv('MODEL_NAME', 'openai/gpt-4o-mini')}") — note: keep
the second as an f-string only if you intend to interpolate os.getenv; otherwise
remove the f and concatenate or format properly — and print(f" Memory: Mem0
persistent memory enabled") to regular string prints without the f prefix (or
convert the MODEL line to use string concatenation/format if you want to
preserve dynamic MODEL_NAME retrieval).
| `.env` file: | ||
| ``` | ||
| OPENROUTER_API_KEY=your_openrouter_key | ||
| MEM0_API_KEY=your_mem0_key | ||
| MODEL_NAME=openai/gpt-4o-mini | ||
| ``` |
There was a problem hiding this comment.
Add language specifier to the .env code block.
The fenced code block should have a language specifier for proper syntax highlighting.
Proposed fix
`.env` file:
-```
+```bash
OPENROUTER_API_KEY=your_openrouter_key
MEM0_API_KEY=your_mem0_key
MODEL_NAME=openai/gpt-4o-mini</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **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.
```suggestion
`.env` file:
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 76-76: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/multilingual-collab-agent/README.md` around lines 75 - 80, The
README's `.env` fenced code block lacks a language specifier; update the block
in examples/multilingual-collab-agent/README.md where the `.env` snippet appears
so the opening fence is ```bash (or ```env) instead of ``` to enable proper
syntax highlighting for the OPENROUTER_API_KEY, MEM0_API_KEY, and MODEL_NAME
entries; simply change the code fence surrounding the `.env` content to include
the language specifier.
Summary
Describe the problem and fix in 2–5 bullets:
examples/multilingual-collab-agent/with agent implementation, config, env template, requirements, three skill manifests, and README documentation.Change Type (select all that apply)
Scope (select all touched areas)
Linked Issue/PR
User-Visible / Behavior Changes
examples/multilingual-collab-agentSecurity Impact (required)
No)No)No)No)No)Yes, explain risk + mitigation: NoneVerification
Environment
F:\Bindu\.venv\Scripts\python.exe)Steps to Test
examples/multilingual-collab-agentmain.py,agent_config.json,requirements.txt, skill manifests, andREADME.mdExpected Behavior
Actual Behavior
examples/multilingual-collab-agentEvidence (attach at least one)
Human Verification (required)
What you personally verified (not just CI):
uv.lockCompatibility / Migration
Yes)No)No)Failure Recovery (if this breaks)
examples/multilingual-collab-agentexamples/multilingual-collab-agent/*Risks and Mitigations
examples/and can be updated independently without affecting core runtime behaviorChecklist
uv run pytest)uv run pre-commit run --all-files)Summary by CodeRabbit
New Features
Documentation