How It Works
This page explains the technical architecture of OWL Watch.
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ OWL Watch │
├──────────────┬──────────────┬──────────────┬────────────────┤
│ Watcher │ Investigator │ Server │ Profile │
│ (log file) │ (LLM + tools)│ (dashboard) │ (project) │
├──────────────┴──────────────┴──────────────┴────────────────┤
│ Ollama (Local LLM) │
└─────────────────────────────────────────────────────────────┘
Components
Log Watcher
The watcher monitors your log file in real-time (similar to tail -f).
How it detects errors:
- Reads new lines from the log file
- Matches against error patterns:
- Log level patterns:
ERROR,WARN,FATAL - Content patterns:
exception,traceback,failed - Compiler patterns:
File.java:33: error:
- Log level patterns:
- Buffers for 2 seconds to capture complete stack traces
- Groups multi-line errors together
Error patterns recognized:
| Type | Example |
|---|---|
| Spring/Log4j | 2024-02-11 ERROR [main] ClassName: message |
| Python logging | ERROR:module:message |
| Bracketed | [ERROR] message |
| Generic | ERROR: message |
Investigator
The investigator uses a 2-phase approach with the LLM:
Phase 1: Analysis
- LLM receives the error + stack trace
- LLM calls tools to search and read files
- Builds understanding of the codebase
Phase 2: Fix Generation
- LLM iterates up to 3 rounds
- Each round can call more tools
- Produces a fix with explanation
LLM Tools
The LLM has 6 tools to examine your codebase:
| Tool | Purpose | Example |
|---|---|---|
find_files | Search for files by pattern | *.java, **/config/* |
read_file | Read file contents | src/main/java/App.java |
search_code | Search for code patterns | class UserService |
list_dir | List directory contents | src/main/java/ |
check_exists | Check if file exists | pom.xml |
get_similar | Find similar files | Files near UserService.java |
Limits:
- File reads: max 50KB per file
- File search: max 50 results
- Code search: max 20 results
Dashboard Server
A lightweight HTTP server that:
- Serves the web dashboard (HTML/CSS/JS)
- Provides REST API for investigations
- Handles concurrent requests with thread pool
API Endpoints:
| Endpoint | Method | Purpose |
|---|---|---|
/api/investigations | GET | List all investigations |
/api/investigate | POST | Start investigation |
/api/resolve | POST | Mark as resolved |
/api/feedback | POST | Submit feedback |
/api/clear-resolved | POST | Delete resolved items |
Project Profile
Profiles store metadata about your project:
{
"name": "my-spring-app",
"type": "maven",
"framework": "spring-boot",
"source_dirs": ["src/main/java"],
"config_dirs": ["src/main/resources"],
"test_dirs": ["src/test"]
}
This helps the LLM know where to look for different types of files.
Data Flow
1. Log file emits error
↓
2. Watcher detects error pattern
↓
3. Creates pending Investigation
↓
4. Dashboard shows error in Live tab
↓
5. User clicks "Investigate"
↓
6. Server sends error to LLM (Phase 1)
↓
7. LLM calls tools (find_files, read_file, etc.)
↓
8. Server executes tools, returns results
↓
9. LLM iterates up to 3 rounds (Phase 2)
↓
10. LLM produces fix
↓
11. Investigation updated with fix + steps
↓
12. Dashboard shows results
↓
13. User provides feedback
Investigation Data Model
Each investigation contains:
Investigation
├── id: string (unique identifier)
├── timestamp: string (ISO 8601)
├── error: string (full error message)
├── error_type: string (e.g., "NullPointerException")
├── steps: array
│ └── { tool: string, args: object, result: string }
├── fix: object | null
│ ├── action: "modify" | "create" | "delete"
│ ├── path: string (file to change)
│ ├── content: string (the fix code)
│ └── reason: string (explanation)
├── summary: string (one-line description)
├── investigated: boolean
├── resolved: boolean
└── feedback: "accurate" | "partial" | "inaccurate" | null
Storage
All data is stored as JSON in ~/.owl-watch/:
| File | Contents | Limits |
|---|---|---|
investigations.json | All investigations | 50 live, 10,000 history |
profiles/<name>.json | Project profiles | One per project |
config.json | User settings | Merged with defaults |
debug.log | LLM interactions | For troubleshooting |
Concurrency
OWL Watch handles concurrent operations safely:
- Log watcher: Runs in main thread (blocking)
- Dashboard server: Runs in background daemon thread
- Investigations: Thread pool with 3 workers
- Rate limiting: 60 requests/minute per IP
Framework-Specific Patterns
The LLM receives framework-specific guidance for common errors:
Spring Boot:
NullPointerExceptionin@Autowiredfield → Missing@ComponentannotationNoSuchBeanDefinitionException→ Bean not registeredLazyInitializationException→ Hibernate session closed
Django:
TemplateDoesNotExist→ Wrong template pathDoesNotExist→ Model query returned no resultsIntegrityError→ Database constraint violation
Express/Node:
Cannot read property of undefined→ Missing null checkECONNREFUSED→ Service not runningRoute not found→ Missing route handler
Hallucination Prevention
OWL Watch includes checks to detect potential LLM hallucinations:
- File metadata: When reading files, the LLM receives line count and character count
- Size validation: If suggested fix is less than 50% of original file size, a warning is shown
- Existence check: The tool results include whether files actually exist
Performance
| Aspect | Limit |
|---|---|
| LLM timeout | 120 seconds per call |
| LLM retries | 3 attempts with exponential backoff |
| Investigation rounds | Maximum 3 iterations |
| Concurrent investigations | Maximum 3 |
| Rate limit | 60 requests/minute per IP |