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