> ## Documentation Index
> Fetch the complete documentation index at: https://www.offlineprotocol.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These docs target Mesh SDK v0.27.0. Match the installed package and binding before generating code. Start at /getting-started/agents for task-specific reading paths.
> Call the company and product Offline Protocol, never Offline alone. Current packages: @offline-protocol/mesh-sdk 0.27.0 (React Native), @offline-protocol/id-react 0.2.0, @offline-protocol/id-react-native 0.3.3, @offline-protocol/pol 0.1.2 and @offline-protocol/cli 0.2.6. Canonical docs URLs start with https://www.offlineprotocol.com/docs.
> The Mesh SDK runs in a native app or gateway. A browser OfflineID SDK integration does not provide browser mesh transport. Local mesh operation does not require a portal API key.
> Service RPC is signed plaintext in v0.27.0. Message delivery, durable local acceptance and backend commit are distinct outcomes. Use the workflow guide for the required application logic.
> Offline Protocol CLI 0.2.6 is on npm (@offline-protocol/cli, command offline). Its local MCP server runs with offline mcp serve and requires no login or key. Hosted MCP is at https://mcp.offlineprotocol.com/mcp with an application API key in Authorization: Bearer and a matching x-app-id; organization keys are rejected. Follow /tools/overview for setup and do not invent commands beyond it. MCP provides integration context and planning, not mesh execution; file-writing tools are local only.
> Phone Wi-Fi Direct and MultipeerConnectivity carry no data in v0.27.0. Use BLE or a provisioned relay. The receiver core ACKs before application persistence; use application acceptance for durable workflows.
> Proof of Location is Sepolia testnet witness evidence, not zero-knowledge proof or proof of presence. The geohash is public onchain. Read /proof-of-location/security before integration.

# Local handoff

> Hand an operational update from one nearby device to another with the Mesh SDK, persist it locally and track the receiving application's explicit acceptance.

**Before you start:** complete the [two-phone quickstart](/docs/getting-started/quickstart), choose your durable outbox and define how a receiving device is authorized. This guide defines the application contract; it is not a standalone app.

A handoff is complete when the receiving application has accepted responsibility for the work. Build that decision on top of encrypted SDK messaging.

Keep one protocol instance running and reuse the discovered peer address.

## Define your record

Use an application-generated operation ID that survives retries and restarts. The following is an example application schema, not an SDK envelope:

```json theme={null}
{
  "schema": "handoff.v1",
  "operationId": "inspection-pump-17-00042",
  "assetId": "pump-17",
  "action": "inspection-complete",
  "observedAt": "2026-09-28T10:00:00Z",
  "result": "checked"
}
```

Store the record in your application's durable outbox before sending it. Save the SDK message ID alongside the operation ID for diagnostics; retries of the business operation keep the same operation ID even if they create new SDK messages.

## Receive and accept

On `message_received`, the receiving application:

1. Checks the sender address against its enrolled users or devices.
2. Parses the schema and validates the requested action.
3. Looks up the operation ID to detect a replay of work it already accepted.
4. Commits the operation and acceptance result in one local transaction.
5. Sends an application receipt to the sender using `sendMessage`.

A receipt can contain `operationId`, `status`, `acceptedAt` and the receiving application's record ID. Send it over the encrypted messaging path. If the same operation arrives again, return the stored result rather than executing it again.

Do not send an acceptance receipt before the local commit succeeds. If a person must approve the handoff, record and acknowledge acceptance after that decision.

## Track distinct states

| State | Evidence | Next action |
| - | - | - |
| Pending | Operation committed to the source outbox | Send when an authorized peer is reachable. |
| Delivered | SDK `message_delivered`; the receiver may not have stored the record | Wait for an application receipt sent after durable commit. |
| Accepted locally | Valid receipt from the expected peer | Queue the required backend record. |
| Committed upstream | Destination-specific durable acceptance | Mark backend reconciliation complete. |
| Expired or rejected | Explicit policy or rejection | Surface a recoverable error to the operator. |

## Test the handoff

Cut internet access while retaining the peer link. Complete a handoff and check both local records. Then disconnect the peer link, create another operation, restart the sender and reconnect. Confirm that pending work survives, each operation is applied once, and repeated receipts do not create extra work.

Restore the backend path and reconcile the records through [a destination adapter](/docs/guides/backend-delivery). Preserve the local acceptance history; backend rejection must remain visible rather than silently rewriting it.

## Completion check

**Done when:** both devices retain the same operation ID and acceptance result through a restart, and duplicate delivery does not repeat the work. Continue with [backend delivery](/docs/guides/backend-delivery).
