Skip to content

Conversation

Dharya4242
Copy link

@Dharya4242 Dharya4242 commented Oct 5, 2025

Closes #116

📝 Description

Graph-based onboarding flow that branches on GitHub verification and routes exploration into the GitHub toolkit (MCP-backed). Centralizes onboarding copy, persists minimal onboarding state, and aligns Discord DM onboarding with the same messages and stages.

Goals:

  • Welcome users, nudge verification, and clearly advertise DevRel capabilities per the design doc.
  • Avoid hardcoding GitHub answers in onboarding; auto-route to github_toolkit so MCP-powered repo/org queries answer user prompts.
  • Keep channel UX consistent via reusable messages and a simple state machine.

🔧 Changes Made

Onboarding state machine and copy

  • Add shared onboarding copy and capability sections:
    backend/app/agents/devrel/onboarding/messages.py
  • Add workflow controller (stages: intro, awaiting_choice, encourage_verification, verified_capabilities, completed):
    backend/app/agents/devrel/onboarding/workflow.py
  • Update handler to use workflow and emit stage, next_tool, and capability_sections:
    backend/app/agents/devrel/nodes/handlers/onboarding.py

State + routing integration

  • Persist onboarding_state in AgentState:
    backend/app/agents/state.py
  • Tool wrapper stores onboarding state and sets force_next_tool:
    backend/app/agents/devrel/tool_wrappers.py
  • Supervisor honors force_next_tool to jump straight to github_toolkit:
    backend/app/agents/devrel/nodes/react_supervisor.py

Discord UX alignment

  • Reuse shared messages; verified users get capability intro + final handoff:
    backend/integrations/discord/cogs.py

  • Capability embed mirrors shared sections; add “I’ve verified” button to re-check linkage:
    backend/integrations/discord/views.py

  • Onboarding now hands off to github_toolkit, which integrates with the MCP-backed GitHub service via github_support.

🤝 Collaboration

Guidance from: @smokeyScraper


✅ Checklist

  • I have read the contributing guidelines.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if applicable).
  • Any dependent changes have been merged and published in downstream modules.

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented multi-stage onboarding workflow for new users with verification checks.
    • Added automatic onboarding flow when members join Discord server.
    • Introduced post-verification direct message with capabilities overview.
    • Added interactive onboarding buttons in Discord (verify, skip).
    • Made OAuth button visibility configurable in onboarding settings.
  • Chores

    • Added MCP server configuration options for backend integration.

Copy link
Contributor

coderabbitai bot commented Oct 5, 2025

Walkthrough

Implements a comprehensive onboarding workflow for new Discord users, featuring multi-stage state machine logic (INTRO → AWAITING_CHOICE → ENCOURAGE_VERIFICATION → VERIFIED_CAPABILITIES → COMPLETED), integrating messaging, Discord views, agent node handlers, authentication callbacks, and configuration settings to welcome users, prompt GitHub verification, and advertise agent capabilities.

Changes

Cohort / File(s) Summary
Onboarding Workflow & State Management
backend/app/agents/devrel/onboarding/workflow.py, backend/app/agents/devrel/onboarding/messages.py, backend/app/agents/state.py
Introduces OnboardingStage enum (INTRO, AWAITING_CHOICE, ENCOURAGE_VERIFICATION, VERIFIED_CAPABILITIES, COMPLETED), OnboardingFlowResult data structure, and run_onboarding_flow orchestrator implementing a multi-stage state machine. Adds messaging primitives (welcome, verification, capabilities) with conditional rendering based on verification/GitHub status. Extends AgentState with onboarding_state field for tracking flow progress.
Agent Node Handlers
backend/app/agents/devrel/nodes/handlers/onboarding.py, backend/app/agents/devrel/nodes/react_supervisor.py, backend/app/agents/devrel/nodes/gather_context.py
Updates handle_onboarding_node to return Dict[str, Any] with richer task_result/current_task instead of AgentState, invokes run_onboarding_flow with extracted context (latest_message, is_verified, github_username). Adds early-exit paths to react_supervisor_node for force_next_tool and force_complete flags. Enhances gather_context.py with Discord-specific user profile refresh via get_or_create_user_by_discord.
Tool Wrappers & State Flow
backend/app/agents/devrel/tool_wrappers.py
Refactors onboarding_tool_node and github_toolkit_tool_node to build state_update from add_tool_result, propagate onboarding_state from handler results, and manage force_next_tool/complete_after_forced_tool/force_complete flags for flow control.
Discord Integration
backend/integrations/discord/cogs.py, backend/integrations/discord/views.py
Introduces OnboardingCog with on_member_join handler triggering _send_onboarding_flow for all new members, user profile creation/fetch, conditional OAuth button rendering, and DM dispatch. Adds OnboardingView with check_verified and skip button handlers for user interaction, plus helper functions build_final_handoff_embed and send_final_handoff_dm for capability advertisement.
Authentication & Configuration
backend/app/api/v1/auth.py, backend/app/core/config/settings.py
Extends auth_callback with app_instance dependency injection to enable post-verification Discord DM handoff messaging. Updates error messages to reference slash commands. Adds three configuration fields: onboarding_show_oauth_button, mcp_server_url, mcp_api_key.
Minor Fixes
backend/app/agents/devrel/github/tools/general_github_help.py
Formatting adjustment in exception return block (no functional change).

Sequence Diagram

sequenceDiagram
    actor User as Discord User
    participant Bot as Discord Bot
    participant OnboardingCog
    participant OnboardingWorkflow
    participant AgentHandler
    participant AuthCallback
    participant Discord as Discord DM

    User->>Bot: Joins Server
    Bot->>OnboardingCog: on_member_join(member)
    OnboardingCog->>OnboardingCog: get_or_create_user_by_discord()
    
    alt User Verified
        OnboardingCog->>OnboardingWorkflow: run_onboarding_flow(state, ..., is_verified=True)
        OnboardingWorkflow->>OnboardingWorkflow: INTRO → VERIFIED_CAPABILITIES
    else User Not Verified
        OnboardingCog->>OnboardingWorkflow: run_onboarding_flow(state, ..., is_verified=False)
        OnboardingWorkflow->>OnboardingWorkflow: INTRO → AWAITING_CHOICE
    end
    
    OnboardingWorkflow-->>OnboardingCog: OnboardingFlowResult + state_update
    OnboardingCog->>OnboardingCog: _build_welcome_embed()
    OnboardingCog->>Discord: Send DM with OnboardingView
    
    alt User Clicks "Verify GitHub"
        User->>Discord: Click verify button
        Discord->>AuthCallback: POST /auth/github/callback?session=...
        AuthCallback->>AuthCallback: Verify GitHub OAuth
        AuthCallback->>Discord: send_final_handoff_dm(user)
        Discord->>User: Final capabilities embed
    else User Clicks "Skip"
        User->>Discord: Click skip button
        Discord->>Discord: send_final_handoff_dm(user)
        Discord->>User: Final capabilities embed
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Rationale: This PR introduces a multi-stage onboarding state machine with dense logic, non-trivial state transitions, and verification/routing conditions. Changes span ten files across agent nodes, Discord integration, authentication, and state management—heterogeneous in nature, requiring separate reasoning for workflow orchestration, state flow synchronization, Discord UX interactions, and auth callback modifications. The interconnected dependencies between workflow stages, node handlers, and Discord views demand careful validation of state consistency and control flow correctness.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • smokeyScraper

🐰 A workflow blooms in stages bright,
From intro's warmth to verified light,
New bunnies skip and hop with glee,
Their GitHub linked, capabilities free!
Onboarding flows through Discord's door,
Welcome home, explore and soar! 🚀

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title Check ⚠️ Warning The pull request title "feat: route onboarding flow through MCP-backed GitHub toolkit" refers to a real and important aspect of the implementation—specifically, the routing of the onboarding handoff to the GitHub toolkit via force_next_tool and the supervisor's early-exit paths. However, this represents only one facet of the broader work, which encompasses the complete structured onboarding workflow system with multiple stages (INTRO, AWAITING_CHOICE, ENCOURAGE_VERIFICATION, VERIFIED_CAPABILITIES, COMPLETED), centralized messaging and capability sections, onboarding state persistence, and Discord integration. The title emphasizes the routing/handoff mechanism rather than the primary change—the implementation of the entire conversational onboarding workflow itself. Consider updating the title to reflect the primary implementation: for example, "feat: implement structured onboarding workflow with GitHub toolkit handoff" or "feat: add multi-stage onboarding workflow for new contributors". This would more accurately capture that the work centers on building the onboarding flow system rather than simply routing through an existing toolkit.
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues Check ✅ Passed The pull request successfully addresses all primary coding-related objectives from issue #116. The implementation provides a structured conversational workflow managed by an OnboardingNode with multiple stages (workflow.py), checks GitHub verification status and conditionally routes to verification encouragement (workflow.py, run_onboarding_flow logic), concludes onboarding by advertising DevRel Agent capabilities through VERIFIED_CAPABILITIES and COMPLETED stages (workflow.py, messages.py), improves the new-member experience via Discord integration (cogs.py, views.py), emphasizes user autonomy by referencing /verify and /help commands in messages (messages.py), and hands off subsequent complex queries to the GitHub toolkit via force_next_tool routing (tool_wrappers.py, react_supervisor.py). All core requirements for welcoming new users, checking verification, advertising capabilities, and maintaining focused node responsibility are met.
Out of Scope Changes Check ✅ Passed All code changes are appropriately scoped to the onboarding workflow feature. The workflow and messaging modules (workflow.py, messages.py) form the core implementation; state persistence (state.py), handler updates (onboarding.py), and supervisor/tool wrapper changes (react_supervisor.py, tool_wrappers.py) enable the workflow integration; Discord integration (cogs.py, views.py) and configuration additions (settings.py) support deployment; and supporting changes to auth.py (DM sending on verification), gather_context.py (Discord user profile refresh), and general_github_help.py (formatting) all directly enable or support the onboarding feature. No extraneous modifications unrelated to structured onboarding or its integration with the GitHub toolkit were detected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
Contributor

@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 (2)
backend/app/agents/devrel/github/tools/general_github_help.py (1)

11-12: Update docstring to document the hint parameter.

The function signature correctly adds the optional hint parameter, but the docstring should be updated to explain its purpose and behavior.

Apply this diff to enhance the docstring:

 async def handle_general_github_help(query: str, llm, hint: Optional[str] = None) -> Dict[str, Any]:
-    """Execute general GitHub help with web search and LLM knowledge"""
+    """
+    Execute general GitHub help with web search and LLM knowledge.
+    
+    Args:
+        query: The user's GitHub-related question
+        llm: The language model to use for generating responses
+        hint: Optional assistant hint to augment the prompt context
+    
+    Returns:
+        Dict containing status, response, and metadata
+    """
backend/app/agents/devrel/onboarding/messages.py (1)

65-74: Consider sanitizing the github_username parameter for markdown safety.

The github_username parameter is wrapped in backticks for markdown formatting (lines 69, 92) without validation. If a username contains backticks or other markdown special characters, it could break the formatting or potentially cause injection issues in the rendered message.

Consider adding a helper function to sanitize usernames before embedding them in formatted strings:

def _sanitize_username(username: str) -> str:
    """Escape markdown special characters in username."""
    # Escape backticks and other markdown characters
    return username.replace("`", "\\`").replace("*", "\\*").replace("_", "\\_")

Then use it when building messages:

 def build_verified_welcome(github_username: Optional[str] = None) -> str:
     """Welcome copy for returning verified contributors."""
     greeting = "👋 Welcome back to the Devr.AI community!"
     if github_username:
-        greeting += f" I see `{github_username}` is already linked, which is great."
+        greeting += f" I see `{_sanitize_username(github_username)}` is already linked, which is great."

Also applies to: 88-98

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 452a278 and 707d33e.

📒 Files selected for processing (12)
  • backend/app/agents/devrel/github/tools/general_github_help.py (3 hunks)
  • backend/app/agents/devrel/nodes/handlers/onboarding.py (1 hunks)
  • backend/app/agents/devrel/nodes/react_supervisor.py (1 hunks)
  • backend/app/agents/devrel/onboarding/messages.py (1 hunks)
  • backend/app/agents/devrel/onboarding/workflow.py (1 hunks)
  • backend/app/agents/devrel/tool_wrappers.py (1 hunks)
  • backend/app/agents/state.py (1 hunks)
  • backend/app/api/v1/auth.py (5 hunks)
  • backend/app/core/config/settings.py (1 hunks)
  • backend/app/integrations/mcp/client.py (1 hunks)
  • backend/integrations/discord/cogs.py (2 hunks)
  • backend/integrations/discord/views.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
backend/app/agents/devrel/tool_wrappers.py (1)
backend/app/agents/devrel/nodes/react_supervisor.py (1)
  • add_tool_result (98-114)
backend/app/agents/devrel/github/tools/general_github_help.py (1)
backend/app/services/embedding_service/service.py (1)
  • llm (55-68)
backend/integrations/discord/cogs.py (5)
backend/app/agents/devrel/onboarding/messages.py (4)
  • build_encourage_verification_message (77-85)
  • build_new_user_welcome (51-62)
  • build_verified_capabilities_intro (88-98)
  • build_verified_welcome (65-74)
backend/app/services/auth/management.py (1)
  • get_or_create_user_by_discord (10-41)
backend/app/services/auth/supabase.py (1)
  • login_with_github (28-30)
backend/app/services/auth/verification.py (1)
  • create_verification_session (33-61)
backend/integrations/discord/views.py (3)
  • OAuthView (36-49)
  • OnboardingView (52-120)
  • build_final_handoff_embed (11-24)
backend/app/agents/devrel/onboarding/workflow.py (2)
backend/app/agents/state.py (1)
  • AgentState (18-76)
backend/app/agents/devrel/onboarding/messages.py (5)
  • build_verified_capabilities_intro (88-98)
  • render_capabilities_text (39-48)
  • build_new_user_welcome (51-62)
  • build_encourage_verification_message (77-85)
  • build_verified_welcome (65-74)
backend/integrations/discord/views.py (2)
backend/app/services/auth/management.py (1)
  • get_or_create_user_by_discord (10-41)
backend/app/models/database/supabase.py (1)
  • User (7-69)
backend/app/api/v1/auth.py (6)
backend/app/database/supabase/client.py (1)
  • get_supabase_client (9-13)
backend/app/services/auth/verification.py (2)
  • find_user_by_session_and_verify (63-135)
  • get_verification_session_info (156-176)
backend/app/services/github/user/profiling.py (2)
  • profile_user_from_github (301-333)
  • request (77-79)
backend/app/core/dependencies.py (1)
  • get_app_instance (7-12)
backend/integrations/discord/views.py (1)
  • send_final_handoff_dm (27-34)
backend/main.py (1)
  • DevRAIApplication (26-87)
backend/app/agents/devrel/nodes/handlers/onboarding.py (2)
backend/app/agents/devrel/onboarding/workflow.py (2)
  • OnboardingStage (12-19)
  • run_onboarding_flow (87-276)
backend/app/agents/state.py (1)
  • AgentState (18-76)
🪛 Ruff (0.13.3)
backend/integrations/discord/cogs.py

228-228: String contains ambiguous (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?

(RUF001)


264-265: try-except-pass detected, consider logging the exception

(S110)


264-264: Do not catch blind exception: Exception

(BLE001)


280-281: try-except-pass detected, consider logging the exception

(S110)


280-280: Do not catch blind exception: Exception

(BLE001)


293-294: try-except-pass detected, consider logging the exception

(S110)


293-293: Do not catch blind exception: Exception

(BLE001)


300-300: Consider moving this statement to an else block

(TRY300)


303-303: Do not catch blind exception: Exception

(BLE001)


304-304: Use logging.exception instead of logging.error

Replace with exception

(TRY400)


308-309: try-except-pass detected, consider logging the exception

(S110)


308-308: Do not catch blind exception: Exception

(BLE001)

backend/app/integrations/mcp/client.py

8-8: Do not catch blind exception: Exception

(BLE001)


31-31: Avoid specifying long messages outside the exception class

(TRY003)


43-43: Avoid specifying long messages outside the exception class

(TRY003)


47-47: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


47-47: Avoid specifying long messages outside the exception class

(TRY003)


50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


50-50: Avoid specifying long messages outside the exception class

(TRY003)


50-50: Use explicit conversion flag

Replace with conversion flag

(RUF010)

backend/integrations/discord/views.py

32-34: try-except-pass detected, consider logging the exception

(S110)


32-32: Do not catch blind exception: Exception

(BLE001)


73-73: Unused method argument: button

(ARG002)


84-84: Do not catch blind exception: Exception

(BLE001)


102-103: try-except-pass detected, consider logging the exception

(S110)


102-102: Do not catch blind exception: Exception

(BLE001)


111-111: Unused method argument: button

(ARG002)


118-120: try-except-pass detected, consider logging the exception

(S110)


118-118: Do not catch blind exception: Exception

(BLE001)

backend/app/api/v1/auth.py

21-21: Unused function argument: request

(ARG001)


24-24: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable

(B008)


98-98: Do not catch blind exception: Exception

(BLE001)

backend/app/agents/devrel/nodes/handlers/onboarding.py

31-32: try-except-pass detected, consider logging the exception

(S110)


31-31: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (8)
backend/app/agents/devrel/github/tools/general_github_help.py (1)

1-1: LGTM!

The Optional import is correctly added to support the new hint parameter's type annotation.

backend/app/agents/state.py (1)

29-31: Onboarding state persistence looks good.

Defaulting to an empty dict matches the rest of the state model and cleanly unlocks the new workflow.

backend/app/core/config/settings.py (1)

42-48: Configuration surface extension is consistent.

The new fields follow existing conventions, so wiring them through env vars should be seamless.

backend/app/agents/devrel/tool_wrappers.py (1)

33-44: Onboarding wrapper propagation looks solid.

State updates now carry onboarding_state and force the next tool when present—nice alignment with the supervisor shortcut.

backend/app/agents/devrel/nodes/react_supervisor.py (1)

20-37: Force-next-tool shortcut is clean.

The auto-route path removes the flag, records the decision, and bumps the iteration counter—exactly what the flow needs.

backend/app/agents/devrel/onboarding/messages.py (3)

39-48: LGTM!

The capability text rendering logic is clear and produces well-formatted output. The function correctly iterates through sections and formats examples with proper spacing.


12-12: Verify repository name: ensure the hardcoded 'Devr.AI-backend' matches the actual GitHub repository’s name (including exact capitalization, punctuation, and hyphenation) to avoid confusion.


58-60: Referenced Discord commands exist and are registered
All commands (/verify_github, /verification_status, /help) are defined in backend/integrations/discord/cogs.py.

Comment on lines 26 to 35
if hint:
help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
query=f"{query}\n\nAssistant hint: {hint}",
search_context=search_context
)
else:
help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
query=query,
search_context=search_context
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Eliminate code duplication in prompt construction.

The GENERAL_GITHUB_HELP_PROMPT.format() call is duplicated in both branches, violating the DRY principle. Construct the augmented query first, then format once.

Apply this diff to refactor the conditional logic:

-        if hint:
-            help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
-                query=f"{query}\n\nAssistant hint: {hint}",
-                search_context=search_context
-            )
-        else:
-            help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
-                query=query,
-                search_context=search_context
-            )
+        augmented_query = f"{query}\n\nAssistant hint: {hint}" if hint else query
+        help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
+            query=augmented_query,
+            search_context=search_context
+        )
📝 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
if hint:
help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
query=f"{query}\n\nAssistant hint: {hint}",
search_context=search_context
)
else:
help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
query=query,
search_context=search_context
)
augmented_query = f"{query}\n\nAssistant hint: {hint}" if hint else query
help_prompt = GENERAL_GITHUB_HELP_PROMPT.format(
query=augmented_query,
search_context=search_context
)
🤖 Prompt for AI Agents
In backend/app/agents/devrel/github/tools/general_github_help.py around lines 26
to 35, the GENERAL_GITHUB_HELP_PROMPT.format() call is duplicated; refactor by
first building an augmented query string (include the hint when present, e.g.,
augmented_query = f"{query}\n\nAssistant hint: {hint}" if hint else query) and
then call GENERAL_GITHUB_HELP_PROMPT.format(query=augmented_query,
search_context=search_context) once to eliminate duplication.

Comment on lines 38 to 50
async with aiohttp.ClientSession() as session:
try:
async with session.post(self.server_url, headers=headers, json=payload, timeout=timeout) as resp:
text = await resp.text()
if resp.status >= 400:
raise MCPClientError(f"MCP HTTP {resp.status}: {text}")
try:
data = json.loads(text)
except json.JSONDecodeError:
raise MCPClientError("MCP returned invalid JSON")
return data
except asyncio.TimeoutError as e:
raise MCPClientError(f"MCP timeout: {str(e)}")
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Wrap aiohttp transport errors in MCPClientError.

Right now any aiohttp.ClientError (DNS failure, refused connection, etc.) bubbles up directly, so callers stop seeing the unified MCPClientError your docstring implies. Please catch those and re-raise as MCPClientError (ideally using raise … from e) to keep error handling consistent.

Apply this diff:

         async with aiohttp.ClientSession() as session:
             try:
                 async with session.post(self.server_url, headers=headers, json=payload, timeout=timeout) as resp:
                     text = await resp.text()
                     if resp.status >= 400:
                         raise MCPClientError(f"MCP HTTP {resp.status}: {text}")
                     try:
                         data = json.loads(text)
                     except json.JSONDecodeError as e:
-                        raise MCPClientError("MCP returned invalid JSON")
+                        raise MCPClientError("MCP returned invalid JSON") from e
                     return data
-            except asyncio.TimeoutError as e:
-                raise MCPClientError(f"MCP timeout: {str(e)}")
+            except asyncio.TimeoutError as e:
+                raise MCPClientError(f"MCP timeout: {e}") from e
+            except aiohttp.ClientError as e:
+                raise MCPClientError(f"MCP transport error: {e}") from e

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Ruff (0.13.3)

43-43: Avoid specifying long messages outside the exception class

(TRY003)


47-47: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


47-47: Avoid specifying long messages outside the exception class

(TRY003)


50-50: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


50-50: Avoid specifying long messages outside the exception class

(TRY003)


50-50: Use explicit conversion flag

Replace with conversion flag

(RUF010)

🤖 Prompt for AI Agents
In backend/app/integrations/mcp/client.py around lines 38 to 50, transport-level
aiohttp.ClientError exceptions (DNS failures, connection refused, etc.) are not
being caught and thus escape as raw aiohttp errors; catch aiohttp.ClientError in
the existing try/except block (or add an except clause) and re-raise as an
MCPClientError using "raise MCPClientError(... ) from e" so callers always
receive MCPClientError while preserving the original error context.

it was committed by mistake ,i was experimenting with MCPs
@Dharya4242 Dharya4242 marked this pull request as draft October 9, 2025 14:15
@smokeyScraper
Copy link
Contributor

Any updates @Dharya4242 ?

@Dharya4242
Copy link
Author

Hey @smokeyScraper
I’ll be working on this tonight to resolve the errors and will update you with my progress tomorrow.

@smokeyScraper
Copy link
Contributor

cool man, actually i was preferring to close all the current issues by working on them myself, but you can give it a try and align it as per your way and then can share your branch's access to me as a collaborator so that I can make commits on top of yours if I feel like a few changes over yours. This way you too would learn from your mistakes in a better way (if any) as I'd be correcting them out.

Thanks!

@Dharya4242
Copy link
Author

got it , sounds great. Really appreciate the opportunity to learn and your guidance

@Dharya4242 Dharya4242 marked this pull request as ready for review October 17, 2025 21:26
Copy link
Contributor

@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: 0

🧹 Nitpick comments (7)
backend/app/agents/devrel/nodes/gather_context.py (2)

28-46: Discord avatar URL construction, PII logging, and exception scope

  • author['avatar'] is a hash, not a URL. Build the CDN URL when only a hash is available.
  • Redact discord_id in logs.
  • Consider narrowing the catch or documenting why a broad catch is acceptable (to address BLE001), and optionally throttle DB calls if profile is already fresh.
-        avatar_url = author.get("avatar") or author.get("avatar_url")
+        avatar_hash = author.get("avatar")
+        avatar_url = author.get("avatar_url")
+        if not avatar_url and avatar_hash and discord_id:
+            # Discord CDN avatar URL format; default to 256px
+            avatar_url = f"https://cdn.discordapp.com/avatars/{discord_id}/{avatar_hash}.png?size=256"
@@
-        if discord_id:
-            try:
+        if discord_id:
+            try:
                 user = await get_or_create_user_by_discord(
@@
                 )
                 profile_data = user.model_dump()
-            except Exception as exc:  # pragma: no cover - graceful degradation
-                logger.warning("Failed to refresh Discord user profile for %s: %s", discord_id, exc)
+            except Exception as exc:  # noqa: BLE001  # Graceful degradation; service raises heterogeneous errors
+                redacted = str(discord_id)
+                if len(redacted) > 6:
+                    redacted = f"{redacted[:2]}***{redacted[-2:]}"
+                logger.warning("Failed to refresh Discord user profile for id=%s: %s", redacted, exc)

Optional (future): cache a last_profile_refresh timestamp in state.context and skip refresh within N minutes to reduce DB load.


55-63: Minor: timezones for last_interaction_time (optional)

If/when the codebase moves to TZ-aware datetimes, switch to datetime.now(tz=timezone.utc) for consistency; current usage matches AgentState defaults.

backend/app/agents/devrel/onboarding/workflow.py (4)

39-46: Broaden intent detection to cover common phrasings

Improve coverage for “verify/verification/gh” and skip phrasings.

-_INTENT_VERIFIED = re.compile(r"\b(i\s*(have)?\s*)?(linked|connected|verified)\b.*github", re.IGNORECASE)
+_INTENT_VERIFIED = re.compile(r"\b(i\s*(have|am)?\s*)?(verify|verified|link(?:ed)?|connect(?:ed)?)\b.*\b(github|gh)\b", re.IGNORECASE)
-_INTENT_SKIP = re.compile(r"\b(skip|later|not\s+now)\b", re.IGNORECASE)
+_INTENT_SKIP = re.compile(r"\b(skip|later|not\s+now|skip\s+for\s+now)\b", re.IGNORECASE)
-_INTENT_HELP = re.compile(r"\b(how|help|can't|cannot|stuck)\b.*verify", re.IGNORECASE)
+_INTENT_HELP = re.compile(r"\b(how|help|can.?t|cannot|stuck)\b.*verif(y|ication|y(ing)?)", re.IGNORECASE)

107-127: DRY up verified-capabilities/completed branches

Four nearly identical blocks construct verified responses. Extract a small helper to build the result to reduce maintenance risk.

+def _verified_response(github_username: Optional[str], capability_sections) -> OnboardingFlowResult:
+    return OnboardingFlowResult(
+        stage=OnboardingStage.VERIFIED_CAPABILITIES,
+        status="completed",
+        welcome_message=messages.build_verified_capabilities_intro(github_username),
+        final_message=messages.render_capabilities_text(),
+        actions=_exploration_suggestions(),
+        is_verified=True,
+        capability_sections=capability_sections,
+        route_hint="onboarding",
+        handoff="github_toolkit",
+        next_tool="github_toolkit",
+    )
@@
-            intro = messages.build_verified_capabilities_intro(github_username)
-            return (
-                OnboardingFlowResult(
-                    stage=OnboardingStage.VERIFIED_CAPABILITIES,
-                    status="completed",
-                    welcome_message=intro,
-                    final_message=messages.render_capabilities_text(),
-                    actions=_exploration_suggestions(),
-                    is_verified=True,
-                    capability_sections=capability_sections,
-                    route_hint="onboarding",
-                    handoff="github_toolkit",
-                    next_tool="github_toolkit",
-                ),
-                onboarding_state,
-            )
+            return (_verified_response(github_username, capability_sections), onboarding_state)

Apply similarly to the other verified transitions.

Also applies to: 145-165, 204-224, 245-261


226-241: Cap reminders to avoid unbounded growth

Consider a max_reminders cap (e.g., 3) and stop incrementing, to prevent ever-growing counters in persisted state.

-    onboarding_state["reminders_sent"] = reminders_sent + 1
+    max_reminders = 3
+    onboarding_state["reminders_sent"] = min(reminders_sent + 1, max_reminders)

22-37: Consider adding to_dict() as defensive serialization, though current handler already converts stage.value

Verification shows the handler at backend/app/agents/devrel/nodes/handlers/onboarding.py:43 already converts flow_result.stage.value to string. The serialization concern is already addressed. Adding to_dict() to the dataclass would be a defensive measure to prevent future bugs if the handler pattern changes or if OnboardingFlowResult is used elsewhere without explicit serialization. Current code is safe as-is.

backend/app/agents/devrel/tool_wrappers.py (1)

33-46: Gate complete_after_forced_tool to supported tool

The stage value is already serialized as a string (.value in handle_onboarding_node), so the type check is safe. However, scope complete_after_forced_tool to the specific tool where it's cleared to avoid leaving stale routing flags. Only set it when next_tool == "github_toolkit".

     next_tool = tool_result.get("next_tool")
     if next_tool:
         context["force_next_tool"] = next_tool
-        if tool_result.get("stage") in {"verified_capabilities", "completed"}:
-            context["complete_after_forced_tool"] = next_tool
+        if next_tool == "github_toolkit" and tool_result.get("stage") in {"verified_capabilities", "completed"}:
+            context["complete_after_forced_tool"] = next_tool
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 707d33e and 7cca3ef.

📒 Files selected for processing (5)
  • backend/app/agents/devrel/github/tools/general_github_help.py (1 hunks)
  • backend/app/agents/devrel/nodes/gather_context.py (2 hunks)
  • backend/app/agents/devrel/nodes/react_supervisor.py (1 hunks)
  • backend/app/agents/devrel/onboarding/workflow.py (1 hunks)
  • backend/app/agents/devrel/tool_wrappers.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/app/agents/devrel/nodes/react_supervisor.py
  • backend/app/agents/devrel/github/tools/general_github_help.py
🧰 Additional context used
🧬 Code graph analysis (3)
backend/app/agents/devrel/tool_wrappers.py (1)
backend/app/agents/devrel/nodes/react_supervisor.py (1)
  • add_tool_result (114-130)
backend/app/agents/devrel/nodes/gather_context.py (2)
backend/app/agents/state.py (1)
  • AgentState (18-76)
backend/app/services/auth/management.py (1)
  • get_or_create_user_by_discord (10-41)
backend/app/agents/devrel/onboarding/workflow.py (2)
backend/app/agents/state.py (1)
  • AgentState (18-76)
backend/app/agents/devrel/onboarding/messages.py (5)
  • build_verified_capabilities_intro (88-98)
  • render_capabilities_text (39-48)
  • build_new_user_welcome (51-62)
  • build_encourage_verification_message (77-85)
  • build_verified_welcome (65-74)
🪛 Ruff (0.14.0)
backend/app/agents/devrel/nodes/gather_context.py

44-44: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (3)
backend/app/agents/devrel/nodes/gather_context.py (2)

26-27: Good: initialize profile_data from persisted state

Keeps prior profile fields when refresh fails.


48-48: Context default for user_profile is sensible

Fallback ensures downstream code always has minimal profile metadata.

backend/app/agents/devrel/tool_wrappers.py (1)

70-78: Verify whether the additional clearing is necessary given existing supervisor-level logic

The script output shows force_next_tool is already being cleared in react_supervisor.py:31 after the supervisor processes a forced action. The suggested addition in tool_wrappers.py would clear it earlier, but the existing mechanism in the supervisor node already handles removal.

To confirm if the suggested refactor is necessary or if the current flow already prevents re-routing loops, verify:

  • Whether the supervisor clears force_next_tool before re-evaluating on the next iteration (confirming the existing logic is sufficient), or
  • Whether there's a race condition where force_next_tool persists long enough to cause unwanted re-routing despite the completion flag being set

Without tracing the full state machine execution order between tool completion and supervisor re-evaluation, the necessity of the refactor is unclear.

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.

FEATURE REQUEST: Focused Onboarding Workflow for New Contributors

2 participants