openclaw - 💡(How to fix) Fix [Feature]: Android node command for allowlisted local URL/deeplink launch

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Add a narrow Android node command, for example system.open_url, that launches local URLs/deeplinks via Android Intent.ACTION_VIEW only when the URL matches an explicit allowlist.

Error Message

  1. Return a structured success/error result to the gateway.

Root Cause

Add a narrow Android node command, for example system.open_url, that launches local URLs/deeplinks via Android Intent.ACTION_VIEW only when the URL matches an explicit allowlist.

Fix Action

Fix / Workaround

Today the workaround is to send a notification and have the local companion app parse that notification text. That works for a prototype, but it is indirect, brittle, and abuses the notification surface as an IPC channel.

Using Canvas as a workaround is not reliable either. In a current Android node setup, canvas.present and canvas.navigate may not be available/allowed for Android nodes. There is also prior discussion in openclaw/openclaw#32319 showing that Android Canvas WebView workarounds such as intent:// URIs and window.open() hit ERR_UNKNOWN_URL_SCHEME; the suggested native fix there was to handle external navigation with shouldOverrideUrlLoading() and Intent.ACTION_VIEW.

  1. Forking/patching the official OpenClaw Android app locally

Code Example

local-alarm://command?action=create_or_update&label=morning_main&hour=8&minutes=30&repeat_bits=127&enabled=true

---

system.open_url

---

{
  "url": "local-alarm://command?action=create_or_update&label=morning_main&hour=8&minutes=30&repeat_bits=127&enabled=true",
  "reason": "Update the user's allowlisted local alarm app"
}

---

{
  "nodes": {
    "android": {
      "openUrl": {
        "enabled": true,
        "allowed": [
          {
            "scheme": "local-alarm",
            "host": "command"
          },
          {
            "scheme": "my-notes",
            "host": "open"
          }
        ]
      }
    }
  }
}

---

calendar.events
camera.list
contacts.search
device.health
device.info
device.permissions
device.status
location.get
motion.activity
motion.pedometer
notifications.actions
notifications.list
system.notify
talk.ptt.cancel
talk.ptt.once
talk.ptt.start
talk.ptt.stop

---

https://github.com/openclaw/openclaw/issues/32319
RAW_BUFFERClick to expand / collapse

Summary

Add a narrow Android node command, for example system.open_url, that launches local URLs/deeplinks via Android Intent.ACTION_VIEW only when the URL matches an explicit allowlist.

Problem to solve

OpenClaw Android nodes can already expose useful local capabilities such as notifications, location, camera, talk, and device status. However, there is currently no safe first-class way for the gateway/assistant to ask the Android node to open a local app deeplink.

This blocks local-first companion-app workflows where the safest integration point is on the phone itself. One concrete example is an alarm-clock companion app that exposes a deeplink such as:

local-alarm://command?action=create_or_update&label=morning_main&hour=8&minutes=30&repeat_bits=127&enabled=true

Today the workaround is to send a notification and have the local companion app parse that notification text. That works for a prototype, but it is indirect, brittle, and abuses the notification surface as an IPC channel.

Using Canvas as a workaround is not reliable either. In a current Android node setup, canvas.present and canvas.navigate may not be available/allowed for Android nodes. There is also prior discussion in openclaw/openclaw#32319 showing that Android Canvas WebView workarounds such as intent:// URIs and window.open() hit ERR_UNKNOWN_URL_SCHEME; the suggested native fix there was to handle external navigation with shouldOverrideUrlLoading() and Intent.ACTION_VIEW.

The missing primitive is not "run arbitrary Android intents." That would be too broad. The missing primitive is a small, auditable, allowlisted local URL/deeplink launcher.

Proposed solution

Add an Android node command such as:

system.open_url

Suggested request shape:

{
  "url": "local-alarm://command?action=create_or_update&label=morning_main&hour=8&minutes=30&repeat_bits=127&enabled=true",
  "reason": "Update the user's allowlisted local alarm app"
}

The Android app should:

  1. Parse the URL.
  2. Verify the scheme/host against an explicit allowlist.
  3. Reject unsupported schemes, hosts, malformed URLs, intent:// URLs, and arbitrary package/class launches.
  4. Launch the URL with Intent(Intent.ACTION_VIEW, uri) only after validation.
  5. Return a structured success/error result to the gateway.

Suggested allowlist config shape:

{
  "nodes": {
    "android": {
      "openUrl": {
        "enabled": true,
        "allowed": [
          {
            "scheme": "local-alarm",
            "host": "command"
          },
          {
            "scheme": "my-notes",
            "host": "open"
          }
        ]
      }
    }
  }
}

The exact config shape can differ; the important behavior is that this is explicit, disabled or empty by default, and scoped to known local app URL surfaces.

Possible command names:

  • system.open_url
  • android.open_url
  • device.open_url

If maintainers prefer a more domain-specific approach, an Android local capability/plugin command surface could also work, but a small allowlisted URL command seems reusable across multiple companion-app cases.

Alternatives considered

  1. Arbitrary Android intent command

    Rejected. This is too powerful and could become a serious local privilege-escalation/security footgun. The request here is intentionally narrower: URL/deeplink only, validated against an allowlist.

  2. Canvas/WebView deeplink launcher

    Rejected for reliability. Android Canvas commands may not be available on all node configurations, and prior Canvas WebView attempts with intent:///window.open() have hit ERR_UNKNOWN_URL_SCHEME (openclaw/openclaw#32319). Canvas should not be used as an indirect intent launcher.

  3. Notification text as command transport

    Works as a prototype and is useful today, but it is the wrong long-term abstraction. Notifications are user-facing UI, not a robust IPC surface. Notification parsing can also be noisy, duplicate-prone, and harder to audit.

  4. Forking/patching the official OpenClaw Android app locally

    Rejected. A local fork would diverge from upstream and be overwritten or made stale by future Android app updates.

  5. Separate companion app only

    A companion app is still useful, but it needs a clean way to receive an assistant-triggered local command. An allowlisted OpenClaw Android URL command would provide that bridge without making OpenClaw responsible for every companion app's internals.

Impact

Affected users/systems:

  • Android users building local-first OpenClaw automations.
  • Companion apps that expose safe deeplinks for local commands.
  • Workflows where cloud/gateway round-trips are undesirable or less secure than local phone IPC.

Severity:

  • Medium. This does not block all Android node use, but it blocks a clean implementation path for local app integrations.

Frequency:

  • Repeated for any Android companion-app automation that needs a local command path.

Consequence:

  • Users fall back to brittle workarounds such as notification parsing, WebView hacks, or local forks.
  • Safe local automations are harder to build than they need to be.

Example use cases:

  • Alarm-clock companion app: create/update/enable a local alarm through a local-alarm://... deeplink.
  • Smart-home companion app: open a local, user-consented bridge command.
  • Health/wellness companion app: trigger a local app-owned action without exposing arbitrary Android intents.
  • Notes/task app: ask OpenClaw to open a pre-approved app route such as my-notes://open?list=today.
  • Navigation app: ask OpenClaw to open an approved navigation route or saved destination flow, while keeping location handling inside the chosen app.
  • Reading/media app: open a pre-approved local app route such as a queue, playlist, or saved article.
  • User-approved app launcher: let the user ask OpenClaw to open specific apps or app screens that were explicitly allowed ahead of time, without giving OpenClaw general app-launch or arbitrary intent power.
  • Any user-owned Android app that wants to expose a small command surface to OpenClaw while keeping the actual sensitive logic inside the app.

Evidence/examples

Observed current Android node command surface on a paired Samsung Android device:

calendar.events
camera.list
contacts.search
device.health
device.info
device.permissions
device.status
location.get
motion.activity
motion.pedometer
notifications.actions
notifications.list
system.notify
talk.ptt.cancel
talk.ptt.once
talk.ptt.start
talk.ptt.stop

There is no current open_url, ACTION_VIEW, start_activity, or generic local deeplink command in that advertised surface.

Related issue:

https://github.com/openclaw/openclaw/issues/32319

That issue discusses Android Canvas WebView external-link behavior and notes that intent:// URIs / window.open() are not reliable from Canvas. The requested command here is not a Canvas workaround; it is a deliberate Android node command with explicit allowlisting.

Additional information

Security constraints that seem important:

  • Disabled by default or empty allowlist by default.
  • Must require gateway/node command allowlist permission like other node commands.
  • Only allow configured schemes/hosts.
  • Do not support intent://.
  • Do not support arbitrary package/class launching.
  • Do not support shell commands or arbitrary extras.
  • Return structured errors such as OPEN_URL_NOT_ALLOWED, OPEN_URL_MALFORMED, OPEN_URL_NO_HANDLER, and OPEN_URL_LAUNCH_FAILED.
  • Consider first-use confirmation or a visible Android setting for high-risk deployments.
  • Log/audit launches on the gateway side.

This keeps the feature aligned with OpenClaw's local capability model while avoiding a broad Android intent execution surface.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Feature]: Android node command for allowlisted local URL/deeplink launch