Node.js SDK
The Node.js SDK is for TypeScript or JavaScript device programs. The package uses @device-agent/device-sdk and BaseDevice to handle MQTT connection, command subscription, command responses, state reports, and event reports. Add real device behavior in src/device.ts.
Use Cases
- TypeScript/JavaScript is used for device-side, gateway, or edge services.
- The device needs an existing Node.js service, HTTP API, database, or business system.
- Claude Code, Cursor, or Codex will continue the device-side implementation.
Package Contents
| File | Purpose |
|---|---|
src/index.ts | Startup entry point that loads .env and creates the device instance |
src/device.ts | Device logic entry point that extends BaseDevice |
device-spec.json | Current DeviceSpec, used for command validation and state fields |
packages/device-sdk | Local copy of the device-side SDK with BaseDevice, voice, and vision clients |
AGENTS.md / CLAUDE.md | Context for local AI coding tools |
For a real device, you mainly work in src/device.ts: handle commands, call hardware or business services, update state, and report events.
Access Steps
- Download the Node.js SDK package.
- Copy
.env.exampleto.envand update MQTT broker or credentials if needed. - Install dependencies and start the program.
- Replace the default behavior in
src/device.tswith real device logic. - Return to the Device Agent workspace, confirm the device is online, and test a control command.
cp .env.example .env
npm install
npm run startImplement Device Logic
The device class in src/device.ts extends BaseDevice. After connection, it publishes a state snapshot. Commands enter handleCommand(). Call hardware interfaces or business services here:
protected override async handleCommand(command: DeviceCommandMessage) {
if (command.cmd === "set_temperature") {
const target = Number(command.params?.target_temperature);
await thermostatClient.setTargetTemperature(target);
this.patchState({ target_temperature: target });
await this.publishStateSnapshot();
return { code: 0, msg: "ok", data: { target_temperature: target } };
}
return { code: 404, msg: `Unknown command: ${command.cmd}` };
}BaseDevice handles MQTT connection, command subscription, response publishing, and state reporting. Keep command names, parameter names, and state fields aligned with device-spec.json.
After state changes, call publishStateSnapshot(). To report an event, use an event already defined in the DeviceSpec:
await this.sendEvent("temperature_alarm", {
current_temperature: 32.5,
level: "warning",
});Voice Access Code
VoiceClient in the Node.js SDK is for device-side voice conversations. The device connects to /ws/voice, sends 16 kHz mono Int16LE PCM audio, and listens for ASR text, agent replies, and TTS audio events.
import { VoiceClient } from "@device-agent/device-sdk";
const voice = new VoiceClient({
wsUrl: "ws://127.0.0.1:3001/ws/voice",
deviceId: "device-001",
productId: "agent-001",
});
voice.on("agentReply", (text) => console.log(text));
await voice.connect();
voice.startListening("manual");
voice.sendAudio(pcmChunk);
voice.stopListening();packages/device-sdk/examples/voice-chat.ts is the complete example. For a real device, connect microphone capture and speaker playback to sendAudio() and TTS events.
Vision Recognition Code
The Node.js toolkit derives /api/vision/frames and /api/chat from VOICE_CHAT_HOST. When the DeviceSpec contains one of these commands, src/device.ts runs the photo recognition flow:
capture_and_recognizetake_photo_visionvision_recognizephoto_identify
The default flow checks imageDataUrl and imageBase64 in command parameters, then VISION_FALLBACK_IMAGE_DATA_URL in .env. For a real device, override captureLocalVisionImage() to read one image from a camera, screenshot, or image file.
protected override async captureLocalVisionImage() {
return {
mimeType: "image/jpeg",
imageBase64: await readCameraFrameAsBase64(),
source: "sdk-camera",
};
}The device uploads the image, calls /api/chat with visionRefs, and returns the recognition result as the command response. This is command-triggered single-frame recognition, not continuous video streaming.
Continue with a Local AI Coding Tool
Node.js packages include AGENTS.md, CLAUDE.md, and device implementation guidance. Open the package folder in Claude Code, Cursor, or Codex and ask it to continue src/device.ts based on device-spec.json.
Verify Access
After the program starts, return to the Device Agent workspace and confirm:
- The device appears in the device list and is online.
- Current state shows fields reported by the Node.js program.
- A conversation command executes the logic in
handleCommand(). - If
sendEvent()is called, the event appears in recent events.