Skip to content

Skill Execution Engine

Reliable, self-healing automation runtime for Android apps. Every skill workflow runs through a standard lifecycle that handles screen state, app launch, and popup dismissal automatically — so skill authors only write the happy path.

Every workflow follows this sequence:

PhaseWhat happens
0. WakeKEYCODE_WAKEUP — ensures screen is on
1. Back-spamPress Back ×5 — dismiss any deep navigation
2. HomePress Home — guaranteed clean starting point
3. LaunchMonkey launcher intent for the skill’s app_package
4. Popup detectRun all skill-defined popup detectors
5–N. StepsExecute each action, then popup detect after each
# Skill authors just define the steps — the engine handles the rest
class SendDM(Workflow):
name = 'send_dm'
def steps(self):
return [
TapSearch(self.device, self.elements),
TypeAndSearch(self.device, self.elements, query=self.username),
TapUser(self.device, self.elements),
TapMessageButton(self.device, self.elements),
TypeMessage(self.device, self.elements, text=self.message),
TapSend(self.device, self.elements),
]

Workflows can customize the engine:

class QuickAction(Workflow):
auto_launch = False # skip wake/home/launch — already in the app
skip_popup_detect = True # no popup checks between steps

Each skill declares popup patterns in skill.yaml:

popup_detectors:
- detect: "Turn on notifications"
button: "Not now"
label: "Notifications popup"
- detect: "Continue editing"
button: "Save draft"
label: "Draft resume overlay"
- detect: "Learn more"
button: "_back"
label: "Invisible promo overlay"
method: "back"
MethodHow it works
XML text matchScans the UI dump for the detect string, taps button by text
Back pressFor invisible overlays (method: "back")
Generic fallbackMatches common dismiss words: Not now, Skip, Cancel, Dismiss, Later
Pixel detectionRed-band scan for TikTok’s draft resume overlay (invisible to uiautomator)
SkillDetectorsCovers
TikTok10Draft resume, contacts, Facebook, TikTok Shop, notifications, security, promo overlays
Instagram4Notifications, save login, add account, permission requests
Base6Generic: Not now, Skip, Cancel, Dismiss, Later, Allow

Popups are dismissed up to 3 in a chain (handles stacked dialogs).

Every execution is recorded automatically in the database.

  • skill_runs — one row per execution (device, skill, workflow, status, duration, error, app version)
  • skill_compat — aggregated pass/fail per device + skill + workflow

The Skill Hub has a Verify button per device. It runs all workflows on the device and records which ones pass or fail. Use this:

  • When setting up a new phone
  • After an app update changes resource IDs
  • After installing a new skill

Results show as colored badges: OK (green), FAIL (red), UNTESTED (gray).

MethodEndpointPurpose
GET/api/skills/compat?device=SERIALCompatibility matrix
GET/api/skills/runs?device=X&skill=YExecution history
POST/api/skills/{name}/verifyRun verification test
DELETE/api/skills/compat/{device}/{skill}Reset for re-test

Skills define defaults in skill.yaml so the UI pre-fills the run modal:

default_params:
workflows:
send_dm:
username: "@username"
message: "Hey! Love your content"
crawl_hashtag:
query: "#fyp"
passes: 5
actions:
launch_app:
package: "com.zhiliaoapp.musically"
FilePurpose
skills/base.pySkill, Action, Workflow base classes + execution engine
skills/_run_skill.pyCLI entry point, DB tracking
skills/*/skill.yamlPer-skill popup detectors, default params, metadata
models/skill_compat.pySkillRun + SkillCompat ORM
routers/skills.pyREST API for skills, compat, verify
bots/common/adb.pyDevice.dismiss_popups() with skill-specific popup support