📖 About the Project

💡 Inspiration

I’m a software developer working on an agentic platform with 100+ developers, where code is pushed to the main branch continuously.

Merge conflicts are not an occasional issue for us — they are part of our daily workflow.

A typical day looked like this: I would spend hours building a feature or fixing a bug, raise a merge request, and while it’s under review, someone else would modify the same files. Now my MR has conflicts. I stop, pull the latest changes, understand someone else’s code, resolve conflicts, and push again.

And then… it happens again.

What frustrated me the most wasn’t just the time — it was the constant context switching. Instead of focusing on building features, I was repeatedly trying to merge intent between multiple developers.

I realized I was spending 4–6 hours every week just resolving merge conflicts.

That’s when the idea of MergeGuard started forming in my mind. And when I came across the GitLab AI Hackathon, it felt like the perfect opportunity to finally build it.


🚀 What MergeGuard Does

MergeGuard is an AI-powered merge conflict resolver built on the GitLab Duo Agent Platform.

You simply mention @ai-mergeguard-conflict-resolution-flow-gitlab-ai-hackathon on a merge request, and it autonomously:

  1. Detects conflicts by analyzing both branches, reading clean file versions, and understanding commit history
  2. Resolves them using a structured 5-category decision framework
  3. Validates the results independently (syntax, conflicts, pipeline status)
  4. Reports every decision with a detailed explanation and audit trail

It doesn’t just “fix conflicts” — it understands them.


🛠️ How I Built It

MergeGuard is designed as a 4-component intelligent flow, where each component has a clear responsibility:

1. Conflict Detector

  • Fetches merge request context
  • Compares branches using GitLab APIs
  • Identifies conflicting files
  • Reads both versions of code
  • Analyzes commit history and cross-file dependencies

2. Conflict Resolver

  • Classifies conflicts into 5 categories:
    • Additive
    • Superset
    • Modification
    • Structural
    • Ambiguous
  • Generates resolved code based on intent
  • Uses create_commit to apply all changes atomically

3. Validator

  • Checks for leftover conflict markers
  • Validates syntax
  • Verifies merge readiness
  • Runs tests and checks pipeline status

4. Reporter

  • Posts a structured resolution report as an MR note
  • Explains every decision taken
  • Creates GitLab issues for conflicts needing manual review

⚙️ Key Design Decisions

A few decisions made a huge difference in reliability:

  • Atomic commits over file edits → Using create_commit instead of edit_file reduced failures
  • Limiting tool access → If a tool isn’t needed, don’t expose it to the LLM
  • Structured outputs between components → Made the system predictable
  • Separation of concerns → Each component does one thing well

⚔️ Challenges We Faced

This project wasn’t smooth — it was a series of learnings.

Silent tool failures.
Initially, tool calls failed without any visible error. The flow would complete successfully but produce no output. It felt like debugging in the dark. Adding on_tool_execution_failed changed everything — suddenly we had visibility.


The missing project_id.
The standalone agent worked perfectly, but the flow kept failing silently. After hours of debugging, I discovered that flows don’t automatically receive project_id.
I had to explicitly pass it and inject it into prompts using {{project_id}}.

Until then, every tool call depending on project context was failing without clear errors. This was one of the hardest bugs to identify.


Over-engineering the initial approach.
At first, I planned to build a Knowledge Graph and external MCP server for deep code understanding. But due to limited documentation and setup complexity, this approach wasn’t feasible within hackathon constraints.

This turned out to be a blessing — GitLab’s native tools like gitlab_blob_search and gitlab_api_get already provided everything needed.


LLM unpredictability.
The same prompt sometimes led to different tool usage. Instead of relying only on instructions, I simplified the system:

👉 Remove unnecessary tools completely

This made behavior far more consistent.


Passing context between components.
Each component runs independently, so passing structured data reliably required careful prompt design. Free-form outputs didn’t work — strict templates did.


Balancing autonomy with safety.
I wanted MergeGuard to be fully autonomous — but not blindly confident.

The solution:

  • A 5-category classification system
  • Independent validation
  • Automatic issue creation for ambiguous conflicts

This ensures the system is both useful and trustworthy.


📚 What I Learned

  • Building with LLMs is less about control and more about designing constraints
  • Simpler systems are often more reliable than complex ones
  • GitLab Duo Agent Platform is powerful enough to build full workflows without external systems
  • Observability (like error hooks) is critical in agent-based systems
  • Removing choices is often better than adding instructions

🎯 Impact

MergeGuard aims to:

  • ⏱️ Save hours spent on repetitive conflict resolution
  • 🤖 Improve accuracy using context-aware decisions
  • 🔁 Reduce developer frustration and context switching
  • 🤝 Enable smoother collaboration in large teams

🔮 What’s Next

  • Automatic triggers when conflicts appear
  • Learning from past resolutions
  • add indexing of the codebase for more better conflicts
  • Predicting and preventing conflicts before they happen

MergeGuard started as a personal frustration —
but it has the potential to remove one of the most common pain points in software development.

Built With

  • gitlab-ci/cd
  • gitlab-duo-agent-platform
  • gitlab-duo-custom-agents
  • gitlab-duo-custom-flows
  • gitlab-rest-api
  • javascript
  • markdown
  • markdowngitlab-duo-agent-platform
  • node.js
  • yaml
Share this project:

Updates