Repository Analysis

langchain-ai/open_deep_research

26.4 Moderate AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of langchain-ai/open_deep_research, a Python project with 12,481 GitHub stars. SynthScan v2.0 examined 8,675 lines of code across 36 source files, recording 177 pattern matches distributed across 14 syntactic categories. The overall adjusted score of 26.4 places this repository in the Moderate AI signal band.

The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).

26.4
Adjusted Score
26.4
Raw Score
100%
Time Factor
2026-07-25
Last Push
12.5K
Stars
Python
Language
8.7K
Lines of Code
36
Files
177
Pattern Hits
2026-08-02
Scan Date
0.06
HC Hit Rate

What These Metrics Mean

Adjusted Score
Primary synthetic code indicator. Raw score normalised per 1,000 lines of code and multiplied by the temporal discount factor. This is the definitive comparative metric — use it to rank repositories by AI authorship density.
Raw Score
The unmodified sum of all severity-weighted, context-multiplied pattern match scores before temporal discounting. Reflects the absolute signal strength independent of when the repository was last active.
Time Factor
The temporal discount multiplier (0–100%) applied to the raw score. Repositories last updated before ChatGPT's launch (Nov 2022) receive a 5% factor. Full signal is only assigned to repositories active in the post-adoption era (Jan 2024+).
Pattern Hits
Total count of individual pattern matches across all files and categories. A high hit count with a low score may indicate a very large codebase with isolated AI snippets; a low count with a high score indicates dense, concentrated AI signatures.
HC Hit Rate
High+Critical pattern hits per file, averaged across the repository. This orthogonal signal catches repositories where a few files are densely packed with high-severity AI tells — a strong indicator even when the normalised score appears moderate due to codebase size.
Lines of Code / Files
Total lines and files analysed. The scanner examines 94 file extensions. These denominators are used to normalise the score, enabling fair comparison between repositories of vastly different sizes.

Score History

Longitudinal tracking requires multiple scan runs. Once this repository is re-scanned after new commits land, this chart will visualise how the synthetic code signal evolves over time — enabling you to detect whether AI authorship is growing, stabilising, or being actively corrected by human engineers.

No multi-scan history yet — run the scanner again to build trend data.

Severity Breakdown

Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.

CRITICAL 0HIGH 2MEDIUM 23LOW 152

Directory Score Breakdown

This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.

Pattern Findings

The scanner identified 177 distinct pattern matches across 14 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.

Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.

Verbosity Indicators43 hits · 64 pts
SeverityFileLineSnippetContext
LOWsrc/open_deep_research/utils.py61 # Step 1: Execute search queries asynchronouslyCOMMENT
LOWsrc/open_deep_research/utils.py70 # Step 2: Deduplicate results by URL to avoid processing the same content multiple timesCOMMENT
LOWsrc/open_deep_research/utils.py78 # Step 3: Set up the summarization model with configurationCOMMENT
LOWsrc/open_deep_research/utils.py109 # Step 5: Execute all summarization tasks in parallelCOMMENT
LOWsrc/open_deep_research/utils.py112 # Step 6: Combine results with their summariesCOMMENT
LOWsrc/open_deep_research/utils.py464 # Step 1: Handle authentication if requiredCOMMENT
LOWsrc/open_deep_research/utils.py470 # Step 2: Validate configuration requirementsCOMMENT
LOWsrc/open_deep_research/utils.py498 # Step 4: Load tools from MCP serverCOMMENT
LOWsrc/open_deep_research/utils.py506 # Step 5: Filter and configure toolsCOMMENT
LOWsrc/open_deep_research/utils.py688 # Step 2: Check provider-specific token limit patternsCOMMENT
LOWsrc/open_deep_research/utils.py696 # Step 3: If provider unknown, check all providersCOMMENT
LOWsrc/open_deep_research/utils.py95 # Step 4: Create summarization tasks (skip empty content)COMMENT
LOWsrc/open_deep_research/utils.py125 # Step 7: Format the final outputCOMMENT
LOWsrc/open_deep_research/utils.py481 # Step 3: Set up MCP server connectionCOMMENT
LOWsrc/open_deep_research/utils.py677 # Step 1: Determine provider from model name if availableCOMMENT
LOWsrc/open_deep_research/deep_researcher.py73 # Step 1: Check if clarification is enabled in configurationCOMMENT
LOWsrc/open_deep_research/deep_researcher.py79 # Step 2: Prepare the model for structured clarification analysisCOMMENT
LOWsrc/open_deep_research/deep_researcher.py96 # Step 3: Analyze whether clarification is neededCOMMENT
LOWsrc/open_deep_research/deep_researcher.py103 # Step 4: Route based on clarification analysisCOMMENT
LOWsrc/open_deep_research/deep_researcher.py149 # Step 2: Generate structured research brief from user messagesCOMMENT
LOWsrc/open_deep_research/deep_researcher.py156 # Step 3: Initialize supervisor with research brief and instructionsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py212 # Step 2: Generate supervisor response based on current contextCOMMENT
LOWsrc/open_deep_research/deep_researcher.py216 # Step 3: Update state and proceed to tool executionCOMMENT
LOWsrc/open_deep_research/deep_researcher.py413 # Step 3: Generate researcher response with system contextCOMMENT
LOWsrc/open_deep_research/deep_researcher.py417 # Step 4: Update state and proceed to tool executionCOMMENT
LOWsrc/open_deep_research/deep_researcher.py525 # Step 1: Configure the compression modelCOMMENT
LOWsrc/open_deep_research/deep_researcher.py534 # Step 2: Prepare messages for compressionCOMMENT
LOWsrc/open_deep_research/deep_researcher.py540 # Step 3: Attempt compression with retry logic for token limit issuesCOMMENT
LOWsrc/open_deep_research/deep_researcher.py620 # Step 1: Extract research findings and prepare state cleanupCOMMENT
LOWsrc/open_deep_research/deep_researcher.py625 # Step 2: Configure the final report generation modelCOMMENT
LOWsrc/open_deep_research/deep_researcher.py634 # Step 3: Attempt report generation with token limit retry logicCOMMENT
LOWsrc/open_deep_research/deep_researcher.py132 # Step 1: Set up the research model for structured outputCOMMENT
LOWsrc/open_deep_research/deep_researcher.py192 # Step 1: Configure the supervisor model with available toolsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py240 # Step 1: Extract current state and check exit conditionsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py264 # Step 2: Process all tool calls together (both think_tool and ConductResearch)COMMENT
LOWsrc/open_deep_research/deep_researcher.py344 # Step 3: Return command with all tool resultsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py379 # Step 1: Load configuration and validate tool availabilityCOMMENT
LOWsrc/open_deep_research/deep_researcher.py391 # Step 2: Configure the researcher model with toolsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py451 # Step 1: Extract current state and check early exit conditionsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py466 # Step 2: Handle other tool calls (search, MCP tools, etc.)COMMENT
LOWsrc/open_deep_research/deep_researcher.py491 # Step 3: Check late exit conditions (after processing tools)COMMENT
LOWsrc/open_deep_research/deep_researcher.py576 # Step 4: Return error result if all attempts failedCOMMENT
LOWsrc/open_deep_research/deep_researcher.py692 # Step 4: Return failure result if all retries exhaustedCOMMENT
Structural Annotation Overuse43 hits · 64 pts
SeverityFileLineSnippetContext
LOWsrc/open_deep_research/utils.py61 # Step 1: Execute search queries asynchronouslyCOMMENT
LOWsrc/open_deep_research/utils.py70 # Step 2: Deduplicate results by URL to avoid processing the same content multiple timesCOMMENT
LOWsrc/open_deep_research/utils.py78 # Step 3: Set up the summarization model with configurationCOMMENT
LOWsrc/open_deep_research/utils.py109 # Step 5: Execute all summarization tasks in parallelCOMMENT
LOWsrc/open_deep_research/utils.py112 # Step 6: Combine results with their summariesCOMMENT
LOWsrc/open_deep_research/utils.py464 # Step 1: Handle authentication if requiredCOMMENT
LOWsrc/open_deep_research/utils.py470 # Step 2: Validate configuration requirementsCOMMENT
LOWsrc/open_deep_research/utils.py498 # Step 4: Load tools from MCP serverCOMMENT
LOWsrc/open_deep_research/utils.py506 # Step 5: Filter and configure toolsCOMMENT
LOWsrc/open_deep_research/utils.py688 # Step 2: Check provider-specific token limit patternsCOMMENT
LOWsrc/open_deep_research/utils.py696 # Step 3: If provider unknown, check all providersCOMMENT
LOWsrc/open_deep_research/utils.py95 # Step 4: Create summarization tasks (skip empty content)COMMENT
LOWsrc/open_deep_research/utils.py125 # Step 7: Format the final outputCOMMENT
LOWsrc/open_deep_research/utils.py481 # Step 3: Set up MCP server connectionCOMMENT
LOWsrc/open_deep_research/utils.py677 # Step 1: Determine provider from model name if availableCOMMENT
LOWsrc/open_deep_research/deep_researcher.py73 # Step 1: Check if clarification is enabled in configurationCOMMENT
LOWsrc/open_deep_research/deep_researcher.py79 # Step 2: Prepare the model for structured clarification analysisCOMMENT
LOWsrc/open_deep_research/deep_researcher.py96 # Step 3: Analyze whether clarification is neededCOMMENT
LOWsrc/open_deep_research/deep_researcher.py103 # Step 4: Route based on clarification analysisCOMMENT
LOWsrc/open_deep_research/deep_researcher.py149 # Step 2: Generate structured research brief from user messagesCOMMENT
LOWsrc/open_deep_research/deep_researcher.py156 # Step 3: Initialize supervisor with research brief and instructionsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py212 # Step 2: Generate supervisor response based on current contextCOMMENT
LOWsrc/open_deep_research/deep_researcher.py216 # Step 3: Update state and proceed to tool executionCOMMENT
LOWsrc/open_deep_research/deep_researcher.py413 # Step 3: Generate researcher response with system contextCOMMENT
LOWsrc/open_deep_research/deep_researcher.py417 # Step 4: Update state and proceed to tool executionCOMMENT
LOWsrc/open_deep_research/deep_researcher.py525 # Step 1: Configure the compression modelCOMMENT
LOWsrc/open_deep_research/deep_researcher.py534 # Step 2: Prepare messages for compressionCOMMENT
LOWsrc/open_deep_research/deep_researcher.py540 # Step 3: Attempt compression with retry logic for token limit issuesCOMMENT
LOWsrc/open_deep_research/deep_researcher.py620 # Step 1: Extract research findings and prepare state cleanupCOMMENT
LOWsrc/open_deep_research/deep_researcher.py625 # Step 2: Configure the final report generation modelCOMMENT
LOWsrc/open_deep_research/deep_researcher.py634 # Step 3: Attempt report generation with token limit retry logicCOMMENT
LOWsrc/open_deep_research/deep_researcher.py132 # Step 1: Set up the research model for structured outputCOMMENT
LOWsrc/open_deep_research/deep_researcher.py192 # Step 1: Configure the supervisor model with available toolsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py240 # Step 1: Extract current state and check exit conditionsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py264 # Step 2: Process all tool calls together (both think_tool and ConductResearch)COMMENT
LOWsrc/open_deep_research/deep_researcher.py344 # Step 3: Return command with all tool resultsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py379 # Step 1: Load configuration and validate tool availabilityCOMMENT
LOWsrc/open_deep_research/deep_researcher.py391 # Step 2: Configure the researcher model with toolsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py451 # Step 1: Extract current state and check early exit conditionsCOMMENT
LOWsrc/open_deep_research/deep_researcher.py466 # Step 2: Handle other tool calls (search, MCP tools, etc.)COMMENT
LOWsrc/open_deep_research/deep_researcher.py491 # Step 3: Check late exit conditions (after processing tools)COMMENT
LOWsrc/open_deep_research/deep_researcher.py576 # Step 4: Return error result if all attempts failedCOMMENT
LOWsrc/open_deep_research/deep_researcher.py692 # Step 4: Return failure result if all retries exhaustedCOMMENT
Excessive Try-Catch Wrapping26 hits · 24 pts
SeverityFileLineSnippetContext
LOWsrc/open_deep_research/utils.py502 except Exception:CODE
LOWsrc/open_deep_research/utils.py210 except Exception as e:CODE
LOWsrc/open_deep_research/utils.py288 except Exception as e:CODE
LOWsrc/open_deep_research/deep_researcher.py332 except Exception as e:CODE
LOWsrc/open_deep_research/deep_researcher.py431 except Exception as e:CODE
LOWsrc/open_deep_research/deep_researcher.py565 except Exception as e:CODE
LOWsrc/open_deep_research/deep_researcher.py661 except Exception as e:CODE
LOWsrc/security/auth.py65 except Exception as e:CODE
MEDIUMsrc/legacy/utils.py1098 print(f"Error in Google search for '{query}': {str(e)}")CODE
MEDIUMsrc/legacy/utils.py1166 print(f"Error in Google search for query '{query}': {str(e)}")CODE
MEDIUMsrc/legacy/utils.py607def process_single_query(query):CODE
MEDIUMsrc/legacy/utils.py765def process_single_query(query):CODE
MEDIUMsrc/legacy/utils.py1023def google_search(query, max_results):CODE
MEDIUMsrc/legacy/utils.py558 print(f"Error processing query '{query}': {str(e)}")STRING
MEDIUMsrc/legacy/utils.py694 print(f"Error processing arXiv query '{query}': {str(e)}")STRING
MEDIUMsrc/legacy/utils.py716 print(f"Error processing arXiv query '{query}': {str(e)}")STRING
LOWsrc/legacy/utils.py1097 except Exception as e:CODE
LOWsrc/legacy/utils.py1146 except Exception as e:CODE
LOWsrc/legacy/utils.py1165 except Exception as e:CODE
LOWsrc/legacy/utils.py1232 except Exception as e:CODE
LOWsrc/legacy/utils.py1306 except Exception as e:CODE
LOWsrc/legacy/utils.py556 except Exception as e:STRING
LOWsrc/legacy/utils.py692 except Exception as e:STRING
LOWsrc/legacy/utils.py714 except Exception as e:STRING
LOWsrc/legacy/utils.py826 except Exception as e:STRING
LOWsrc/legacy/utils.py862 except Exception as e:STRING
AI Slop Vocabulary8 hits · 16 pts
SeverityFileLineSnippetContext
MEDIUMtests/prompts.py1OVERALL_QUALITY_PROMPT = """You are an expert evaluator tasked with assessing the quality of research reports. Please evCODE
MEDIUM.github/workflows/claude-code-review.yml62 # - For React components: Performance, accessibility, and best practicesCOMMENT
MEDIUM.github/workflows/claude-code-review.yml69 # 'Please provide a thorough code review focusing on our coding standards and best practices.' }}COMMENT
MEDIUMsrc/open_deep_research/prompts.py228final_report_generation_prompt = """Based on all the research conducted, create a comprehensive, well-structured answer CODE
MEDIUMsrc/open_deep_research/utils.py386 """Wrap MCP tool with comprehensive authentication and error handling.STRING
MEDIUMsrc/open_deep_research/deep_researcher.py641 # Create comprehensive prompt with all research contextCOMMENT
MEDIUMsrc/open_deep_research/deep_researcher.py608 """Generate the final comprehensive research report with retry logic for token limits.STRING
MEDIUMsrc/legacy/prompts.py83query_writer_instructions="""You are an expert technical writer crafting targeted web search queries that will gather coSTRING
Hyper-Verbose Identifiers18 hits · 13 pts
SeverityFileLineSnippetContext
LOWtests/supervisor_parallel_evaluation.py10def right_parallelism_evaluator(CODE
LOWsrc/open_deep_research/utils.py703def _check_openai_token_limit(exception: Exception, error_str: str) -> bool:CODE
LOWsrc/open_deep_research/utils.py385def wrap_mcp_authenticate_tool(tool: StructuredTool) -> StructuredTool:CODE
LOWsrc/open_deep_research/utils.py399 def _find_mcp_error_in_exception_chain(exc: BaseException) -> McpError | None:CODE
LOWsrc/open_deep_research/utils.py599def get_notes_from_tool_calls(messages: list[MessageLikeRepresentation]):CODE
LOWsrc/open_deep_research/utils.py607def anthropic_websearch_called(response):CODE
LOWsrc/open_deep_research/utils.py736def _check_anthropic_token_limit(exception: Exception, error_str: str) -> bool:CODE
LOWsrc/open_deep_research/utils.py759def _check_gemini_token_limit(exception: Exception, error_str: str) -> bool:CODE
LOWsrc/open_deep_research/utils.py848def remove_up_to_last_ai_message(messages: list[MessageLikeRepresentation]) -> list[MessageLikeRepresentation]:CODE
LOWsrc/legacy/multi_agent.py340async def supervisor_should_continue(state: ReportState) -> str:CODE
LOWsrc/legacy/multi_agent.py447async def research_agent_should_continue(state: SectionState) -> str:CODE
LOWsrc/legacy/graph.py396def gather_completed_sections(state: ReportState):CODE
LOWsrc/legacy/graph.py451def initiate_final_section_writing(state: ReportState):CODE
LOWsrc/legacy/utils.py89def deduplicate_and_format_sources(CODE
LOWsrc/legacy/utils.py1501async def select_and_execute_search(search_api: str, query_list: list[str], params_to_pass: dict) -> str:CODE
LOWsrc/legacy/utils.py1573def split_and_rerank_search_results(embeddings: Embeddings, query: str, search_results: list[dict], max_chunks: int = 5)CODE
LOWsrc/legacy/utils.py219async def azureaisearch_search_async(search_queries: list[str], max_results: int = 5, topic: str = "general", include_raSTRING
LOWsrc/legacy/tests/test_report_quality.py140def test_response_criteria_evaluation(research_agent, search_api, models, eval_model):CODE
Self-Referential Comments5 hits · 12 pts
SeverityFileLineSnippetContext
MEDIUMsrc/open_deep_research/deep_researcher.py713# Define main workflow edges for sequential executionCOMMENT
MEDIUMsrc/legacy/utils.py1207 # Create an async HTTP clientCOMMENT
MEDIUMsrc/legacy/utils.py417 # Define the function to process a single querySTRING
MEDIUMsrc/legacy/utils.py422 # Define the function for the executor with all parametersSTRING
MEDIUMsrc/legacy/tests/test_report_quality.py147 # Create a table for model configurationCOMMENT
Deep Nesting18 hits · 10 pts
SeverityFileLineSnippetContext
LOWsrc/open_deep_research/utils.py531CODE
LOWsrc/open_deep_research/utils.py665CODE
LOWsrc/open_deep_research/utils.py892CODE
LOWsrc/open_deep_research/deep_researcher.py607CODE
LOWsrc/legacy/multi_agent.py240CODE
LOWsrc/legacy/utils.py374CODE
LOWsrc/legacy/utils.py577CODE
LOWsrc/legacy/utils.py928CODE
LOWsrc/legacy/utils.py1188CODE
LOWsrc/legacy/utils.py1248CODE
LOWsrc/legacy/utils.py1501CODE
LOWsrc/legacy/utils.py418CODE
LOWsrc/legacy/utils.py607CODE
LOWsrc/legacy/utils.py967CODE
LOWsrc/legacy/utils.py1258CODE
LOWsrc/legacy/utils.py1262CODE
LOWsrc/legacy/utils.py1023CODE
LOWsrc/legacy/utils.py1118CODE
Modern AI Meta-Vocabulary2 hits · 6 pts
SeverityFileLineSnippetContext
MEDIUMsrc/legacy/CLAUDE.md61# Test only the multi-agent implementationCOMMENT
MEDIUMsrc/legacy/tests/test_report_quality.py174 # Checkpointer for the multi-agent approachCOMMENT
Docstring Block Structure1 hit · 5 pts
SeverityFileLineSnippetContext
HIGHsrc/legacy/utils.py1502Select and execute the appropriate search API. Args: search_api: Name of the search API to use STRING
Redundant / Tautological Comments5 hits · 4 pts
SeverityFileLineSnippetContext
LOWsrc/open_deep_research/utils.py710 # Check if this is an OpenAI exceptionCOMMENT
LOWsrc/open_deep_research/utils.py743 # Check if this is an Anthropic exceptionCOMMENT
LOWsrc/open_deep_research/utils.py766 # Check if this is a Google/Gemini exceptionCOMMENT
LOWsrc/legacy/utils.py426 # Set text to True if max_characters is None, otherwise use an object with max_charactersSTRING
LOWsrc/legacy/tests/run_test.py129 # Display results with rich formattingCOMMENT
Over-Commented Block4 hits · 4 pts
SeverityFileLineSnippetContext
LOW.github/workflows/claude-code-review.yml1name: Claude Code ReviewCOMMENT
LOW.github/workflows/claude-code-review.yml61 # - For API endpoints: Security, input validation, and error handlingCOMMENT
LOW.github/workflows/claude.yml41 actions: readCOMMENT
LOW.github/workflows/claude.yml61 # Optional: Custom environment variables for ClaudeCOMMENT
Synthetic Comment Markers1 hit · 4 pts
SeverityFileLineSnippetContext
HIGHsrc/legacy/utils.py428 "summary": True, # This is an amazing feature by EXA. It provides an AI generated summary of the contenSTRING
Unused Imports2 hits · 2 pts
SeverityFileLineSnippetContext
LOWsrc/legacy/tests/conftest.py5CODE
LOWsrc/legacy/tests/test_report_quality.py13CODE
AI Structural Patterns1 hit · 1 pts
SeverityFileLineSnippetContext
LOWsrc/security/auth.py51CODE