Skip to content

[feat]: langsmith tracing integration#71

Closed
smokeyScraper wants to merge 20 commits into
AOSSIE-Org:mainfrom
smokeyScraper:langsmith_integration
Closed

[feat]: langsmith tracing integration#71
smokeyScraper wants to merge 20 commits into
AOSSIE-Org:mainfrom
smokeyScraper:langsmith_integration

Conversation

@smokeyScraper

@smokeyScraper smokeyScraper commented Jun 7, 2025

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Introduced an intelligent Discord bot that manages user support threads, classifies messages, and routes requests to specialized AI agents for developer relations, onboarding, technical support, FAQs, and web search.
    • Added advanced agent workflows for intent classification, context gathering, and tailored response generation using language models and web search tools.
    • Implemented asynchronous orchestration and queue management for prioritizing and handling agent requests and responses.
  • Bug Fixes

    • Removed outdated Discord bot implementation and legacy FastAPI server setup to streamline backend operations.
  • Chores

    • Updated environment variable templates and configuration management.
    • Refined project dependencies to support new AI agent and orchestration features.

@coderabbitai

coderabbitai Bot commented Jun 7, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a modular, agent-based backend architecture with a focus on developer relations (DevRel) automation. It adds a new Discord bot integrated with a queue-based orchestration system, agent state management, and specialized DevRel agent workflows. The FastAPI server is replaced by an asynchronous application coordinating agent execution and Discord interactions.

Changes

File(s) Change Summary
backend/.env.example, pyproject.toml Expanded environment variable placeholders, updated dependencies (removed Groq, added LangGraph, Tavily, LangChain, Pydantic settings, LangSmith).
backend/app/agents/__init__.py New module aggregating agent classes and routers for public API.
backend/app/agents/devrel/agent.py Introduces DevRelAgent class with workflow graph for DevRel support.
backend/app/agents/devrel/nodes/*.py Adds nodes for intent classification, context gathering, FAQ, onboarding, technical support, web search, and response generation.
backend/app/agents/devrel/prompts/*.py Adds prompt templates for LLM responses and search query extraction.
backend/app/agents/devrel/state.py Placeholder for DevRel-specific state extensions.
backend/app/agents/devrel/tools/faq_tool.py, search_tool.py Implements FAQ and Tavily web search tools with async methods and error handling.
backend/app/agents/shared/base_agent.py Adds BaseAgent class for LangGraph agent workflows, including async run and streaming.
backend/app/agents/shared/classification_router.py Adds message classification router with enums and LLM-based classification.
backend/app/agents/shared/state.py Introduces AgentState Pydantic model for agent session and context.
backend/app/core/config.py Adds Pydantic-based settings loader for environment configuration.
backend/app/core/orchestration/agent_coordinator.py Implements AgentCoordinator for async agent execution and response dispatch.
backend/app/core/orchestration/queue_manager.py Adds AsyncQueueManager for prioritized message handling and worker management.
backend/bots/discord/discord_bot.py New Discord bot class with thread management, agent integration, and command handling.
backend/bots/discord_bot/discordBot.py Removes legacy Discord bot implementation and event bus integration.
backend/main.py Replaces FastAPI app with async application class orchestrating queue, coordinator, and Discord bot; adds signal handling and lifecycle management.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DiscordBot
    participant QueueManager
    participant AgentCoordinator
    participant DevRelAgent

    User->>DiscordBot: Sends message in Discord
    DiscordBot->>QueueManager: Enqueue message (with classification)
    QueueManager->>AgentCoordinator: Dispatch devrel_request
    AgentCoordinator->>DevRelAgent: Run agent with initial state
    DevRelAgent->>DevRelAgent: Process workflow (intent, context, handlers)
    DevRelAgent->>AgentCoordinator: Return response
    AgentCoordinator->>QueueManager: Enqueue response for Discord
    QueueManager->>DiscordBot: Deliver agent response
    DiscordBot->>User: Post response in Discord thread
Loading

Poem

In burrows deep, the code did grow,
With queues and bots in tidy row.
Agents now chat, classify, and search,
Discord threads bloom on every perch.
Old ways retired, new flows begin—
The DevRel rabbit grins within!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59ac2f3 and 2354f5d.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (25)
  • backend/.env.example (1 hunks)
  • backend/app/agents/__init__.py (1 hunks)
  • backend/app/agents/devrel/agent.py (1 hunks)
  • backend/app/agents/devrel/nodes/classify_intent_node.py (1 hunks)
  • backend/app/agents/devrel/nodes/gather_context_node.py (1 hunks)
  • backend/app/agents/devrel/nodes/generate_response_node.py (1 hunks)
  • backend/app/agents/devrel/nodes/handle_faq_node.py (1 hunks)
  • backend/app/agents/devrel/nodes/handle_onboarding_node.py (1 hunks)
  • backend/app/agents/devrel/nodes/handle_technical_support_node.py (1 hunks)
  • backend/app/agents/devrel/nodes/handle_web_search_node.py (1 hunks)
  • backend/app/agents/devrel/prompts/base_prompt.py (1 hunks)
  • backend/app/agents/devrel/prompts/search_prompt.py (1 hunks)
  • backend/app/agents/devrel/state.py (1 hunks)
  • backend/app/agents/devrel/tools/faq_tool.py (1 hunks)
  • backend/app/agents/devrel/tools/search_tool.py (1 hunks)
  • backend/app/agents/shared/base_agent.py (1 hunks)
  • backend/app/agents/shared/classification_router.py (1 hunks)
  • backend/app/agents/shared/state.py (1 hunks)
  • backend/app/core/config.py (1 hunks)
  • backend/app/core/orchestration/agent_coordinator.py (1 hunks)
  • backend/app/core/orchestration/queue_manager.py (1 hunks)
  • backend/bots/discord/discord_bot.py (1 hunks)
  • backend/bots/discord_bot/discordBot.py (0 hunks)
  • backend/main.py (1 hunks)
  • pyproject.toml (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hello @smokeyScraper, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

As Gemini, I've reviewed this pull request titled "[feat]: langsmith tracing integration". The primary intent of this PR is to integrate Langsmith tracing into the application's backend, providing better observability into the execution of the AI agents and their components. This integration is part of a larger effort to refactor the backend towards a more robust, agent-based, and queue-driven architecture.

The changes introduce a new structure for defining agents using LangGraph, implement a core DevRel agent with various nodes and tools (like FAQ and web search via Tavily), and establish an asynchronous queue manager and agent coordinator for handling incoming messages and orchestrating agent execution. The Discord bot has been updated to classify messages and enqueue them for processing by this new system. Configuration for Langsmith, Gemini, and Tavily APIs has been added, and dependencies have been updated accordingly.

Highlights

  • Langsmith Tracing Integration: Adds Langsmith dependency, configuration options in .env.example and app/core/config.py, and applies @traceable decorators across various agent nodes, tools, and orchestration components to enable detailed tracing of agent runs.
  • New Agent Architecture (LangGraph): Introduces a new agents directory structure with shared and devrel subdirectories. Defines a BaseAgent class and an AgentState Pydantic model. Implements the DevRelAgent using LangGraph, defining a workflow with distinct nodes for intent classification, context gathering, handling specific request types (FAQ, web search, onboarding, technical support), and generating responses.
  • Asynchronous Queue and Orchestration: Adds AsyncQueueManager and AgentCoordinator classes in app/core/orchestration. This establishes a queue-based system for handling incoming messages asynchronously and coordinating their processing by the appropriate agents based on classification and priority.
  • Discord Bot Integration: Updates the DiscordBot to use the new ClassificationRouter to classify incoming messages and enqueue them via the AsyncQueueManager for processing by the agent coordinator. It also registers a handler to receive and send responses back to Discord threads.
  • New Tools and Prompts: Adds TavilySearchTool for web search and a basic FAQTool. Includes new prompt templates (GENERAL_LLM_RESPONSE_PROMPT, EXTRACT_SEARCH_QUERY_PROMPT) used by the DevRel agent nodes.
  • Dependency and Configuration Updates: Adds necessary libraries like langsmith, langgraph, langchain-tavily, tavily-python, langchain[google-genai], and pydantic-settings to pyproject.toml. Removes langchain-groq and groq. Updates .env.example and app/core/config.py to include API keys and settings for the new services.
  • Application Entry Point Change: Refactors main.py to replace the direct FastAPI/uvicorn run with a new DevRAIApplication class that manages the lifecycle of the queue manager, agent coordinator, and Discord bot using asyncio.run.

Changelog

Click here to see the changelog
  • backend/.env.example
    • Added example environment variables for Langsmith tracing (LANGSMITH_TRACING, LANGSMITH_ENDPOINT, LANGSMITH_API_KEY, LANGSMITH_PROJECT).
    • Added example variables for GEMINI_API_KEY and TAVILY_API_KEY.
    • Commented out some previous variables.
  • backend/app/agents/init.py
    • Added imports for new base agent components and the DevRel agent.
    • Updated __all__ list.
  • backend/app/agents/devrel/agent.py
    • New file: Defines the DevRelAgent class using LangGraph.
    • Implements the agent's workflow graph with various nodes.
    • Integrates ChatGoogleGenerativeAI, TavilySearchTool, and FAQTool.
    • Adds @traceable decorator to the run method and _route_to_handler.
  • backend/app/agents/devrel/nodes/classify_intent_node.py
    • New file: Defines the classify_intent_node function.
    • Uses ClassificationRouter to determine message intent.
    • Adds @traceable decorator.
  • backend/app/agents/devrel/nodes/gather_context_node.py
    • New file: Defines the gather_context_node function.
    • Adds @traceable decorator.
  • backend/app/agents/devrel/nodes/generate_response_node.py
    • New file: Defines the generate_response_node function and helpers.
    • Generates final responses based on task results (FAQ, web search, etc.).
    • Adds @traceable decorators to all functions.
  • backend/app/agents/devrel/nodes/handle_faq_node.py
    • New file: Defines the handle_faq_node function.
    • Uses the faq_tool to get responses.
    • Adds @traceable decorator.
  • backend/app/agents/devrel/nodes/handle_onboarding_node.py
    • New file: Defines the handle_onboarding_node function.
    • Adds @traceable decorator.
  • backend/app/agents/devrel/nodes/handle_technical_support_node.py
    • New file: Defines the handle_technical_support_node function.
    • Adds @traceable decorator.
  • backend/app/agents/devrel/nodes/handle_web_search_node.py
    • New file: Defines the handle_web_search_node function and helper.
    • Uses the search_tool (Tavily) after extracting a query.
    • Adds @traceable decorators to both functions.
  • backend/app/agents/devrel/prompts/base_prompt.py
    • New file: Defines the GENERAL_LLM_RESPONSE_PROMPT string.
  • backend/app/agents/devrel/prompts/search_prompt.py
    • New file: Defines the EXTRACT_SEARCH_QUERY_PROMPT string.
  • backend/app/agents/devrel/state.py
    • New file: Placeholder comment.
  • backend/app/agents/devrel/tools/faq_tool.py
    • New file: Defines the FAQTool class with hardcoded responses.
    • Includes basic fuzzy matching.
    • Adds @traceable decorators to methods.
  • backend/app/agents/devrel/tools/search_tool.py
    • New file: Defines the TavilySearchTool class.
    • Integrates with the Tavily API for web search.
    • Adds @traceable decorator to the search method.
  • backend/app/agents/shared/base_agent.py
    • New file: Defines the abstract BaseAgent class.
  • backend/app/agents/shared/classification_router.py
    • New file: Defines MessageCategory, DevRelNeed, and ClassificationRouter.
    • Implements message classification using LLM and pattern matching.
    • Adds @traceable decorators to classification methods.
  • backend/app/agents/shared/state.py
    • New file: Defines the AgentState Pydantic model for agent state management.
  • backend/app/core/config.py
    • New file: Defines the Settings class using pydantic-settings.
    • Adds configuration fields for Gemini, Tavily, and Langsmith.
    • Removes Groq-related configuration.
  • backend/app/core/orchestration/agent_coordinator.py
    • New file: Defines the AgentCoordinator class.
    • Manages agent instances and routes messages from the queue.
    • Handles sending responses back to platforms.
    • Adds @traceable decorators to handling methods.
  • backend/app/core/orchestration/queue_manager.py
    • New file: Defines the AsyncQueueManager class.
    • Implements an asynchronous priority queue for messages.
    • Manages message handlers and worker tasks.
  • backend/bots/discord/discord_bot.py
    • New file: Defines the DiscordBot class.
    • Uses the ClassificationRouter and AsyncQueueManager.
    • Handles incoming messages, creates threads, and enqueues messages for agents.
    • Handles responses from agents and sends them to Discord.
    • Adds !reset and !help_devrel commands.
  • backend/main.py
    • Replaced the previous FastAPI/uvicorn setup with a new DevRAIApplication class.
    • Initializes and starts the AsyncQueueManager, AgentCoordinator, and DiscordBot.
    • Configures logging and signal handling for graceful shutdown.
    • Adds checks for required environment variables.
    • The main entry point now uses asyncio.run to start the application.
  • pyproject.toml
    • Removed langchain-groq and groq dependencies.
    • Added langgraph, langchain-tavily, tavily-python, langchain[google-genai], pydantic-settings, and langsmith dependencies.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@smokeyScraper

Copy link
Copy Markdown
Contributor Author

Closing this PR, added way too much granular tracing leading to duplicated results.

Screenshots

Screenshot 2025-06-07 192451

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive Langsmith tracing integration and a new DevRel agent powered by LangGraph, complete with a Discord bot interface. The architecture is well-thought-out, featuring an asynchronous queue manager, Pydantic-based configuration, and modular agent components. The code quality is high, with good use of async programming, type hints, and error handling. The Langsmith integration via @traceable decorators is correctly implemented.

Summary of Findings

  • Agent Routing Logic: A critical issue was found in DevRelAgent where the keys for conditional routing in add_conditional_edges do not match the string values returned by the _route_to_handler function. This needs to be corrected for the agent to route intents properly.
  • LLM JSON Parsing: The JSON parsing in ClassificationRouter._parse_llm_response relies on string searching for '{' and '}'. Using Langchain's dedicated output parsers could make this more robust.
  • Discord Thread Creation Fallback: In DiscordBot._get_or_create_thread, if thread creation fails, it falls back to using the original channel ID as the thread ID. This could lead to responses appearing in the main channel unexpectedly.
  • f-string in Fallback Classification: In backend/app/agents/shared/classification_router.py line 190, the reasoning string in _fallback_classification appears to intend to use an f-string for original_message[:50], but it's currently a literal string. It should be f"Fallback classification for message: {original_message[:50]}...". I did not comment on this inline due to the review settings.

Merge Readiness

This pull request introduces valuable Langsmith tracing and a powerful DevRel agent. However, there is a critical issue in the agent's routing logic that must be addressed before merging. Additionally, a couple of medium-severity issues related to JSON parsing and Discord thread handling should be considered for improvement.

I recommend that the critical issue be fixed, and the medium-severity issues be reviewed by the author. As a reviewer, I am not authorized to approve pull requests; please ensure further review and approval from authorized team members after addressing the feedback.

Comment on lines +52 to +65
workflow.add_conditional_edges(
"gather_context",
self._route_to_handler,
{
MessageCategory.FAQ: "handle_faq",
MessageCategory.WEB_SEARCH: "handle_web_search",
MessageCategory.ONBOARDING: "handle_onboarding",
MessageCategory.TECHNICAL_SUPPORT: "handle_technical_support",
MessageCategory.COMMUNITY_ENGAGEMENT: "handle_technical_support",
MessageCategory.DOCUMENTATION: "handle_technical_support",
MessageCategory.BUG_REPORT: "handle_technical_support",
MessageCategory.FEATURE_REQUEST: "handle_technical_support",
"default": "handle_technical_support"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

There appears to be a mismatch in how conditional edges are defined. The _route_to_handler method (lines 84-101) returns string keys (e.g., "faq", "web_search") based on the intent. However, the dictionary provided to add_conditional_edges (lines 55-65) uses MessageCategory enum objects (e.g., MessageCategory.FAQ) as keys for most routes, instead of the strings returned by _route_to_handler.

According to LangGraph documentation, the keys in the mapping dictionary for add_conditional_edges must be the string outputs from the conditional function (_route_to_handler in this case).

This mismatch will likely cause the routing to not work as expected for enum-keyed routes, potentially always falling back to a default or failing if the returned string key isn't found.

Could you update the keys in the add_conditional_edges dictionary to be the string values that _route_to_handler returns (e.g., use "faq" instead of MessageCategory.FAQ)? The "default" key should also match the default string returned by _route_to_handler (which is "technical_support").

        workflow.add_conditional_edges(
            "gather_context",
            self._route_to_handler,
            {
                "faq": "handle_faq",
                "web_search": "handle_web_search",
                "onboarding": "handle_onboarding",
                "technical_support": "handle_technical_support", # This will catch explicit technical_support and defaults
                # Ensure _route_to_handler returns these exact strings for the respective categories
                # For categories that map to the same handler, ensure _route_to_handler returns "technical_support"
                # e.g., COMMUNITY_ENGAGEMENT, DOCUMENTATION, BUG_REPORT, FEATURE_REQUEST should result in "technical_support" from _route_to_handler
            }
        )

Style Guide References

Comment on lines +167 to +175
# Extract JSON from response
json_start = response.find('{')
json_end = response.rfind('}') + 1

if json_start != -1 and json_end != -1:
json_str = response[json_start:json_end]
parsed = json.loads(json_str)
return parsed
raise ValueError("No JSON found in response")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current method for parsing JSON from the LLM response by finding { and } characters can be a bit fragile if the LLM output isn't perfectly clean (e.g., includes preamble/postamble text outside the JSON block despite instructions).

Have you considered using Langchain's built-in output parsers, like JsonOutputParser or PydanticOutputParser? They are generally more robust at extracting and validating JSON from LLM responses and can simplify this parsing logic significantly. This would also align well with the Pydantic models used elsewhere.

Style Guide References

Comment on lines +154 to +157
except Exception as e:
logger.error(f"Failed to create thread: {str(e)}")

return str(message.channel.id) # Fallback to original channel

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The fallback return str(message.channel.id) in _get_or_create_thread if thread creation fails (line 157) might lead to agent responses being sent to the main channel instead of a dedicated thread. This could be confusing for users if they expect interactions to be contained within threads.

Would it be more appropriate to perhaps notify the user in the original channel that thread creation failed and they should try again, or handle this error more explicitly rather than silently falling back to the channel ID as the thread_id? This would ensure that the agent's context and response delivery mechanism remain consistent with the threaded conversation model.

Style Guide References

@smokeyScraper
smokeyScraper deleted the langsmith_integration branch June 24, 2025 14:36
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