Your Personal AI Assistant for Android Automation
Miku transforms natural language into native Android actions. No more tapping through menus, just tell Miku what you want, and it happens instantly.
Built on ElizaOS with decentralized inference, Miku bridges conversational AI with deep Android system integration, giving you voice-controlled automation that runs on your terms.
True Native Integration β Unlike chatbots that only reply with text, Miku executes real Android API calls. Set alarms, toggle WiFi, send SMS, control brightness, and launch apps through natural language.
Decentralized Intelligence β Your agent runs on Nosana's distributed GPU network instead of a traditional centralized host. You control the infrastructure and keep the Android execution layer on your own device.
Fast to Start β Deploy the agent, install the app, connect the endpoint, and start automating. The repo keeps the moving pieces separated so the path from clone to demo stays simple.
Hybrid Architecture β ElizaOS handles intent parsing and response formatting, while native Android APIs handle execution. That split keeps the assistant flexible without giving up local device control.
- Set Alarm β "Set alarm for 7 AM tomorrow"
- Set Timer β "Timer for 10 minutes"
- Calendar Events β "Add meeting with John at 2 PM"
- View Schedule β "What's on my calendar today?"
- Reminders β "Remind me to call mom in 30 minutes"
- Send SMS β "Text 081234567890 saying I'm running late"
- Make Calls β "Call 081234567890"
- Notifications β "Notify me to take a break"
- WiFi β "Turn on WiFi" / "Disable WiFi"
- Bluetooth β "Enable Bluetooth"
- Flashlight β "Turn on flashlight"
- Brightness β "Set brightness to 80%"
- Volume β "Set volume to 50%"
- Ringer Mode β "Set phone to silent" / "Vibrate mode"
- Get Location β "Where am I?"
- Open Apps β "Open Spotify"
- Uninstall Apps β "Uninstall Twitter"
Miku uses a hybrid client-server architecture where intelligence lives remotely and execution happens locally:
Why This Architecture?
- Separation of Concerns β AI inference happens on remote compute, execution happens locally on the device
- Privacy β Sensitive actions such as SMS and calls never need to be executed in the cloud
- Scalability β One agent can serve multiple devices while each phone keeps its own permissions and execution state
- Flexibility β You can change prompts, models, and deploy settings without rewriting the Android app
- Docker Hub account
- GitHub account with Actions enabled
- Nosana API key from deploy.nosana.com
- Gemini API key for the current GitHub Actions deploy flow
- Android device (API 26+)
Go to your repo β Settings β Secrets and variables β Actions, then add:
| Secret | Value | Where to Get |
|---|---|---|
DOCKER_USERNAME |
Your Docker Hub username | hub.docker.com |
DOCKER_PASSWORD |
Docker Hub access token | hub.docker.com/settings/security |
NOSANA_API_KEY |
Nosana API key | deploy.nosana.com/account |
GEMINI_API_KEY |
Gemini API key required by the current workflow | Google AI Studio or Google Cloud |
The Docker workflow uses DOCKER_USERNAME to tag the image automatically, so you do not need to hardcode the image name in the repository first.
Miku started with Qwen 3.5 27B as the reference model, but the agent layer can be adapted to other LLMs you wire into ElizaOS, for example OpenAI-compatible endpoints, Claude, GLM, and similar provider integrations.
The checked-in Nosana deploy workflow in this repo currently deploys with GEMINI_API_KEY, so if you switch providers or models, update that workflow and the runtime environment together.
Run these workflows manually from the Actions tab:
- Deploy Docker ElizaOS Builds and pushes the agent image to Docker Hub.
- Build Debug APK or Build Release APK Produces the Android artifact you want to install.
- Deploy Nosana
Starts the Nosana deployment using the Docker image tag you choose, usually
latestor a specific commit SHA.
- Download the APK from the workflow artifact of Build Debug APK or Build Release APK.
- Install it on your Android device.
- Get the agent URL from the Nosana dashboard.
- Open the Miku app, enter the URL, and tap
Connect. - Start automating.
Miku uses a custom ElizaOS action flow that parses natural language into structured JSON:
// Input: "Set alarm for 7 AM tomorrow"
// Output:
{
"text": "β° Alarm set for 7:00 AM",
"actions": [{
"type": "SET_ALARM",
"params": {
"hour": 7,
"minute": 0,
"label": "Alarm"
}
}]
}The parser handles:
- Time extraction β Relative ("in 10 minutes") and absolute ("7 AM")
- Parameter inference β Smart defaults when information is missing
- Phone number extraction β SMS and call targets from plain text
- Multi-action commands β "Turn on WiFi and set brightness to 50%"
AutomationExecutor.kt maps action types to native Android APIs:
| Action Type | Android API | Permission Required |
|---|---|---|
SET_ALARM |
Intent(AlarmClock.ACTION_SET_ALARM) |
None |
SEND_SMS |
SmsManager.sendTextMessage() |
SEND_SMS |
TOGGLE_WIFI |
WifiManager.setWifiEnabled() |
CHANGE_WIFI_STATE |
SET_BRIGHTNESS |
Settings.System.putInt() |
WRITE_SETTINGS |
GET_LOCATION |
FusedLocationProviderClient |
ACCESS_FINE_LOCATION |
TOGGLE_FLASHLIGHT |
CameraManager.setTorchMode() |
CAMERA |
Permission Handling β Miku requests permissions just-in-time. When you first send SMS, it asks for SMS permission. When you first set brightness, it opens system settings.
For exact scheduled reminders, Miku separately requests Android's exact alarm capability when needed.
Health Check:
GET /healthRequest:
POST /api/chat
{
"text": "Set alarm for 7 AM and turn on WiFi",
"userId": "android_user"
}Response:
{
"text": "Alarm ready for 07:00. WiFi will be turned on",
"actions": [
{
"type": "SET_ALARM",
"params": {
"hour": 7,
"minute": 0,
"label": "Alarm"
}
},
{
"type": "TOGGLE_WIFI",
"params": {
"enable": true
}
}
]
}The Android app checks /health before connecting, executes each action sequentially, and displays follow-up status updates in the chat for async actions such as location lookup.
Miku uses Jetpack Compose + ViewModel for reactive UI:
ChatViewModelβ Manages messages, connection state, and API callsAutomationExecutorβ Stateless executor for Android APIsApiClientβ Retrofit HTTP client with URL normalization and health checks
No local storage is required, all state is ephemeral by design.
miku/
βββ src/ # ElizaOS Agent
β βββ parser.ts # Shared natural-language -> action parser
β βββ actions/
β β βββ androidAutomation.ts # Eliza action wrapper for parser output
β βββ api.ts # Plugin routes (/api/chat, /health)
β βββ index.ts # Plugin entry point
β
βββ android/ # Android App
β βββ app/
β β βββ build.gradle.kts # Build config
β β βββ src/main/
β β βββ AndroidManifest.xml # Permissions & config
β β βββ java/com/miku/
β β β βββ MainActivity.kt # Compose UI
β β β βββ ChatViewModel.kt # State management
β β β βββ ApiClient.kt # HTTP client
β β β βββ AutomationExecutor.kt # Android API executor
β β β βββ ReminderReceiver.kt # Reminder notifications
β β β βββ Models.kt # Data classes
β β βββ res/
β β βββ values/strings.xml
β β βββ values/themes.xml
β βββ build.gradle.kts # Root build file
β βββ settings.gradle.kts # Project settings
β βββ gradlew # Gradle wrapper
β
βββ characters/
β βββ android.character.json # Agent personality & examples
β
βββ nos_job_def/
β βββ nosana_eliza_job_definition.json # Nosana deployment config template
β
βββ .github/workflows/
β βββ android-release.yml # Manual release APK build
β βββ build-debug-apk.yml # Manual debug APK build
β βββ deploy-docker-elizaos.yml # Manual Docker build/push
β βββ deploy-nosana.yml # Manual Nosana deployment
β
βββ Dockerfile # Container config
βββ package.json # Node dependencies
βββ README.md # This file
# Install dependencies
pnpm install
# Copy environment template
cp .env.example .env
# Start the agent in development mode
pnpm devFor local Ollama development, .env.example includes an example OpenAI-compatible setup.
By default, Miku now uses a Nosana OpenAI-compatible endpoint with:
MODEL_NAME=Qwen3.5-9B-FP8OPENAI_API_URL=https://5i8frj7ann99bbw9gzpprvzj2esugg39hxbb4unypskq.node.k8s.prd.nos.ci/v1
For embeddings, .env.example also includes:
OPENAI_EMBEDDING_URL=https://4yiccatpyxx773jtewo5ccwhw1s2hezq5pehndb6fcfq.node.k8s.prd.nos.ci/v1OPENAI_EMBEDDING_MODEL=Qwen3-Embedding-0.6B
Conversation fallback order in src/conversation.ts is:
- OpenAI-compatible provider (Nosana/Qwen default)
- Gemini fallback (
GEMINI_API_KEY) if primary provider is unavailable
If both providers are unavailable, Miku keeps parser-only behavior for automation commands and skips conversational LLM replies.
Agent runs on http://localhost:3000
cd android
# Debug build
./gradlew assembleDebug
# Install to connected device
./gradlew installDebug
# Release build
./gradlew assembleReleaseAPK output: android/app/build/outputs/apk/
- Get your computer's local IP.
- Run the agent locally with
pnpm dev. - In the Miku app, enter
http://YOUR_LOCAL_IP:3000. - Ensure the phone and computer are on the same WiFi network.
GitHub Actions handles the maintained deployment path for this repo, but each workflow is triggered manually.
If you already followed Quick Start, there is no extra setup here. Run the workflows in the order you need:
deploy-docker-elizaos.ymlbuild-debug-apk.ymlorandroid-release.ymldeploy-nosana.yml
The maintained manual flow lives in these workflow files:
.github/workflows/android-release.yml.github/workflows/build-debug-apk.yml.github/workflows/deploy-docker-elizaos.yml.github/workflows/deploy-nosana.yml
The Nosana deployment flow uses:
- market discovery via
/api/markets/ - deployment creation via
/api/deployments/create - deployment start via
/api/deployments/{id}/start
- Material Design 3 β Modern, clean UI with dynamic theming
- Real-time messaging β Instant feedback on action execution
- Auto-scroll β Always shows the latest messages
- Manual URL input β Connect to any compatible ElizaOS agent
- Health checks β Validates the endpoint before chat requests begin
- Error handling β Graceful fallback on network issues
- Just-in-time requests β Only asks when needed
- Clear explanations β Shows why each permission is required
- Graceful degradation β Continues working even if some permissions are denied
Every action shows:
- β Success confirmation
- β‘ Action type executed
- π Result details when available
Privacy-First Design:
- No data collection or analytics
- No cloud storage of messages
- All sensitive actions such as SMS and calls execute locally
- Agent only receives command text, not contact lists or other device-private datasets
Permission Model:
- Runtime permissions requested on-demand
- User has full control over what Miku can access
- Permissions can be revoked anytime via Android settings
Network Security:
- Deployed endpoints should use HTTPS whenever available
- The Android app currently allows cleartext traffic, which is useful for local development and LAN testing
- No authentication tokens stored on device
Try these to verify key features:
β° Time Management:
- "Set alarm for 7 AM"
- "Set timer 5 minutes"
- "Add meeting tomorrow at 2 PM"
π§ System Control:
- "Turn on WiFi"
- "Set brightness to 70%"
- "Turn on flashlight"
- "Set phone to silent"
π± Communication:
- "Send SMS to 081234567890 saying hello"
- "Notify me to take a break"
π Location:
- "Where am I?"
π± Apps:
- "Open Chrome"
| Issue | Solution |
|---|---|
| Can't connect to agent | Verify URL format: https://xxx.node.k8s.prd.nos.ci for deployed endpoints, including the protocol. |
| Permission denied | Grant permission when prompted, or check Settings β Apps β Miku β Permissions. |
| Action not executing | Check Logcat for errors: adb logcat | grep Miku. |
| Agent not responding | Check the latest GitHub Actions run and the Nosana dashboard for deployment status. |
| Build fails | Ensure JDK 17 is installed: java -version. |
| Gradle sync fails | Delete .gradle and sync again. |
Edit characters/android.character.json:
{
"name": "Miku",
"system": "Your custom instructions here...",
"messageExamples": [
// Add more examples to improve parsing accuracy
]
}1. Add to shared parser (src/parser.ts):
if (lowerText.includes("screenshot")) {
pushAction(actions, {
type: "TAKE_SCREENSHOT",
params: {}
});
}2. Add to Executor (android/.../AutomationExecutor.kt):
"TAKE_SCREENSHOT" -> takeScreenshot(action.params)3. Implement Android API:
private fun takeScreenshot(params: Map<String, Any>): String {
// Your implementation
return "β
Screenshot saved"
}Add more capabilities:
pnpm add @elizaos/plugin-web-searchUpdate characters/android.character.json:
{
"plugins": [
"@elizaos/plugin-bootstrap",
"@elizaos/plugin-openai",
"@elizaos/plugin-web-search"
]
}- Framework: ElizaOS v2
- Runtime: Node.js
- Reference model: Qwen3.5-27B
- Model layer: OpenAI-compatible endpoints plus other ElizaOS integration paths such as Claude, GLM, and similar providers
- Local dev option: Ollama-compatible OpenAI endpoint
- Inference host: Nosana decentralized GPU network
- API: ElizaOS plugin routes (
/api/chat,/health) - Container: Docker
- Language: Kotlin
- UI Framework: Jetpack Compose (Material Design 3)
- Architecture: MVVM (ViewModel + State)
- HTTP Client: Retrofit + OkHttp
- Async: Kotlin Coroutines
- Location: Google Play Services FusedLocationProvider
- Min SDK: 26 (Android 8.0)
- Target SDK: 35 (Android 15)
- Compute: Nosana decentralized network
- CI/CD: GitHub Actions
- Container Registry: Docker Hub
- Deployment: Automated via GitHub workflow
Agent Response Time:
- Intent parsing: ~500ms
- Total round-trip: <2s including network
Android Execution:
- Action execution: <100ms for native APIs
- UI update: instant through Compose reactivity
Resource Usage:
- APK size: ~8MB
- Memory footprint: ~50MB
- Battery impact: minimal with no persistent background service requirement
Contributions welcome. Areas for improvement:
- Voice input integration (SpeechRecognizer)
- Multi-step action sequences
- Action history & undo
- Widget support
- Tasker integration
- More Android APIs (camera, media, sensors)
MIT License - see LICENSE file.
Built with:
- ElizaOS - AI agent framework
- Nosana - Decentralized compute
- Qwen - Open-source model family used as the original reference point
Miku β Your device, your assistant, your control. π€β¨

