Hawkeye: AI-Powered Legal Conflict Detection
Inspiration
Legal firms face a critical challenge: conflict of interest checks. When a new client walks through the door with an engagement, the firm must verify that representing this client won't create a conflict with:
- Existing clients
- Past adversarial relationships
- Related entities and subsidiaries
- Prior representations
Currently, this process is manual, time-consuming, and error-prone. Partners search through databases, cross-reference spreadsheets, and make judgment calls—often taking 30+ minutes per engagement review. Miss a conflict, and the firm faces ethical violations, malpractice liability, and disciplinary action.
We saw this as a perfect opportunity to apply multi-agent AI to solve a high-stakes legal problem. Hawkeye was born.
What It Does
Hawkeye is an AI-powered multi-agent system that analyzes legal conflicts in real-time. Users input two parties (client + opposing party), and the system:
- Normalizes party names — handles legal suffixes, aliases, and variations
- Searches the firm database — finds historical matters and relationships
- Performs fuzzy matching — catches near-matches (typos, abbreviations)
- Detects conflicts — identifies 5 types of conflicts automatically
- Calculates risk quantitatively — scores 0-1 with confidence intervals
- Generates recommendations — ACCEPT, ACCEPT WITH BARRIER, REVIEW, or DECLINE
Key Innovation: Real-time Server-Sent Events (SSE) streaming shows users the analysis happening step-by-step. Instead of a blank screen for 30 seconds, they see:
- 💭 Normalizing party names...
- 📚 Loading firm database (12 clients, 20 matters)
- 🔍 Found 3 matches
- ⚖️ Calculating risk...
- 💰 Financial impact: $130K+ engagement cost
Real Demo Outputs
Scenario 1: Direct Conflict
Input: Zenith Technology Corp vs Zenith Technology Corp
Output: 🔴 HIGH RISK (0.95)
Reason: DIRECT_CLIENT — cannot represent same company against itself
Recommendation: ❌ DECLINE
Scenario 2: Prior Representation
Input: University of South Florida vs Zenith Technology Corp
Output: 🟡 MEDIUM RISK (0.68)
Reason: ADVERSE_MATTER — we sued Zenith on behalf of USF in 2021
Sources: IP Dispute (2021, won, $125K burn rate)
Financial Impact: Estimate $130K for similar engagement
Recommendation: ⚠️ REVIEW — need ethics committee assessment
Win Rate: 50% historical (3 wins, 1 loss from related matters)
Scenario 3: Low Risk
Input: Tech Solutions Inc vs Advanced Computing Group
Output: 🟢 LOW RISK (0.15)
Reason: No conflicts detected; minor match uncertainty
Recommendation: ✅ ACCEPT — proceed with engagement
How It's Built
Architecture: 6-Agent Pipeline
User Input
↓
[Normalization Agent] → Standardizes party names (LLM thinking + code)
↓
[Database Agent] → Loads 12 clients, 20 historical matters
↓
[Matching Agent] → Fuzzy-matches against database (2-gram, 75% threshold)
↓
[Conflict Analysis Agent] → Detects DIRECT_CLIENT, ADVERSE_MATTER, SUBSIDIARY_CONFLICT, etc. (LLM analysis)
↓
[Risk Scoring Agent] → Weighted algorithm + LLM implications
↓
[Ethics & Compliance Agent] → Final recommendation + explanation
↓
Output: Risk Level + Sources + Financial Impact + Recommendation
Tech Stack
Frontend:
- Framework: Next.js 14 (TypeScript, React)
- UI: shadcn/ui components (Button, Card, Alert, Badge)
- Styling: Tailwind CSS v4 with custom color tokens
- Real-time: Server-Sent Events (SSE) for streaming analysis
Backend:
- Route Handler:
/api/analyze-stream(Next.js Route Handler) - Response Format: SSE with
\n\ndelimited JSON - Database: Supabase (PostgreSQL)
- Data Cache:
/public/data/firm_database.json(sample data)
AI/LLM:
- Provider: Ollama (self-hosted or cloud)
- Model: kimi-k2.5:cloud (advanced reasoning)
- Integration: OpenAI-compatible API
- Purpose: Agent thinking, conflict analysis, risk assessment, explanation generation
Libraries:
string-similarity— fuzzy matching algorithm@clerk/nextjs— authentication@supabase/supabase-js— database clientlucide-react— iconsreact-hot-toast— notifications
Data Model
Firm Database (firm_database.json):
- 12 clients — Universities, tech firms, healthcare, consulting, financial services
- 20+ historical matters — Each with client, opposing party, date, outcome, burn rate
- Relationships graph — Tracks subsidiary relationships and entity connections
Example Matter:
{
"id": 101,
"client_name": "University of South Florida",
"opposing_party": "Zenith Technology Corp",
"matter_type": "IP Dispute",
"outcome": "won",
"burn_rate": 125000,
"date_ended": "2022-06-15",
"years_ago": 4
}
Streaming Pipeline
Every agent action is streamed via SSE in real-time:
const sendAction = (agent: string, type: string, message: string) => {
const action = {
id: `action-${++actionId}`,
agent,
type,
message,
timestamp: Date.now(),
};
controller.enqueue(encoder.encode(`data: ${JSON.stringify(action)}\n\n`));
};
// Usage:
sendAction("Normalization Agent", "thinking", "Normalizing...");
const normalized = normalizePartyNameFast(name);
sendAction("Normalization Agent", "result", `✓ ${name} → ${normalized}`);
Frontend listens with ReadableStream, parses SSE, updates React state incrementally:
const reader = response.body.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
const messages = text.split('\n\n').filter(m => m.startsWith('data: '));
messages.forEach(msg => {
const action = JSON.parse(msg.replace('data: ', ''));
setActions(prev => [...prev, action]);
});
}
Challenges We Faced
1. LLM Response Time
Problem: Initial tests with Ollama showed 10+ second delays on agent calls. "Starting analysis" hung for too long, degrading UX.
Solution:
- Created synchronous
normalizePartyNameFast()fallback that doesn't require LLM - Used LLM only for complex reasoning (analysis, explanation)
- Implemented request timeout with fallback messaging
- Result: Sub-30 second end-to-end analysis (from 45+ seconds)
2. SSE Controller Errors ("Controller is already closed")
Problem: Early streaming implementation had complex buffering logic that tried to split SSE frames manually, sometimes closing the controller mid-stream.
Solution:
- Simplified to send each action immediately (
controller.enqueue()) - No buffering or manual frame splitting
- Proper error handling with try-catch around enqueue
- Fixed duplicate/malformed route handler code
- Result: Stable streaming with zero controller errors
3. Demo Data Returning Zero Risk
Problem: Initial demo scenarios used fictional companies (Apple, Samsung, Tesla). They never matched the database, returning 0% risk universally.
Solution:
- Swapped demo data to use real database companies (Zenith, USF, UF)
- Created realistic scenarios from actual firm relationships
- Result: All 3 demo scenarios now return meaningful risk scores
4. Fuzzy Matching False Negatives
Problem: "zoom technologies" didn't match "Zenith Technology Corp" (too different for exact match).
Solution:
- Implemented 2-gram Jaccard similarity algorithm
- Set 75% threshold (catches typos without false positives)
- Result: Reliable matching across name variations
5. Financial Impact Display
Problem: Simple ACCEPT/DECLINE recommendations didn't give partners the context to make decisions.
Solution:
- Added sources listing (specific related matters from database)
- Added financial metrics:
- Historical burn rate per matter
- Total historical spend
- Win rate (% of matters won)
- Estimated cost for this engagement
- Added nuanced recommendations (ACCEPT WITH BARRIER, REVIEW)
- Result: Partners have full picture for decision-making
Accomplishments
✅ 6-Agent Multi-Stage Pipeline — Each agent has a single responsibility; output feeds into next agent
✅ Real-Time Streaming UI — SSE with live thinking panel shows analysis in progress (not blank screen for 30s)
✅ Comprehensive Recommendations — Not just YES/NO, but ACCEPT/ACCEPT WITH BARRIER/REVIEW/DECLINE with reasoning
✅ Financial Context — Burn rate, win rate, estimated costs tied to historical matters
✅ Source Attribution — Every recommendation cites specific matters from the database
✅ LLM Integration — Ollama with kimi-2.5:cloud model for sophisticated reasoning at each step
✅ Production-Ready UI — Dashboard with live thinking panel, tool alerts, action log, risk badges
✅ Fallback Graceful Degradation — Even if LLM is down, system still analyzes with deterministic code
✅ End-to-End Demo — 3 realistic scenarios from real firm database
What We Learned
Multi-Agent Systems > Single LLM Call
- Breaking down the problem into 6 sequential agents allowed each to specialize
- Easier to debug ("which agent has the bug?") than one monolithic LLM call
- Each agent can have its own LLM tuning, error handling, and retry logic
Streaming Changes UX Perception
- 30 seconds with real-time updates feels 5× faster than 30 seconds with a spinner
- Users trust systems more when they see the "thinking" process
- SSE is simple but powerful for modern web UX
Hybrid LLM + Code is optimal
- Pure code (fuzzy matching) is fast and deterministic; perfect for matching
- Pure LLM (reasoning) is flexible but slow
- Hybrid (code for deterministic tasks, LLM for reasoning) wins on speed and quality
Database > Configuration
- Hard-coded scenarios felt brittle; switching to real database data made the demo compelling
- Using actual firm relationships instantly increased believability
Explainability Matters for Legal
- Legal professionals are risk-averse and won't trust a black box "DECLINE"
- Showing sources (which matters), reasoning (why), and financial impact (cost/benefit) makes recommendations actionable
- Legal tech requires transparency more than consumer tech
Future Plans
Short Term (1-2 weeks)
- Deploy to production on Vercel
- Replace demo database with real firm data via Supabase
- Add analysis export to PDF
- Create ethics committee review workflow
Medium Term (1-3 months)
- Database Integration Plugins — Connect to LexisNexis, Westlaw, practice management systems
- ML Risk Weighting — Learn from historical resolution outcomes; let ML adjust conflict weights
- Time Decay Weighting — Older matters should count less in risk calculation
- Jurisdiction Customization — Different conflict rules per state (Florida vs NY vs CA)
- Bulk Analysis — Upload CSV of potential engagements; batch analyze all
Long Term (3-6 months)
- CLI Tool —
hawkeye analyze "Company A" "Company B"for terminal users - White-Label SaaS — License to other firms
- API for Third Parties — Embed conflict checking into other legal software
- Advanced Analytics — Dashboard showing conflict patterns over time
- Multi-Jurisdiction Support — Cross-border conflict detection
Getting Started
Local Development
# 1. Clone repo
git clone https://github.com/yourusername/hawkeye.git
cd hawkeye
# 2. Set up environment
cp .env.example .env.local
# Fill in keys for Clerk, Supabase, Ollama, Google API (optional)
# 3. Install dependencies
bun install
# 4. Start Ollama (for LLM)
ollama serve &
ollama pull kimi-2.5:cloud
# 5. Run dev server
bun dev
# 6. Open http://localhost:3000/dashboard
Try the Demo
- Tampa Bay Scenario: Select "Bloomin' Brands vs Raymond James" from dropdown
- Historical Matter: Try "University of South Florida vs Zenith Technology"
- Custom Query: Enter any two company names to test the analyzer
Technical Highlights
Conflict Detection Algorithm
const detectConflicts = (matchedNames, opposingParty, firmData) => {
const conflicts = [];
// DIRECT_CLIENT: both parties are existing clients
if (clientIsInDatabase && opposingIsInDatabase) {
conflicts.push({ type: "DIRECT_CLIENT", severity: "HIGH" });
}
// ADVERSE_MATTER: we represented one party against the other
const adverseMatters = findMattersWhere(
(matter) =>
(matter.client === clientName && matter.opposing === opposingName) ||
(matter.opposing === clientName && matter.client === opposingName)
);
if (adverseMatters.length > 0) {
conflicts.push({ type: "ADVERSE_MATTER", severity: "HIGH" });
}
// SUBSIDIARY_CONFLICT: one party owns the other
if (isSubsidiary(clientName, opposingName)) {
conflicts.push({ type: "SUBSIDIARY_CONFLICT", severity: "MEDIUM" });
}
return conflicts;
};
Risk Scoring Formula
Risk Score = Σ(conflict_severity_weights) / number_of_factors
× confidence_multiplier
Example:
- DIRECT_CLIENT: 0.95 (highest weight)
- 2+ database matches: +0.15 (stronger evidence)
- Recent matter (<1 year): +0.10 (recency)
- Total: (0.95 + 0.15 + 0.10) / 3 × 0.88 = 0.35
Risk Levels:
- 0.00-0.33: 🟢 LOW
- 0.33-0.67: 🟡 MEDIUM
- 0.67-1.00: 🔴 HIGH
Team
- Product & Design: Smart UI/UX decisions (streaming, live thinking panel)
- Backend Engineering: 6-agent orchestration, SSE streaming, LLM integration
- Frontend Engineering: React state management for real-time updates, responsive dashboard
- Research: Legal conflict detection rules, historical matter analysis
Links
- GitHub: https://github.com/yourusername/hawkeye
- Live Demo: https://hawkeye-legal.vercel.app (deployed)
- Documentation:
/Design.md— Design system & brand guidelines/Plan.md— Implementation roadmap (19/23 complete, 83%)/DEPLOYMENT.md— Deploy to Vercel, Docker, or VPS/SLIDES_PRESENTATION.md— 18-slide technical deep-dive for investors
- Database Schema:
/supabase/schema.sql - Sample Data:
/public/data/firm_database.json(12 clients, 20+ matters)
Conclusion
Hawkeye brings AI-powered intelligence to legal conflict detection—a process that has remained largely manual and error-prone for decades. By combining:
- Multi-agent reasoning (6 specialized agents)
- Real-time streaming (transparent UX)
- Financial context (burn rates, win rates, estimated costs)
- Source attribution (specific matters cited)
- Nuanced recommendations (ACCEPT/REVIEW/DECLINE instead of binary)
...we enable legal firms to make confident, defensible conflicts decisions in seconds, not hours—with full audit trail and explainability.
This is just the beginning. The legal tech market is ripe for AI-native tools built with modern tech stacks. Hawkeye proves that concept.
Technology Specs
| Component | Technology |
|---|---|
| Frontend Framework | Next.js 14 + React 18 + TypeScript |
| Styling | Tailwind CSS v4 + shadcn/ui |
| Backend | Next.js Route Handlers (no separate backend) |
| Real-Time | Server-Sent Events (SSE) |
| LLM | Ollama + kimi-2.5:cloud (OpenAI API compatible) |
| Database | Supabase (PostgreSQL) |
| Authentication | Clerk |
| Deployment | Vercel (frontend), Ollama (local/cloud LLM) |
| Matching Algorithm | 2-gram Jaccard similarity |
| Data Caching | JSON file + Supabase |
Performance Metrics
- Analysis Speed: 20-25 seconds end-to-end (including LLM calls)
- Streaming Latency: <100ms per agent action
- Concurrent Users: 1-5 (limited by Ollama GPU memory; scales with multiple instances)
- Database Size: 12 clients, 20+ matters; <1MB JSON
- Historical Accuracy: 100% on demo scenarios (all 3 return expected risk levels)
Thank You
Thanks to the hackathon organizers for the inspiring challenge. This was a creative collision between legal domain expertise, AI/LLM reasoning, and modern web architecture. We're excited to see where legal tech goes next.
🦅 Hawkeye: See conflicts before they happen.
Built With
- googleadk
- nextjs
- typescript
Log in or sign up for Devpost to join the conversation.