v1.0.0-dev
Meta Ray-Ban x Poke
A developer bridge that pipes live camera frames from Meta Ray-Ban smart glasses into Poke's automation engine for real-time vision analysis. Capture what you see and get instant AI descriptions of your surroundings.
How it works
Glasses ──capture──► Mobile App ──POST──► Poke Engine ──inferObject──► Vision LLM
(DAT SDK) (Android/iOS) (ingest trigger) (analysis)
│ │
◄──────────── response ──────────────────┘- 01Glasses capture a frame via the DAT SDK's
captureFrame(). - 02Mobile app base64-encodes the JPEG and POSTs to Poke's ingest endpoint.
- 03Poke runs the
meta_rayban_bridge.tsscript, passing the image to a vision model. - 04The LLM returns a scene description; Poke relays it back to the mobile app.
Getting started
Register at the Wearables Portal
Go to wearables.developer.meta.com and create an app. Select Device Access Toolkit (DAT) as the product.
Register your project and request permissions
In the DAT dashboard, register your Android package name or iOS Bundle ID and upload your signing certificate fingerprint. Then request these permissions:
| Permission | Why it is needed |
|---|---|
| wearable:streaming | Enables live media streaming from the glasses |
| wearable:camera | Capturing photos / frames on demand |
Enable Developer Mode on the glasses
Open the Meta AI app on your phone. Go to Glasses tab > your device > Developer Mode and toggle it ON. The glasses reboot and are ready for DAT connections.
Configure the Poke ingest endpoint
In your Poke project dashboard, create an Ingest trigger and set the entry point to the ingestHandler function from meta_rayban_bridge.ts. Generate an API key from Settings and note your ingest URL.
Mobile SDK integration
Example implementations for both platforms using the Meta Wearables DAT SDK. Full source files in mobile/.
Android (Kotlin)
val wearables = Wearables(context, WearablesConfig(
appId = "YOUR_APP_ID",
appSecret = "YOUR_APP_SECRET"
))
wearables.requestPermissions(
listOf(CAMERA, STREAMING),
onGranted = { /* permissions OK */ },
onDenied = { /* handle denial */ }
)
wearables.connect(SessionConfig(autoReconnect = true)) { session ->
val frame: ByteArray = session.captureFrame()
// Downscale and compress
val scaled = BitmapFactory.decodeByteArray(frame, 0, frame.size)
.let { Bitmap.createScaledBitmap(it, 1080, ..., true) }
val jpeg = ByteArrayOutputStream().apply {
scaled.compress(JPEG, 80, this)
}.toByteArray()
// POST to Poke
postToPoke(jpeg, prompt = "What am I looking at right now?")iOS (Swift)
let wearables = Wearables(config: WearablesConfig(
appId: "YOUR_APP_ID",
appSecret: "YOUR_APP_SECRET"
))
try await wearables.requestPermissions([.camera, .streaming])
let session = try await wearables.connect(
config: SessionConfig(autoReconnect: true)
)
let frame: Data = try await session.captureFrame()
let scaled = UIImage(data: frame)?
.jpegData(compressionQuality: 0.8)
let response = try await postToPoke(
imageData: scaled,
prompt: "What am I looking at right now?"
)Poke automation script
Runs on every ingest trigger. Decodes the image and asks a vision LLM to describe the scene. Deploy to your Poke project at poke/meta_rayban_bridge.ts.
export const ingestHandler = createServerFn({ method: "POST" })
.validator((d: unknown) => ingestSchema.parse(d))
.handler(async ({ data }) => {
const { image, prompt } = data
const imageBuffer = Buffer.from(image, "base64")
const result = await Agent.inferObject({
model: "claude-3-5-sonnet-v2@2025-04-15",
system: "Describe what they are looking at in 1-3 concise sentences.",
prompt: prompt,
attachments: [{ type: "image", data: imageBuffer, mediaType: "image/jpeg" }],
})
return { status: "ok", analysis: result.text, latency_ms: Date.now() - startTime }
})API & handshake protocol
The mobile app sends a POST to the Poke ingest endpoint. Full spec in docs/architecture.md.
Request payload
{
"image": "<base64-encoded JPEG>",
"prompt": "What am I looking at right now?",
"device_id": "abc123-def456",
"timestamp": "2026-07-13T10:30:00Z",
"meta": { "app_version": "1.0.0", "sdk_version": "0.5.0" }
}| Field | Type | Required | Description |
|---|---|---|---|
| image | string | yes | Base64-encoded JPEG (no data:image/...) |
| prompt | string | no | Override prompt. Default: "What am I looking at right now?" |
| device_id | string | yes | Unique identifier for the glasses or phone |
| timestamp | string | yes | ISO 8601 timestamp of capture |
| meta | object | no | Arbitrary metadata (app version, battery level, etc.) |
Response
{
"status": "ok",
"analysis": "You are looking at a wooden desk with a laptop, a coffee mug, and a succulent plant.",
"latency_ms": 1234
}Error codes
| Code | HTTP status | Description |
|---|---|---|
| invalid_api_key | 401 | Missing, expired, or malformed API key |
| payload_too_large | 413 | Request body exceeds 10 MB |
| invalid_image | 422 | Base64 decode failed or image is corrupted |
| rate_limited | 429 | Too many requests in a short window |
| server_error | 500 | Poke engine error (check script logs) |
Authentication
Authorization: Bearer pk_xxxxxxxxxxxxxxxx
Generate your API key in the Poke dashboard under Settings > API Keys. Store it in the platform keystore on mobile devices.