---
title: Migrating from raw Meta DAT
description: Move an app you already built against Meta's Device Access Toolkit onto the Extentos SDK — a call-site swap, not a rewrite, because Extentos calls the same DAT underneath.
type: guide
platform: all
vendor: meta
related:
  - /docs/concepts/vs-meta-dat
  - /docs/getting-started/with-agent
  - /docs/vendors/meta
  - /docs/reference/errors
---

If you already built your app directly against Meta's [Device Access Toolkit](/docs/vendors/meta) (DAT / the Wearables SDK), adopting Extentos is a **call-site swap, not a rewrite** — Extentos's production transport calls the *same* DAT under the hood, so every DAT concept you use has a one-to-one Extentos primitive. This guide maps your DAT symbols to their Extentos replacements and gives the order to do the swap in.

For the conceptual "Extentos vs raw DAT" comparison — what each layer owns and when going direct to DAT is still the right call — see [Extentos vs Meta DAT](/docs/concepts/vs-meta-dat). This page is the practical migration.

<Callout type="warn">
**This is a full cutover, not a side-by-side path.** Running raw DAT and the Extentos SDK in the same process at once is not supported today: the Meta `DeviceSession` is a single-owner handle and there is no public accessor to the DAT session underneath Extentos yet. Migrate an app fully, or keep it on raw DAT — incremental / side-by-side adoption is a roadmap item, not a current capability.
</Callout>

## Do it with the agent

The fastest path is to let your coding agent drive it. The `getMigrationGuide` MCP tool returns this same mapping as structured data plus an ordered plan, and most entries name an Extentos `feature` so the agent can drill into `getCapabilityGuide(feature)` for the exact Kotlin/Swift idiom and `getCodeExample(pattern)` for a full composition to peel from.

```
getMigrationGuide({ from: "meta_dat" })
```

## The order to migrate in

1. **Scaffold the bootstrap.** Run `generateConnectionModule`. It replaces `Wearables.initialize` / `Wearables.configure` **and** your hand-rolled registration/pairing UI — pick where `ExtentosConnectionPage` lives when prompted.
2. **Derive permissions.** Run `getPermissions` with your capability list, apply the emitted manifest / `Info.plist` entries, then delete the ones you maintained by hand.
3. **Swap call sites,** area by area, using the table below. Drill into `getCapabilityGuide(feature)` for each.
4. **Convert error handling** from `try`/`catch` / `runCatching` to [`ExtentosResult`](/docs/reference/errors) pattern-matching.
5. **Validate and dogfood.** Run `validateIntegration`, then `createSimulatorSession` — you can prove the whole cutover in the browser simulator before pairing glasses.

## The mapping

Each row is keyed by the raw DAT symbol you have today. `Feature` is the name to pass to `getCapabilityGuide` for the call-shape.

| Area | Your raw DAT | Extentos | Feature |
|---|---|---|---|
| SDK init | `Wearables.initialize` / `Wearables.configure()` | `ExtentosGlasses.create(...)` / `Extentos.create(config:)` (via `generateConnectionModule`) | — |
| Registration / pairing UI | `Wearables.startRegistration` / `registrationState` / `handleUrl` | `ExtentosConnectionPage` + `glasses.connection.state` | `connection_state` |
| Device session lifecycle | `Wearables.createSession` / `DeviceSession` / `DeviceSessionState` | `glasses.connection` (Auto transport owns the session) | `connection_state` |
| Device discovery / identity | `Wearables.devices` / `Device` / `DeviceType` | `glasses.device.type` / `glasses.device.vendor` | — |
| Permissions & Meta scopes | `checkPermissionStatus` / `RequestPermissionContract` / manual manifest+plist | `getPermissions({ capabilities, platform })` | — |
| Camera — photo | `PhotoData` / `photoDataPublisher` | `glasses.camera.capturePhoto()` | `capture_photo` |
| Camera — frames | `Stream` / `addStream` / `removeStream` / `videoFramePublisher` | `glasses.camera.videoFrames(...)` | `video_frames` |
| Camera — video clip | Stream video capture / `VideoQuality` | `glasses.camera.captureVideo(...)` | `capture_video` |
| Audio — raw mic | HFP/SCO + `AudioRecord` (hand-wired) | `glasses.audio.audioChunks(...)` | `audio_chunks` |
| Audio — transcription & wake | `SpeechRecognizer` / `SFSpeechRecognizer` over BT (hand-wired) | `glasses.audio.transcriptions()` + `glasses.voice.onPhrase` | `transcription_incremental` |
| Audio — TTS | `TextToSpeech` / `AVSpeechSynthesizer` + route handling | `glasses.audio.speak()` / `cancelSpeak()` | `speak` |
| Display (Ray-Ban Display) | `Display` / `addDisplay` / `DisplayConfiguration` | `glasses.display.show { }` / `clear()` / `isAvailable` | `display` |
| Voice-AI loop (if hand-wired) | your own wake → STT → LLM → TTS | `glasses.assistant.start(provider) { tool(...) }` | `assistant_runtime` |
| Error handling | raw exceptions / `CaptureError` / `StreamError` | `ExtentosResult<T, E>` — pattern-match | — |

## What you stop maintaining

The value of the cutover is the fragile, per-app plumbing you get to delete:

- **The wake-phrase path** — DAT never recognized phrases; you streamed the mic to a phone recognizer and matched strings yourself. That becomes a subscription.
- **SCO/HFP mic routing + A2DP playback coexistence** — the SDK owns the audio-route policy.
- **Permission derivation** — one capability list drives the manifest, `Info.plist`, and Meta scopes.
- **Publisher/stream lifecycle** — `addStream`/`removeStream`/`DeviceSession` ownership is internal; you consume typed primitives.
- **The test harness** — you gain the browser simulator and the agent-driven end-to-end loop with no glasses paired.

## Notes

- Extentos handler code is **vendor-agnostic** — the SDK is built for multiple vendors, with Meta supported today. Migrating off raw DAT also moves you off Meta-only wiring.
- Keep the parts DAT does that Extentos doesn't surface yet on raw DAT; see [when to use DAT directly](/docs/concepts/vs-meta-dat#when-to-use-meta-dat-directly). If you hit a missing primitive, [tell us](mailto:hello@extentos.com) so it gets surfaced.
