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.