Notifications
Read accessible active Android notifications without opening the notification shade, waking the display or dismissing keyguard:
clawperator notifications list --app <package> --limit 25 --max-text-chars 256
clawperator doctor --capability background-observation
Notification access must be enabled for the selected Operator and its listener must be connected. Operator setup grants access; unavailable access or a connection failure returns an error, not an empty list. Android profile and sensitive-content restrictions still apply.
list_notifications accepts optional applicationId, limit (1-100, default 25)
and maxTextChars (1-1024, default 256). Omit applicationId for all accessible apps.
Blank values, unknown parameters and invalid bounds are rejected. The same action
works through HTTP /execute and generic MCP execute.
The canonical step's data.payload is a JSON string with schemaVersion: 1,
observedElapsedMs, deviceState, notifications, total and truncated. Node's
decodeNotificationMediaPayload validates and decodes it. Notifications include
key, applicationId, nullable title/text, postTime, ongoing/clearable/group fields,
action descriptors, text/action truncation flags and nullable generic progress.
deviceState records screenOn, deviceLocked and userUnlocked at query completion.
These endpoint values alone cannot exclude a transient wake; use independent
state-transition evidence for regression tests. Ongoing notifications and group summaries are included. Results are capped at
64,000 payload bytes as well as the requested item/text limits; truncated
indicates omitted items. An empty list with total zero is a successful snapshot.
Action descriptors expose opaque actionId, title, requiresInput and requiresAuthentication. Use these handles for the button operation below. Progress is the notification's generic value/max and indeterminate flag, not a playback timestamp. Use media status.
Observation-only execution lists may contain list_notifications, list_media_sessions and get_media_status in any order. They bypass interactive readiness and do not need accessibility or an app window. Lists may also include media_pause, media_play and media_seek without waking or unlocking the device. Any list containing a UI action, dismissal or notification button retains normal whole-execution interactive readiness; no prefix runs if readiness fails. Before first unlock after reboot, a supported Android user-state probe returns DEVICE_USER_NOT_UNLOCKED before dispatch. Unlock the user once during setup; reads do not unlock it. An unsupported probe leaves platform/runtime failures authoritative.
Errors include NOTIFICATION_ACCESS_DENIED, NOTIFICATION_LISTENER_DISCONNECTED, NOTIFICATION_QUERY_FAILED and NOTIFICATION_SERVICE_UNAVAILABLE. Inspect the failed step's errorCode; transport failures remain distinct.
Dismissal
clawperator notifications dismiss '<key>' --wait-timeout-ms 2000
dismiss_notification requires notificationKey (nonblank, at most 4096
characters). Optional waitTimeoutMs is an integer from 0 to 30000, default 0.
Android checks the current listener snapshot and clearability immediately before
requesting cancellation. The schemaVersion 1 payload contains notificationKey,
dispatched, removalObserved, waitTimeoutMs, observedElapsedMs and deviceState.
dispatched: true means cancellation was requested. Only removalObserved: true
means a subsequent active snapshot omitted the key. With a positive wait the
service polls until removal or the deadline; a still-present notification returns
success with removalObserved=false, including when Android refuses cancellation.
It does not claim deletion. A re-posted notification with the same key may prevent
confirmation. Observation failure after dispatch returns an error with dispatch
receipt retained. A missing key returns NOTIFICATION_EXPIRED; a non-clearable
notification returns NOTIFICATION_NOT_DISMISSIBLE before dispatch.
Notification buttons
clawperator notifications action '<key>' --action '<action-id>'
invoke_notification_action requires notificationKey and actionId (nonblank,
at most 128 characters). Use the opaque actionId returned by a recent listing.
The schemaVersion 1 payload contains notificationKey, actionId, dispatched,
observedElapsedMs and deviceState. Dispatch does not confirm the application's
side effect.
The service validates the current key and notification revision, then sends the exact advertised PendingIntent once. Notification updates, removals, listener replacement/reconnection and Operator restart invalidate references. The process issues fresh opaque handles for each listing and retains at most 2000 advertised button handles; an evicted handle also requires a fresh listing. Unadvertised buttons, including truncated ones, cannot be invoked. No replacement button is selected after a race. Android can still change state between validation and dispatch.
| Error | Meaning |
|---|---|
| NOTIFICATION_EXPIRED | The key is no longer active |
| NOTIFICATION_ACTION_EXPIRED | The advertised revision/handle is no longer available or does not match |
| NOTIFICATION_ACTION_CANCELLED | Android canceled the PendingIntent; dispatched=false |
| NOTIFICATION_ACTION_INPUT_UNSUPPORTED | The button requires RemoteInput, including data-only input |
| NOTIFICATION_ACTION_AUTHENTICATION_UNSUPPORTED | The button requires authentication on a platform that exposes this requirement |
| NOTIFICATION_MEDIA_OPERATION_FAILED | A platform operation failed; inspect dispatched before deciding what to do next |
Dismissal and buttons require interactive readiness and accessibility for the
whole execution, including mixed read/mutation lists. They do not automatically
authenticate. Both work through runNotificationMedia, HTTP /execute and generic
MCP execute with the same canonical action parameters. All step data remains
string-valued. Failures/cancellation retain dispatched and waitTimeoutMs when a
step began; a missing transport receipt is uncertain and never triggers replay.