I built an AI code reviewer with 6 parallel agents. Here’s the architecture, warts and all. A developer built LGTM (Looks Good To Meow), an AI code reviewer that uses six parallel agents for security, bugs, performance, readability, best practices, and documentation. The architecture includes a synthesizer that merges findings, resolves conflicts via precedence, and limits output to the top 10 findings to improve readability. The project highlights challenges with multi-agent coordination and user engagement. Six months ago I got fed up with my AI code review tool. Two problems. That combination broke my trust. So I cancelled my subscription and started building my own. Today I'm launching LGTM Looks Good To Meow . This isn't a launch post about features. It's about the architecture, because that's the interesting part. The obvious implementation looks like this: Give one LLM a giant system prompt telling it to review security, bugs, performance, readability, best practices and documentation all at once. I built exactly that first. It didn't work. The model spread its attention across every category equally. That meant: Beta users simply stopped reading after the first few comments. I tried making the prompt more aggressive. Prioritize security above everything else. That solved one problem and created another. Security became better. Everything else became dramatically worse. The fundamental issue remained. One prompt was trying to solve six different problems. Instead of making one model do everything, I split the review into six independent reviewers. | Agent | Responsibility | |---|---| | πŸ”’ Security | Auth, injection, secrets, XSS, unsafe deserialization | | 🐞 Bugs | Correctness, null handling, race conditions | | ⚑ Performance | N+1 queries, quadratic loops, allocations | | πŸ“– Readability | Naming, function size, cognitive complexity | | βœ… Best Practices | Language idioms and architectural patterns | | πŸ“ Documentation | JSDoc, docstrings, README updates | Each receives: Every agent returns structured JSON. { "agent": "security", "findings": { "severity": "high", "file": "src/api/user.ts", "line": 47, "title": "Missing authorization check", "description": "DELETE endpoint allows any authenticated user to delete accounts.", "suggested fix": "Verify ownership or admin role before deletion." } } Six reports come back simultaneously. That is where the interesting part begins. Simply concatenating six reports produces garbage. Real pull requests can easily end up with 40–60 findings. Nobody reads that. The synthesizer converts six raw reports into one review. It performs four jobs. Security and bug reviewers frequently report the same issue. Example: Instead of showing duplicates, the synthesizer groups findings by: and keeps the strongest explanation. Sometimes two reviewers disagree. For example: Security says: Add rate limiting. Performance says: Remove rate limiting to improve latency. They're both technically correct. So I built a simple precedence system. Security Correctness Performance Style When conflicts occur, the final report still includes both viewpoints so the developer can override the decision. Ordering matters more than people realize. Nobody wants this: Instead, findings are sorted by: Severity β†’ Category Weight β†’ File β†’ Line Critical issues always appear first. Finally the synthesizer emits one overall review. Possible outputs: based entirely on blocker findings. One surprising lesson from beta testing: People don't read long reviews. The dashboard originally showed everything. Average review length: 27 findings Almost nobody reached the bottom. Today LGTM only surfaces the top 10 findings plus a summary. Everything else stays available inside the dashboard. Ten wasn't chosen mathematically. It was chosen because users actually read ten. Early versions had weird behavior. The longest report usually won. Not because it found better issues. Because the model subconsciously treated verbose output as more important. I fixed that by normalizing token counts before synthesis. Then another issue appeared. The synthesizer became too aggressive. Different findings got merged together. That caused genuine bugs to disappear. The fix was introducing a confidence score for every finding so uncertain matches remained separate. Most of the work wasn't building reviewers. It was teaching them how to disagree. The CI/CD scanner doesn't use AI. It shouldn't. It consists of 16 deterministic detectors. Example: on: pull request target: jobs: test: steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull request.head.sha }} That's a classic pull request target vulnerability. Static analysis detects it instantly. I benchmarked several popular LLMs. Two missed it completely. One detected it but couldn't explain why it was dangerous. Pattern matching wins here. Another example: env: API KEY: "sk live xxxxxxxxx" Detected immediately. No reasoning required. Another: uses: some-org/action@main Unpinned GitHub Actions. Again, deterministic. Not AI. The scanner currently includes detectors for: pull request target ...and several more. Sometimes boring software beats AI. Another decision I made early: LGTM never owns your API usage. You connect your own: Every review runs against your account. Not mine. That means: Most AI products bundle token costs into subscriptions. Eventually someone pays for that. Usually the customer. I preferred making pricing explicit. The downside is obvious. Users now have two bills. For solo developers that's usually cheaper. For larger organizations wanting one invoice, it's friction. I'm considering managed API keys in the future. Not today. | Plan | Price | |---|---| | Free | β‚Ή0/month | | Hobby | β‚Ή399/month | | Pro | β‚Ή999/month | | Enterprise | Custom | Top-ups are available separately for additional reviews and CI scans. Payments are handled through Dodo Payments . CLI: npm install -g @tarin/lgtm-cli I'm the only person building this. The part I'm watching most closely isn't whether the AI finds bugs. It's whether the synthesizer makes the same prioritization decisions that experienced engineers would. If it disagrees with your judgment, I want to know why. That's the failure mode I'm most interested in fixing. 🌐 Website https://looksgoodtomeow.in https://looksgoodtomeow.in πŸš€ Dashboard https://app.looksgoodtomeow.in https://app.looksgoodtomeow.in πŸ“š Documentation https://docs.looksgoodtomeow.in https://docs.looksgoodtomeow.in πŸ† Product Hunt https://www.producthunt.com/products/lgtm-looks-good-to-meow?utm source=other&utm medium=social https://www.producthunt.com/products/lgtm-looks-good-to-meow?utm source=other&utm medium=social πŸ› Feedback & Issues https://github.com/tarinagarwal/lgtm-feedback https://github.com/tarinagarwal/lgtm-feedback Thanks for reading. If you're building AI developer tools, I'd genuinely love to hear how you're approaching review quality, ranking, or synthesis. I think that's where the next generation of AI coding tools will differentiate themselves.