Skip to content

Data Layer Agent

Ali Sadeghi edited this page May 28, 2026 · 3 revisions

Data Layer Agent

Implements the data layer for KMP features. Invoked by creating-kmp-feature skill in Phase 4 (Implementation).

Model: sonnet · Color: blue · Allowed tools: Read, Write, Edit, Glob, Grep, ./gradlew

Generates

  • Domain DTOs with @Serializable in data/model/
  • Ktor Resources (type-safe API routes) in data/remote/
  • {Entity}RemoteDataSource interface + …Impl in data/datasource/
  • {Entity}Repository interface + …Impl in data/repository/
  • feature/{featurename}/build.gradle.kts from the gradle template
  • All using Either<T> for error handling

The gradle template intentionally does NOT redeclare compileSdk, minSdk, or jvmTarget — root config handles them.

Workflow

  1. Load architecture references (_shared/patterns.md, creating-kmp-feature/architecture/data.md) on demand.
  2. Create module structure using the gradle template.
  3. Implement models (data/model/).
  4. Implement Ktor Resources (data/remote/).
  5. Implement DataSource interface + impl.
  6. Implement Repository interface + impl.
  7. Validate: ./gradlew :feature:{featurename}:assembleAndroidMain.

Example Output

// feature/productcatalog/data/model/Product.kt
@Serializable
data class Product(
    val id: String,
    val name: String,
    val price: Double,
    val imageUrl: String?,
)

// feature/productcatalog/data/remote/ProductResources.kt
@Resource("/products")
class ProductResource {
    @Resource("{id}")
    data class Id(val parent: ProductResource, val id: String)
}

// feature/productcatalog/data/datasource/ProductRemoteDataSource.kt
interface ProductRemoteDataSource {
    suspend fun getProducts(): Either<List<Product>>
    suspend fun getProduct(id: String): Either<Product>
}

class ProductRemoteDataSourceImpl(
    private val client: ApiClient,
) : ProductRemoteDataSource {
    override suspend fun getProducts(): Either<List<Product>> =
        client.get(ProductResource())
    override suspend fun getProduct(id: String): Either<Product> =
        client.get(ProductResource.Id(ProductResource(), id))
}

// feature/productcatalog/data/repository/ProductRepository.kt
interface ProductRepository {
    suspend fun getProducts(): Either<List<Product>>
    suspend fun getProduct(id: String): Either<Product>
}

class ProductRepositoryImpl(
    private val dataSource: ProductRemoteDataSource,
) : ProductRepository {
    override suspend fun getProducts() = dataSource.getProducts()
    override suspend fun getProduct(id: String) = dataSource.getProduct(id)
}

Error Handling

Uses ErrorConst from {CORE_DATA_PKG}:

Constant Triggered when
ErrorConst.NoNetwork Connection errors
ErrorConst.Unauthorized HTTP 401
ErrorConst.SerializationError JSON parsing failures
ErrorConst.ServerUnknownError(httpCode) Unknown errors

On Build Failure

Loads troubleshooting/data.md on demand, identifies the error pattern, fixes, retries (max 3).

Output Report

## Data Layer Complete: {featurename}

### Files Created
- build.gradle.kts
- data/model/*.kt
- data/remote/{Feature}Resources.kt
- data/datasource/{Feature}RemoteDataSource.kt + Impl
- data/repository/{Feature}Repository.kt + Impl

### Rules Followed
✅ Interface + Impl pairs
✅ Either<T> returns
✅ Lowercase packages
✅ Build successful

Back to Feature-Development-Agents | Agents

Clone this wiki locally