OpenPhone exposes the phone as a runtime endpoint. A runtime can be local
(Phone) or remote (OpenClaw, future Hermes, MCP clients, CLI tools).
Android owns the screen/action surface, session records, and user confirmation
boundary; remote runtimes own agent reasoning.
- A phone surface creates an attention request: chat, volume voice, Dynamic Island, watcher, job, or notification.
RuntimeManagercreates a phone execution session and sends the request to the selectedRuntimeAdapter.- The adapter maps the generic request to the runtime's wire protocol.
- The runtime may answer directly or request phone tools.
RuntimeToolBridgevalidates the command, applies autonomy policy, creates confirmations for mutating actions, runs the phone tool, and returns the result.
- Runtime: an agent backend selected by the user.
- Surface: the phone source that initiated a request.
- Phone session: durable Android-owned execution state.
- Runtime session: backend-owned session/thread/run key.
- Attention request: phone-to-runtime user request.
- Tool request: runtime-to-phone inspect/action request.
- Confirmation: Android-local approval for risky actions.
observe_only: read-only tools may run; mutating tools are denied.ask_before_action: mutating tools require Android confirmation.trusted_actions: low/medium-risk mutating tools may run without OpenPhone confirmation, but high-risk tools and OS/app confirmations still require confirmation.
If a runtime tool call omits autonomy, OpenPhone inherits the phone execution
session's autonomy. If no session is available, it falls back to
ask_before_action.
- Commands:
runtime/protocol/openphone-commands.json - Events:
runtime/protocol/openphone-events.json - Capabilities:
runtime/protocol/openphone-capabilities.json - Shape reference:
runtime/protocol/openphone-runtime.schema.json
Every protocol manifest carries an integer version. Consumers load
manifests through runtime/protocol/openphone-runtime-tools.mjs, which
accepts an inclusive supported range (RUNTIME_PROTOCOL_VERSION_RANGE,
currently min_version=1, max_version=1) instead of a single pinned
version, so new manifest versions can roll out without breaking older
clients.
Integrations advertise the supported runtime-protocol range in a structured way so clients can negotiate before invoking tools:
- MCP server: the
initializeresult'sserverInfo.runtimeProtocolfield carries{ name, min_version, max_version }. (This is separate from the MCPprotocolVersiondate string, which versions the MCP transport itself.) - CLI:
openphone info --jsonprints the same structure underruntime_protocol.
- Additive, backward-compatible changes (new commands, new optional fields, new events/capabilities) do NOT bump the manifest version.
- Breaking changes (removing or renaming a command, changing a field's
meaning or required shape) require bumping the manifest
versionand raisingmax_versioninRUNTIME_PROTOCOL_VERSION_RANGE. Keepmin_versionunchanged while old clients are still supported. - Raise
min_versiononly when support for an old manifest version is deliberately dropped; announce it in release notes first. - Instead of removing a command in place, mark it
deprecated: trueand point at its replacement withsuperseded_by: "<command>". The validator (runtime/protocol/validate-runtime-protocol.mjs, run byscripts/check.sh) enforces thatsuperseded_byreferences an existing command and is only set alongsidedeprecated: true. Deprecated commands must keep working for at least one released version before removal (which is the breaking change that bumps the manifest version).