| Metadata | Value |
|---|---|
| Status | Archived |
| Version | 1.0.0 |
| Last Updated | 2026-09-10 |
| Author | Sangeetha Grantha Team |
| Document Type | Archive |
[!NOTE] Historical evidence: results, counts, commands, and observations below belong to the original work described here. The editorial update date is not a new test or corpus verification. For present behavior, use current ingestion guide.
This document provides a detailed evaluation of Koog specifically for the Krithi import pipeline use case. It builds on existing Koog analysis documents and provides import-pipeline-specific recommendations.
Key Finding: Koog offers significant value for complex, multi-stage import workflows, but may be over-engineered for initial phases. A phased evaluation approach is recommended: start with custom workflow, then evaluate Koog for specific pain points.
The import pipeline consists of 10 stages:
imported_krithisKoog Strength: Define complex workflows as graphs
Import Pipeline as Koog Graph: val importWorkflow = agent { graph { val discovery = node(“discover”) { discoverUrls(source) } val scraping = node(“scrape”) { scrapeUrl(url) } val extraction = node(“extract”) { extractMetadata(html) } val entityResolution = node(“resolve”) { resolveEntities(metadata) } val cleansing = node(“cleanse”) { cleanseData(mapped) } val deduplication = node(“dedupe”) { findDuplicates(cleaned) } val validation = node(“validate”) { validateData(processed) } val staging = node(“stage”) { stageForReview(validated) }
```text
discovery -> scraping -> extraction -> entityResolution ->
cleansing -> deduplication -> validation -> staging
} } ```
Benefits:
Considerations:
Koog Strength: Integrate external systems as tools
Import Pipeline Tools:
val scrapingTool = tool(“scrape_url”) {
description = “Scrape HTML content from URL”
parameter
val entityResolutionTool = tool(“resolve_composer”) {
description = “Resolve composer name to canonical entity”
parameter
val validationTool = tool("validate_krithi") {
description = "Validate extracted Krithi data"
parameter<ExtractedMetadata>("metadata")
execute { metadata ->
validationService.validate(metadata)
}
}
Benefits:
Considerations:
Koog Strength: Built-in retry and persistence
Retry Configuration: agent { retryPolicy { maxRetries = 3 backoffStrategy = ExponentialBackoff( initialDelay = 1.seconds, maxDelay = 30.seconds ) }
```text
persistence {
// Save workflow state for recovery
storage = DatabasePersistence(db)
} } ```
Benefits:
Considerations:
Koog Strength: OpenTelemetry integration
**Tracing:**
agent {
tracing {
exporter = OpenTelemetryExporter()
level = TraceLevel.DETAILED
}
}
Benefits:
Considerations:
Koog Strength: Switch LLM providers easily
**Multi-Provider Support:**
agent {
llm = when (stage) {
"extraction" -> GeminiProvider(model = "gemini-2.0-flash-exp")
"validation" -> GeminiProvider(model = "gemini-1.5-pro")
else -> GeminiProvider(model = "gemini-2.0-flash-exp")
}
}
Benefits:
Considerations:
| Feature | Koog | Custom (Coroutines) | Winner |
|---|---|---|---|
| Workflow Definition | Graph DSL | Function composition | Koog (more expressive) |
| Error Handling | Built-in retry | Manual implementation | Koog (less code) |
| Observability | OpenTelemetry | Manual logging | Koog (better) |
| State Persistence | Built-in | Manual (DB) | Koog (easier) |
| Learning Curve | Medium-High | Low | Custom (team knows it) |
| Performance | Some overhead | Direct execution | Custom (faster) |
| Flexibility | Framework constraints | Full control | Custom (more flexible) |
| Maintenance | Framework updates | Own code | Custom (more control) |
| Provider Switching | Easy | Manual | Koog (if needed) |
| Tool Calling | Built-in | Manual | Koog (if using LLM tools) |
**Custom Workflow (Coroutines):**
suspend fun importPipeline(url: String): ImportResult {
return try {
val html = webScrapingService.scrape(url)
val extracted = extractionService.extract(html)
val resolved = entityResolutionService.resolve(extracted)
val cleaned = cleansingService.cleanse(resolved)
val validated = validationService.validate(cleaned)
stagingService.stage(validated)
ImportResult.Success
} catch (e: Exception) {
// Manual retry logic
if (retryCount < 3) {
delay(exponentialBackoff(retryCount))
importPipeline(url)
} else {
ImportResult.Failure(e)
}
}
}
Koog Workflow: val importAgent = agent { graph { val scrape = node(“scrape”) { scrapeUrl(url) } val extract = node(“extract”) { extractMetadata(html) } val resolve = node(“resolve”) { resolveEntities(metadata) } val cleanse = node(“cleanse”) { cleanseData(mapped) } val validate = node(“validate”) { validateData(cleaned) } val stage = node(“stage”) { stageForReview(validated) }
scrape -> extract -> resolve -> cleanse -> validate -> stage
}
```text
retryPolicy { maxRetries = 3 }
tracing { level = TraceLevel.DETAILED } } ```
Analysis:
Complex, Multi-Stage Workflows:
Long-Running Workflows:
LLM-Heavy Workflows:
Observability Requirements:
Simple, Linear Workflows:
Performance-Critical Paths:
Rapid Iteration:
Existing Infrastructure:
Build custom coroutine-based pipeline:
WebScrapingServiceEntityResolutionServiceImportPipelineService with coroutinesRationale:
Build Koog POC for one stage:
POC Criteria:
If Koog Adds Value:
If Custom Sufficient:
┌─────────────────────────────────────────┐
│ Import API Endpoints │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ ImportPipelineService │
│ (Orchestrates Koog agents) │
└──────┬──────────┬──────────┬───────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Extraction│ │ Entity │ │Validation│
│ Agent │ │Resolution│ │ Agent │
│ (Koog) │ │ Agent │ │ (Koog) │
│ │ │ (Koog) │ │ │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└──────────┴──────────┘
│
┌───────────▼───────────┐
│ Custom Services │
│ (Scraping, Staging) │
└──────────────────────┘
Extraction Agent:
extract_krithi_metadataEntity Resolution Agent:
resolve_composer, resolve_raga, resolve_deity, resolve_templeValidation Agent:
validate_krithi_dataWith Existing Services:
WebScrapingService: Called before Koog agentsTransliterationService: Called as tool or after extractionDevelopment:
Operational:
Dependencies:
Short-Term:
Long-Term:
Quantifiable:
Development:
Operational:
Dependencies:
Short-Term:
Long-Term:
Quantifiable:
| Risk | Impact | Probability | Mitigation |
|---|---|---|---|
| Learning Curve | Medium | High | Training, documentation, POC |
| Framework Changes | Medium | Low | Version pinning, monitoring |
| Over-Engineering | Low | Medium | Start with POC, evaluate value |
| Performance Overhead | Low | Medium | Benchmark, optimize if needed |
| Team Resistance | Medium | Low | Involve team in decision |
| Risk | Impact | Probability | Mitigation |
|---|---|---|---|
| Missing Features | Medium | Medium | Add as needed, consider Koog later |
| Error Handling Complexity | Medium | Medium | Use proven patterns, test thoroughly |
| Observability Gaps | Low | Medium | Add OpenTelemetry manually |
| Maintenance Burden | Low | Low | Well-structured code, good tests |
Start with Custom Workflow:
Rationale:
Build Koog POC (After Custom):
Evaluation Criteria:
Adopt Koog If:
Stick with Custom If:
Koog offers compelling features for complex import workflows, but may not be necessary initially. The recommended approach:
Key Insight: Don’t optimize prematurely. Build what works, then evaluate if Koog adds value for specific pain points.
Success Factors: