Service Architecture
Nectr’s service layer follows a domain-driven design where each service has a single responsibility:PR Review Service
File:app/services/pr_review_service.py
Orchestrates the complete PR review workflow from webhook to GitHub comment.
Class: PRReviewService
process_pr_review()
process_pr_review()
Main entry point for PR review processing.Flow:
- Extract PR metadata (number, title, author, files)
- Fetch diff + files from GitHub
- Parse issue references from PR body (
Fixes #123) - Find candidate issues (semantic matching)
- Check for open PR conflicts (same files)
- Create tool executor for agentic loop
- Run AI analysis (standard or parallel mode)
- Build review comment with sections:
- Summary
- Resolved issues
- Semantic issue matches
- Open PR conflicts
- Similar past work
- Post review to GitHub (with inline suggestions)
- Index PR in Neo4j
- Extract memories to Mem0
- Update event status
Class: ReviewToolExecutor
Implements the tool executor protocol for Claude’s agentic loop.execute()
Routes tool calls to their implementations:
read_file→ Fetch full source code from GitHubsearch_project_memory→ Query Mem0 for project patternssearch_developer_memory→ Query Mem0 for developer habitsget_file_history→ Neo4j file experts + related PRsget_issue_details→ Fetch GitHub issue metadatasearch_open_issues→ Keyword search in candidate issuesget_linked_issues→ MCP client for Linear/GitHubget_related_errors→ MCP client for Sentry
Tool: read_file
Tool: read_file
Tool: get_file_history
Tool: get_file_history
Helper Functions
_parse_issue_refs()
_parse_issue_refs()
Parses
Fixes #123, Closes #456, Resolves #789 from PR body + title._find_candidate_issues()
_find_candidate_issues()
Finds open GitHub issues that might be resolved by this PR (semantic matching).Algorithm:
- Fetch up to 50 open issues from GitHub
- Build keyword set from PR title + body + file paths
- Score each issue by keyword overlap
- Return top 8 candidates (overlap ≥ 2 words)
_build_line_map()
_build_line_map()
Parses diff
patch field to map line content to absolute line numbers.Why? Claude returns line_hint (exact line content) in suggestions. We need to resolve this to a line number for GitHub’s review API.AI Service
File:app/services/ai_service.py
Manages Claude AI interactions with agentic tool execution.
Class: AIServices
analyze_pull_request_agentic()
Agentic review mode (default).Claude receives:
- PR metadata (title, body, author)
- Diff (up to 15,000 chars)
- File list with additions/deletions
- 8 tools to fetch context on-demand
- Send initial prompt with diff
- Claude analyzes + calls tools
- Execute tools → return results
- Claude continues analysis
- Repeat until
stop_reason == "end_turn" - Parse output for verdict + inline suggestions
Tool Execution Loop
Tool Execution Loop
analyze_pull_request_parallel()
Parallel review mode (opt-in via
PARALLEL_REVIEW_AGENTS=true).Runs 3 specialized agents concurrently:- Security agent - Injection, auth flaws, secrets
- Performance agent - N+1 queries, memory leaks, O(n²)
- Style agent - Missing tests, unclear names, dead code
Specialized Agent Prompts
Specialized Agent Prompts
Synthesis Agent
Synthesis Agent
Output Parsing
_parse_output()
_parse_output()
Extracts structured data from Claude’s markdown response:
- Verdict - Regex match for
**APPROVE**,**REQUEST_CHANGES**, or**NEEDS_DISCUSSION** - Inline suggestions - JSON block in
<suggestions>...</suggestions>tags - Semantic issue matches - JSON block in
<semantic_issues>...</semantic_issues>tags
Context Service
File:app/services/context_service.py
Builds ReviewContext by combining Mem0 semantic memories and Neo4j structural context.
build_review_context()
- Mem0: Project patterns, decisions, rules
- Mem0: Developer-specific patterns, strengths
- Neo4j: File experts (developers who touched files most)
- Neo4j: Related past PRs (same files)
Serialized Context Format
Serialized Context Format
Graph Builder Service
File:app/services/graph_builder.py
Builds and queries the Neo4j knowledge graph.
build_repo_graph()
Called when a repo is connected (or on rescan).
- Fetch full recursive file tree from GitHub
- Create
:Repositorynode - Batch-create
:Filenodes (chunks of 200) - Create
[:CONTAINS]edges - Remove stale files (deleted since last scan)
index_pr()
Called after a PR review is posted.
- Create
:PullRequestnode - Create
:Developernode - Create
[:AUTHORED_BY]edge - Create
[:TOUCHES]edges for changed files - Create
[:CLOSES]edges for linked issues
get_file_experts()
Returns developers who most frequently touched the given files.
get_related_prs()
Returns past PRs that touched the same files (structural similarity).
Next Steps
Neo4j Graph
Deep dive into graph schema and queries
Database Schema
PostgreSQL tables and relationships
MCP Client
How Nectr pulls Linear, Sentry, Slack data