Skip to content

Safety

TouchPilot's safety model has four layers. Each one is enforced in code, not just promised in the UI.

1. Skill allowlists

Every bundled skill declares the set of tools it may call. If a tool is not in the active skill's allowed_tools list, the agent loop rejects the call with a POLICY_BLOCKED event before it is executed.

Example: the messages skill only allows observation, navigation, typing, and back/home. It cannot send a tap on a Send button unless the user explicitly authorizes that step.

See Authoring skills for the full contract.

2. Tool risk levels

Every tool has a risk level. The current catalog defines:

Risk Examples Behaviour
LOW observe_screen, wait_for_idle, get_foreground_app Runs without prompting.
MEDIUM open_app, tap, type_text, scroll, swipe Prompts for approval on first use per session.
HIGH (none in the default catalog yet) Always prompts.
BLOCKED (none in the default catalog) Hard-blocked by policy.

The agent loop surfaces a confirmation card in chat before any medium- or high-risk call. The card shows the tool name, its arguments (with redaction applied), and a Cancel / Approve pair.

3. Central policy decisions

A small policy module (security/ActionPolicy) evaluates every tool call and returns one of:

  • Allow — execute as proposed.
  • RequireApproval — pause and ask the user.
  • Deny — block with a reason.

The decision considers the tool's risk, the active skill, the target app (if known), and a list of app-aware policy rules. Rules can lower or raise the risk for a specific combination (e.g. always require approval for any tool that targets a banking app).

4. Redaction

Sensitive argument values are redacted before they are written to the local audit log or shown in approval copy. The redactor covers:

  • Free-text fields that look like phone numbers, emails, credit card numbers, API keys, or passwords.
  • Argument keys named password, secret, token, api_key, private_key, credential, auth, otp, pin.

The redacted value is rendered as [REDACTED] in logs and approval cards, and the unredacted value is never persisted.

Permissions on your device

TouchPilot only requests the Android permissions it actually needs:

Permission Why
BIND_ACCESSIBILITY_SERVICE The agent's primary observation and control surface.
FOREGROUND_SERVICE The agent posts a persistent notification while it is running.
POST_NOTIFICATIONS Required on Android 13+ to surface the foreground service notification.
INTERNET Optional. Only used if you configure an OpenAI-compatible cloud fallback.
QUERY_ALL_PACKAGES Lets open_app resolve a friendly app name to a package without you typing the package id.

TouchPilot does not request:

  • READ_SMS, RECEIVE_SMS, SEND_SMS — no message interception.
  • READ_CONTACTS — no contact scraping.
  • READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE — no file access outside its own sandbox.
  • CAMERA, RECORD_AUDIO — no microphone or camera access.
  • READ_PHONE_STATE — no call log or IMEI access.
  • SYSTEM_ALERT_WINDOW — no overlay drawing.

If you have a feature request that would need additional permissions, please open a Feature request that explains the user workflow and the safety review you have considered.

What TouchPilot does not do (today)

These are intentional non-goals for the 1.0 release:

  • No broad unsupervised control of a user's main phone.
  • No hidden background automation.
  • No banking, purchasing, password, or account-recovery workflows.
  • No dependency on a local GPT-class model for the first usable version.
  • No attempt to replicate every OpenClaw channel or plugin at launch.

See Vision for the longer-horizon direction.

Reporting a safety issue

If you find a way to bypass one of these layers — a missing redaction, a missing approval prompt, a privilege escalation — please report it privately to the maintainers rather than opening a public issue. See Security policy for the disclosure process.