11 KiB
Android Agent/Genie
This file applies to the Android subtree under android/. It is developer-facing
context for working on the Android Agent/Genie implementation in this repo.
Do not confuse this with the runtime guidance asset at
android/bridge/src/main/assets/AGENTS.md, which is copied into Codex homes on
device for live Agent/Genie sessions.
Module layout
android/app: Agent appandroid/genie: Genie appandroid/bridge: shared Android bridge/runtime compatibility layerandroid/build-agent-genie-apks.sh: helper for building both APKsandroid/install-and-provision-agent-genie.sh: helper for adb install, role assignment, and auth seeding
Default SDK input
When building the Android APKs, use the branch-local Android Agent Platform stub SDK at:
$HOME/code/io/ci/aosp/artifacts/aosp/android16-qpr2-release/android-agent-platform-stub-sdk.zip
The Android build already accepts this through either:
- environment:
ANDROID_AGENT_PLATFORM_STUB_SDK_ZIP - script flag:
android/build-agent-genie-apks.sh --agent-sdk-zip ... - Gradle property:
-PagentPlatformStubSdkZip=...
Treat this path as the default SDK source unless the user explicitly says otherwise.
Authoritative design references
Read these first when recovering Android Agent/Genie context:
- local architecture/status doc:
docs/android-agent-genie-refactor.md - SDK docs inside the stub SDK zip:
README.mdAGENT_GENIE_DESIGN.mdCONSUMER_GUIDE.md
Useful inspection commands:
unzip -p "$HOME/code/io/ci/aosp/artifacts/aosp/android16-qpr2-release/android-agent-platform-stub-sdk.zip" README.md | sed -n '1,220p'
unzip -p "$HOME/code/io/ci/aosp/artifacts/aosp/android16-qpr2-release/android-agent-platform-stub-sdk.zip" AGENT_GENIE_DESIGN.md | sed -n '1,260p'
unzip -p "$HOME/code/io/ci/aosp/artifacts/aosp/android16-qpr2-release/android-agent-platform-stub-sdk.zip" CONSUMER_GUIDE.md | sed -n '1,260p'
Key platform contract to preserve
The current Android work in this repo assumes the same contract described by the stub SDK docs and the local refactor doc:
- Agent and Genie are separate APKs.
- The framework-managed per-session bridge is the app-private Agent<->Genie control plane.
- The framework-owned streaming HTTP exchange is the transport for active
/responsestraffic in both top-level Agent planner sessions and live Genie child sessions. - Genie is headless and should not depend on direct internet access.
- Detached target handling must use framework-authoritative presentation/runtime state and typed detached-target recovery APIs rather than guessed relaunches.
- Genies should keep the paired app hidden by default. Prefer
DETACHED_HIDDENunless the user explicitly asks to bring the app to the front, asks to leave it visibly shown, or the task clearly implies a visible app handoff. - App-scoped HOME drafts are real framework
STATE_CREATEDsessions created beforestartGenieSession(...); if you expose that flow outside the on-device UI, remember that provisional HOME sessions are expected to hold a session-UI lease until they are started or cancelled. - Desktop draft attach is now implemented by bootstrapping an idle app-server
runtime before the first turn:
- HOME drafts start Genie with an internal idle-bootstrap sentinel and become attachable immediately after bridge bootstrap.
- direct AGENT drafts spin up an idle planner app-server host inside the Agent process.
- the first prompt can then be typed in the attached desktop TUI instead of
being supplied to
sessions start.
- Attached runtime completion semantics are intentionally non-terminal:
- attached Genie turns remain live after
turn/completedso the same desktop TUI can send follow-up prompts. - attached direct AGENT planner sessions stay live after planning completes.
- child Genie sessions spawned by an attached planner are launched in idle desktop-attach mode instead of immediately consuming their delegated prompt.
- those idle child sessions still receive Agent-provisioned bridge state first, stage the delegated objective as runtime context, and remain attachable while the planner stays attached.
- if the planner detaches before the user manually starts the child, the staged delegated objective is released automatically as a fallback.
- after a child turn completes, planner-held child sessions remain attachable until the planner attach detaches.
- once the planner detaches, those held child sessions are allowed to settle to their terminal framework state and the parent roll-up can complete.
- attached Genie turns remain live after
- Recoverable hosted-runtime failures are also intentionally non-terminal when a
fresh app-server thread can still be bootstrapped:
- recoverable app-server / bridge I/O failures during an attached Genie turn close only the current desktop attach, then restart the Genie into a fresh attachable idle thread with staged recovery context
- recoverable I/O failures during an unattached Genie run first retry automatically with staged recovery context, then pause into an attachable idle recovery thread if automatic retries are exhausted
- only failures that prevent bootstrapping any new hosted runtime at all should still terminate the Genie session
- Parent-session cancellation is tree-scoped for direct AGENT sessions:
cancelling the parent from the desktop bridge, framework tool bridge, or the
detail UI must cancel the parent and all child Genie sessions through the
framework
cancelSession(...)path, even when some of those sessions are already terminal. - Framework-owned session notifications now support delegated AGENT rendering:
- user-facing question/result/error notifications should be rendered by the
Agent app when the framework calls
onShowOrUpdateSessionNotification(...)and cancelled when it callsonCancelSessionNotification(...) - child Genie notification callbacks under a direct AGENT parent should be ACKed but not rendered; the parent session icon/notification is the only user-facing notification surface for Agent-anchored work
- RUNNING/CREATED/QUEUED callbacks should be ACKed but suppressed so the Agent only notifies for user action or terminal outcomes
- the Agent must ACK a posted notification with
ackSessionNotification(...)and route inline replies throughanswerQuestionFromNotification(...) - if delegated rendering is unavailable, the framework may post a generic fallback notification, so app-side notification code must remain token-aware and idempotent
- user-facing question/result/error notifications should be rendered by the
Agent app when the framework calls
- Direct AGENT planning can ask user-facing questions before any child Genie is
created:
- hosted planner
request_user_inputcalls are stored by the Agent, the parent session is moved toWAITING_FOR_USER, and the parent Agent icon / notification becomes the user-facing question surface - answering the parent question resolves the pending planner tool request so the same planner turn can continue and produce the child-Genie plan
- child Genie questions remain separate child-session questions that roll up through the parent session when user escalation is needed
- hosted planner
- Retention is intentionally bounded:
- keep only the most recent 10 terminal top-level session trees in framework history; never prune active/queued/waiting sessions
- prune stale Agent planner
CODEX_HOMEcache directories under the Agent app cache to the most recent 10 - prune stale Genie
CODEX_HOMEcache directories per paired target app to the most recent 10 from inside the Genie runtime, because the Agent app does not have direct filesystem ownership of other app sandboxes
- HOME icon / notification taps for question or final-result states should route
to
SessionPopupActivity, which uses one dialog-style popup shape for both question answering and result follow-up. For top-level HOMERUNNINGstates with a detached target, the same handler should immediately callshowDetachedTarget(sessionId)so a red-badged live icon brings the paired app on screen without attaching and ending the Genie session. Launcher may dispatch HOME-anchored icon taps through eitherACTION_HANDLE_AGENT_SESSIONorACTION_HANDLE_HOME_AGENT_SESSION; both should first resolve through the transparentSessionRouterActivityso running live-preview taps can open the target without flashing Agent UI. The fullSessionDetailActivityremains the fallback inspector for non-popup states and Agent-app initiated navigation. - HOME completion and cancellation are AGENT-owned policy decisions:
- pressing Done in a completed HOME result popup should call
consumeCompletedHomeSession(sessionId), then close a still-detached target instead of relying on Launcher to consume/open the target directly - pressing Done in a non-completed terminal HOME result popup should call
consumeHomeSessionPresentation(sessionId)and close a still-detached target - pressing Send in the final result popup for a HOME session should launch a fresh HOME continuation with previous-result context, then consume the old result presentation
- pressing Send in the final result popup for a completed AGENT session should resume the same direct parent session with previous-result context, keeping the same parent HOME icon identity; the prompt must not be routed directly to one of the child Genies the planner previously created
- Codex Agent is an AGENT-role app, not a HOME-role surface, so its
user-driven cancellation flows should still call
cancelSession(sessionId);cancelHomeSession(sessionId)is for Launcher/HOME callers
- pressing Done in a completed HOME result popup should call
- Direct AGENT parent sessions may also surface on HOME:
Codexshould be a launcher entrypoint that opens only the planner-session prompt flowCodex Managershould remain the explicit admin/session-list entrypoint- parent HOME icon taps should route through
HANDLE_SESSIONto the per-session popup/detail flow rather than the management list - parent result
Doneshould callconsumeHomeSessionPresentation(parentSessionId)and leave the session inspectable in Manager
External reference implementations
There are standalone stub apps outside this repo that are useful for understanding the intended Android API usage:
- Agent stub root:
$HOME/code/omix/AgentStub - Genie stub root:
$HOME/code/omix/GenieStub
Especially useful files:
$HOME/code/omix/AgentStub/src/com/example/agentstub/ValidationAgentService.java$HOME/code/omix/AgentStub/src/com/example/agentstub/AgentOrchestrationService.java$HOME/code/omix/AgentStub/src/com/example/agentstub/SessionActivity.java$HOME/code/omix/AgentStub/README-standalone.md$HOME/code/omix/GenieStub/src/com/example/geniestub/ValidationGenieService.java$HOME/code/omix/GenieStub/README-standalone.md
Use these as contract/reference implementations for session lifecycle, detached target control, question flow, and framework HTTP exchange usage.
Recovery checklist
When returning to Android Agent/Genie work after interruption:
- Read
docs/android-agent-genie-refactor.mdfor the current architecture and recent implementation status. - Re-read the three markdown files inside the stub SDK zip if the framework contract matters for the change.
- Check
git log --oneline -- android docs/android-agent-genie-refactor.mdto see the latest Android-specific changes. - If behavior is ambiguous, compare against the AgentStub/GenieStub reference implementations before changing repo code.