When AI Meets AI β An Android project demonstrating an AI-assisted development ecosystem where multiple AI agents (Designer, Accessibility, Functionality) collaborate under an orchestrator to build and maintain an Android application.
π Read the full article: When AI Meets AI
AIEcosystemPoc is a sample Android project that showcases a novel development workflow where AI agents are guided by structured rules, architecture definitions, and orchestration logic stored inside the repository itself (the ai/ directory). Instead of ad-hoc prompting, this approach creates a self-documenting, rule-driven AI development pipeline.
The app itself is a minimal but well-architected Android application built with Jetpack Compose and Material 3, serving as the canvas on which AI agents operate.
AIEcosystemPocSampleCode/
βββ ai/ # AI agent definitions & rules
β βββ agents/
β βββ development/ # Development agent configs
β
βββ app/
β βββ src/main/java/com/a7/aiecosystempoc/
β βββ core/
β βββ analytics/
β β βββ AnalyticsManager.kt # Simulated Firebase Analytics
β βββ logger/
β β βββ AppLogger.kt # Centralized logging (AI + App)
β βββ navigation/
β β βββ AppNavHost.kt # Jetpack Navigation host
β β βββ AppNavigator.kt # Route constants
β βββ network/
β β βββ NetworkClient.kt # Simulated HTTP client (GET/POST)
β β βββ Repository.kt # Data repository + UserProfile model
β βββ remoteconfig/
β β βββ AppConfig.kt # Config data class
β β βββ RemoteConfigKeys.kt # Feature flag keys
β β βββ RemoteConfigManager.kt # Simulated Firebase Remote Config
β βββ theme/
β β βββ Color.kt # Color palette
β β βββ Theme.kt # Material 3 theming (dynamic color)
β β βββ ThemeController.kt # Runtime theme state
β β βββ Type.kt # Typography
β βββ ui/
β βββ activity/
β β βββ SplashActivity.kt # Splash screen (launcher)
β β βββ MainActivity.kt # Main activity with NavHost
β βββ components/
β βββ PrimaryButton.kt # Reusable button component
β
βββ build.gradle.kts # Root build config
βββ gradle/libs.versions.toml # Version catalog
βββ AI_README.md # AI agent instructions
| Component | Description |
|---|---|
AI Agent System (ai/) |
Directory containing agent definitions, architecture rules, guidelines, and orchestration logic that AI tools read before performing tasks |
| AppLogger | Dual-purpose logger with ai() for AI agent logs and app() for application logs |
| NetworkClient | Simulated HTTP layer with configurable failure rate (20%) for testing error states |
| Repository | Bridges ViewModels and NetworkClient; returns dummy UserProfile data |
| RemoteConfigManager | Simulated Firebase Remote Config with feature flags and A/B test variants |
| AnalyticsManager | Simulated Firebase Analytics for event tracking, screen tracking, and user properties |
| AppNavHost | Jetpack Compose Navigation with route-based navigation |
| ThemeController | Runtime theme switching via Compose state |
| PrimaryButton | Reusable Material 3 button component |
The project defines a multi-agent system:
- Designer Agent β Generates UI components using Jetpack Compose following design guidelines
- Accessibility Agent β Validates generated UI for accessibility compliance
- Functionality Agent β Implements business logic, network calls, and data flow
An Orchestrator coordinates these agents, ensuring they follow the rules defined in ai/architecture/, ai/guidelines/, and ai/orchestrator/.
| Technology | Version |
|---|---|
| Kotlin | 2.0.21 |
| AGP (Android Gradle Plugin) | 9.0.1 |
| Jetpack Compose BOM | 2024.09.00 |
| Material 3 | Latest (via BOM) |
| Navigation Compose | 2.9.7 |
| Lifecycle ViewModel Compose | 2.10.0 |
| Min SDK | 24 (Android 7.0) |
| Target/Compile SDK | 36 |
- Android Studio Meerkat (2024.3+) or newer (AGP 9.x requires latest AS)
- JDK 11 or higher
- Android SDK with API 36 installed
- An Android Emulator or physical device (API 24+)
-
Clone the repository
git clone https://github.com/AKannanDev/AIEcosystemPocSampleCode.git cd AIEcosystemPocSampleCode -
Open in Android Studio
- Open Android Studio β File β Open β select the project root folder
- Wait for Gradle sync to complete
-
Run the app
- Select a device/emulator from the toolbar
- Click Run βΆ (or
Shift + F10) - The app will launch with a Splash Screen ("AI Engineering Ecosystem") for 2 seconds, then navigate to the Main Activity
-
Run from command line (alternative)
# Build debug APK ./gradlew assembleDebug # Install on connected device ./gradlew installDebug # Run unit tests ./gradlew testDebugUnitTest # Run instrumented tests ./gradlew connectedDebugAndroidTest
This section walks through how to create a feature using the Login screen as a real example. The project includes a feature template at ai/features/login-feature.md that AI agents (and developers) follow.
Create a markdown file in ai/features/ describing the feature. Here's the login example:
ai/features/login-feature.md
The template defines:
| Section | Purpose |
|---|---|
| Description | What the feature does β "A login screen with email, password, and a login button" |
| Acceptance Criteria | Checkboxes the feature must satisfy before it's complete |
| Figma Design | Link or path to the design reference (e.g. res/drawable/login_screen_figma.png) |
| Accessibility Design | Accessibility requirements (standard or custom) |
| A/B Test Details | Remote Config keys if the feature is behind a feature flag |
| Click Actions | What each button does β "Login Button β navigates to Home, triggers login_cta_clicked" |
| Navigation Flow | Screen-to-screen flow β "Login Screen β Click Login β Home Screen" |
| Analytics & Events | Events to track β login_screen_viewed, login_cta_clicked |
| Test Cases | QA and feature-specific test requirements |
app/src/main/java/com/a7/aiecosystempoc/features/login/
βββ ui/
β βββ LoginScreen.kt # Composable UI
β βββ LoginViewModel.kt # ViewModel with state
βββ data/
βββ LoginRepository.kt # (optional) Data layer
features/login/ui/LoginViewModel.kt
package com.a7.aiecosystempoc.features.login.ui
import androidx.lifecycle.ViewModel
import com.a7.aiecosystempoc.core.analytics.AnalyticsManager
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
class LoginViewModel : ViewModel() {
private val _email = MutableStateFlow("")
val email: StateFlow<String> = _email
private val _password = MutableStateFlow("")
val password: StateFlow<String> = _password
fun onEmailChanged(value: String) { _email.value = value }
fun onPasswordChanged(value: String) { _password.value = value }
fun onScreenViewed() {
AnalyticsManager.trackScreen("login_screen_viewed")
}
fun onLoginClicked() {
AnalyticsManager.trackEvent("login_cta_clicked", mapOf(
"email" to _email.value
))
}
}features/login/ui/LoginScreen.kt
package com.a7.aiecosystempoc.features.login.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.a7.aiecosystempoc.core.ui.components.PrimaryButton
@Composable
fun LoginScreen(
viewModel: LoginViewModel = viewModel(),
onLoginSuccess: () -> Unit
) {
val email by viewModel.email.collectAsState()
val password by viewModel.password.collectAsState()
LaunchedEffect(Unit) { viewModel.onScreenViewed() }
Column(
modifier = Modifier.fillMaxSize().padding(24.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
OutlinedTextField(
value = email,
onValueChange = viewModel::onEmailChanged,
label = { Text("Email") },
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = password,
onValueChange = viewModel::onPasswordChanged,
label = { Text("Password") },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(24.dp))
PrimaryButton(
text = "Login",
modifier = Modifier.fillMaxWidth()
) {
viewModel.onLoginClicked()
onLoginSuccess()
}
}
}AppNavigator.kt β add the route constant:
object AppNavigator {
const val HOME = "home"
const val LOGIN = "login" // β add this
const val USER_PROFILE = "user_profile"
}AppNavHost.kt β add the composable destination and update the start destination:
composable(AppNavigator.LOGIN) {
LoginScreen(
onLoginSuccess = {
navController.navigate(AppNavigator.HOME) {
popUpTo(AppNavigator.LOGIN) { inclusive = true }
}
}
)
}Cross-check with the feature template (ai/features/login-feature.md):
- Email text field present
- Password text field present
- Login button navigates to Home screen
-
login_screen_viewedevent tracked on screen entry -
login_cta_clickedevent tracked on button click
| Step | What to do |
|---|---|
| 1 | Create ai/features/<feature-name>.md with the feature template (description, acceptance criteria, design, analytics, tests) |
| 2 | Create the feature directory under features/<feature_name>/ui/ and optionally data/ |
| 3 | Implement ViewModel with state and analytics events |
| 4 | Implement Screen composable using Material 3 and core components like PrimaryButton |
| 5 | Register the route in AppNavigator.kt and AppNavHost.kt |
| 6 | Verify all acceptance criteria from the feature template are met |
π‘ Tip: AI agents read the
ai/features/templates automatically. Just create the.mdfile with your requirements and let the AI ecosystem generate the implementation!
SplashActivity (2s delay)
βββ Initializes RemoteConfigManager
βββ Navigates to β MainActivity
βββ AppNavHost
βββ Home Screen ("No feature implemented yet")
The app is intentionally minimal β it's a scaffold designed for AI agents to build features on top of. The infrastructure (networking, analytics, logging, remote config, navigation, theming) is all in place.
# Unit tests
./gradlew testDebugUnitTest
# Instrumented tests (requires device/emulator)
./gradlew connectedDebugAndroidTestUnit tests are configured with unitTests.isReturnDefaultValues = true to allow Android framework mocking.
This project is a proof of concept / sample code for the article When AI Meets AI.
a7 β @ag7aka