Open Protocol · Apache 2.0

When an AI acts on
the physical world,
someone has to answer for it.

DoSync turns a goal into a plan your deployment's own rules can veto, and leaves a record that survives someone with root access. Runs in the building it serves — no cloud required.

56/56conformance, signed
900+automated tests
<100msintent to action
Apache 2.0open source

Existing protocols

lock.unlock()
light.set_brightness(100)
thermostat.set_temperature(21)
// hardcoded, per-device, per-scenario

DoSync

"there is an emergency at home"
"nobody is home — save energy"
"good morning"
// every device resolves its own role

Architecture

Five layers. One semantic bridge.

DoSync is a 5-layer protocol stack. Each layer has a single responsibility and doesn't need to know how the others work. Compatible with Home Assistant, Philips WiZ, Shelly, Matter, Zigbee, and any WiFi device.

Layer 5

Intent

AI expresses semantic goals

Layer 4

Semantic

Resolver maps intent → device actions

Layer 3

Registry

Devices self-declare capabilities on join

Layer 2

Security

mTLS, local PKI — no internet required

Layer 1

Transport

WiFi · BLE · Zigbee · Z-Wave · Thread

Demo

From natural language to physical action.

A conversation with Claude AI triggers a physical emergency protocol in real time — 10 Philips WiZ bulbs, SMS notification, audit log. No commands. No rules. No cloud.

user → "there is an emergency at home"
# DoSync hub receives intent
# ensure_safety [emergency]
light-zone3-01 turn_on brightness=100
light-zone3-02 turn_on brightness=100
light-zone4-01 turn_on brightness=100
alarm-01 alarm pattern=emergency
notifier-01 notify → +1555012...
# 18 actions · 8 devices · 79ms
# audit log updated · SHA-256 chain intact
Watch the demo — 2 min

Raspberry Pi 5 running the hub autonomously · 10 Philips WiZ bulbs via UDP · SMS via Twilio · zero internet dependency

Milestone · June 2026

An AI gave one sentence.
A drone flew the whole mission.

DoSync was built domain-agnostic — nothing in it assumes a house. The proof: we took it to the hardest device, an autonomous drone. Then an AI model, from a single sentence in plain language, fired the intent and the drone flew the entire mission — every step confirmed by real telemetry, validated against ArduPilot SITL.

Human → AI

A sentence

“inspect the perimeter of this area”

AI → Intent

inspect_area

model builds the context and fires it

DoSync → Drone

Mission

take_off → 4× go_to → return_home → land

Path A — verified first

Intent fired by API

The full mission flown by posting the semantic intent to the hub. Proves the closed loop: command, telemetry, confirmed arrival at every step.

Path B — the real goal

Intent fired by an AI model

A model (Claude Haiku, via DoSync's native MCP server) read the goal in plain language, chose inspect_area, built the context, and fired it. The AI decided to act — the whole point of the protocol.

An AI model receives a plain-language instruction and fires the inspect_area intent
1 · The AI commands. A sentence in plain language → the model fires inspect_area with the center, radius and altitude it inferred.
DoSync hub log showing each waypoint command followed by a telemetry-confirmed arrival
2 · The hub confirms. Every go_to accepted is followed by a telemetry-confirmed reached target — FINISHED. Acceptance ≠ completion.
ArduPilot SITL console: arm, takeoff, climb, RTL, land, disarm
3 · The drone flies. ArduPilot SITL: ARM → NAV_TAKEOFF → height 25 → RTL → land → DISARMED. A complete autonomous mission.

When the AI guessed wrong, the system caught it.

On the first attempt — with no coordinates given — the model filled the gap with a plausible guess 11,000 km away from the drone. The supervisor did not fake success: it waited for a confirmed arrival, none came, and it aborted the mission with a clear diagnosis. The AI can be wrong. The protocol does not have to be.

Validated in ArduPilot SITL · physical-hardware flight is the next step, not a claim made today.

How it executes

From intent to action in 79ms.

Press the button and watch every layer of the protocol execute in sequence — resolver, policy engine, adapters, audit log. Real times from the production deployment.

Intent fired
intent: "ensure_safety"
urgency: emergency
source: claude_mcp
79ms
total latency
8
devices acted
18
actions fired
0
rules written

Quick start

Up and running in one command.

No hardware required. The hub starts with authentication on, an audit chain running, and a device scan that searches WiFi and Bluetooth without any configuration.

1 Install
$ pipx install dosync
# or: pip install dosync
2 Start the hub
$ dosync-hub
# auth on, audit chain running
3 Open the dashboard
open http://localhost:47200
# hub · devices · audit log

Discovery

It finds what's there — over WiFi and over radio.

Press Scan and the hub asks every transport it can search. Bluetooth included, with nothing extra to install.

GET /v1/discovery/scan
{
  "searched": ["wiz (udp broadcast)", "ble"],
  "not_searchable": ["homeassistant", "mqtt"],
  "found": [ ... ]
}

Scanning registers nothing. It lists candidates; you choose which become devices and what they are called. In a protocol built around being able to account for what is in it, devices appearing because they answered a broadcast — approved by nobody — would contradict the premise.

The scan reports which transports it searched and which it could not, because "found nothing" means something different when Bluetooth was never scanned.

Bluetooth works out of the box because the library that finds BLE devices is a core dependency — discovery is how you learn what you have, and a library you can only install after knowing you need it is a circle.

Extensibility

Your device probably isn't in our list.

Describe it in a file, publish it as a package, or implement one method. Three ways in, and only one of them needs code.

my_adapter.py
class MyBrandAdapter(DoSyncAdapter):

  async def execute(self, action, urgency):
    # translate DoSync action to your device
    await self.device.send(action.action, action.params)
    return ActionResult(success=True)

  @property
  def adapter_name(self):
    return "mybrand"

# register once — hub uses it automatically
executor.register(MyBrandAdapter())

Available today

homeassistant · matter · mqtt · ble · mavlink · wiz · shelly · declarative · gpio

The adapter contract

One method: execute(action, urgency). The hub handles routing, audit logging, policy evaluation, and state tracking. Your adapter only speaks to the device.

Optional: state querying

Implement get_state(device_id) to participate in the background state refresher — the hub polls your device every 60s and skips redundant actions automatically.

No code at all: describe it in a file.

Most of what a hub needs to reach a device is not interesting code — "send this request, read this field". Requiring Python for that made "domain-agnostic" mean "agnostic across the domains we already wrote".

hallway-light.yaml
device:
  id: light-hallway
  tags: [light, energy]        # how intents find it
  emergency_capable: true      # may an emergency use it

transport:
  kind: http                   # http or mqtt
  base_url: http://192.168.1.40

actions:
  turn_on:
    type: turn_on              # what it MEANS
    request: { method: POST, path: /light/on }

The type on each action is the part that matters. A file that only said "POST /on turns it on" would let DoSync switch the device and leave it invisible to everything else: no intent could select it, no policy could name it, an emergency would pass it by.

Six worked examples ship with the package — a light, an air conditioner, a 3D printer, a television, a building's lighting controller and an industrial conveyor over MQTT. Run dosync-manage examples and edit the one closest to your device.

What it cannot do, stated plainly: it speaks HTTP and MQTT. Not Zigbee, not Z-Wave, not BLE pairing, not an OPC-UA session — those need a code adapter. It covers most simple devices and almost no complex ones.

If you make devices, you don't need us to add them.

Publish a package, your customer runs pip install, and the hub finds it. No pull request here, no waiting on one person's agenda — and no promise from this project to maintain code for hardware it has never seen. You answer for your own adapter.

pyproject.toml
[project.entry-points."dosync.adapters"]
mybrand = "dosync_adapter_mybrand:MyBrandAdapter"

DoSync does not download adapter code from a remote source, and will not. The whole argument of this protocol is that nothing actuates hardware without passing a policy and leaving a record; fetching executable code from the internet would put the largest possible hole exactly where the guarantee lives. An entry point differs in the two ways that matter: someone chose to install it, and someone's name is on it.

Such an adapter runs inside the hub with the hub's permissions, so the hub says so: logged on load, recorded in the audit chain, and reported as third_party regardless of what the plugin claims about itself.

Use cases

Not just for the home.

The same 5-layer stack works anywhere an AI needs to coordinate physical systems.

🏠

Smart home

Emergencies, routines, energy efficiency — orchestrated by intent, not rules.

🛒

Retail store

Cold chain failure at 3am → manager notified, sector locked, maintenance dispatched — before products are lost.

🏨

Hotel

"Guest in 412 has arrived" → room configured to saved preferences, no configuration needed.

🏭

Factory

"Line B failure" → notifications, access control, tamper-evident audit trail — coordinated alongside the line's own safety systems.

What we found in our own claims

We audited the five properties we advertise.
Two of them were false.

In July we checked each claim against the code instead of against the README. Two did not hold.

"The AI cannot route around your policies."

POST /v1/device/action called the executor directly — no policy evaluation, no audit entry. The MCP tool used that path, so the bypass belonged to the AI rather than to an operator: a lock could be opened with nothing recorded. Closed 25 July. Direct actions are now evaluated under a reserved intent class and always audited.

"The audit chain is tamper-evident."

It detected a modified entry. It did not detect a truncated chain or a wholesale rewrite — someone with database access could remove the last hour, or rebuild the history, and verification would still pass. Now three layers: sequence numbers, a head mark in a separate table, and Ed25519-signed checkpoints stored off the hub — the only layer that catches a full rewrite.

The threat model states what each layer detects and what it does not — including the rows that read not detected, each with the test that demonstrates it.

Nothing here is claimed to be unbreakable. A protocol whose value is honesty cannot make absolute security claims and stay coherent.

Certification

Self-certify your device in minutes.

Three tiers, self-certifiable with the CLI. No manual approval required for Basic and Standard.

Basic

DoSync Basic

Layers 1–3: connectivity, authentication, capability manifest.

  • Connects and authenticates
  • Publishes capability manifest
  • Appears in device registry
Emergency

DoSync Emergency

All layers + emergency override + tamper-evident audit log.

  • Emergency override without confirmation
  • SHA-256 chained audit log
  • mTLS per-device authentication
$ python3 certify.py --host <device-ip> --port 47200 --tier emergency
# generates dosync-cert.json — signed certification report

Project status

Honest about where we are.

Reference implementation. Apache 2.0. One person building it. Here's what's real today.

DoneREST API · WebSocket · Dashboard
DoneCertification — 56/56 conformance, signed, against a real deployment
DonePhilips WiZ adapter (UDP local)
DoneHome Assistant bridge (10 domains)
DoneNative MCP server (Claude, any LLM)
DoneLocal PKI + mTLS per-device auth
DoneRaspberry Pi 5 — autonomous 24/7
Donedosync-node — Node.js implementation (Standard 33/33 against the v0.3 suite; re-validation against the current 56-test suite pending)
DoneMulti-hub assisted failover
DoneEmergency preemption — device-finality guaranteed (v0.4)
DonePrometheus /metrics — zero-dep observability
In progressDistributed state replication
DoneBLE adapter — controls and discovers over Bluetooth radio
DoneDeclarative adapters — describe a device in YAML/JSON, no code (HTTP, MQTT)
DoneThird-party adapters via Python entry points
DoneSigned heartbeats for hardware that cannot do TLS
DoneDevice discovery over WiFi and Bluetooth, out of the box
Donepip install dosync — 0.6.3 on PyPI
PlannedThird-party device certifications

Roadmap

Q2 2026 ✓ Shipped: idempotency + delivery semantics · multi-hub assisted failover · protocol v0.4
Q3 2026 — now 0.6.3 shipped: discovery over WiFi, Bluetooth, mDNS and SSDP · a drafted adapter checked against the device before it is trusted · what a device announced about itself kept on its manifest · declarative adapters · third-party entry points · signed heartbeats · three-layer audit integrity · every simulated action declared as such. IEEE WF-IoT 2026 — submitted and not accepted; the reviews said the architecture held and the evaluation did not, and the evaluation work was rebuilt around that. In progress: distributed state replication
Q4 2026 Second independent implementation · language-independent wire format · outreach to device manufacturers
2027+ FamilyOS integration · DoSync as native protocol in commercial devices

Works with Home Assistant

A layer on top of HA — not a replacement for it.

Home Assistant already solved the hardest problem in the smart home: talking to thousands of devices. DoSync doesn't reinvent that — it reads devices from HA through a bridge that's already in the repo, and adds a semantic, auditable coordination layer above them. HA is one source of devices; the intelligence stays in the connecting AI.

HA's MCP server exposes commands

Turn on this light, set that thermostat. The intelligence of what to do lives in an automation you wrote, or in the AI sending commands.

DoSync resolves intents

Express a goal — ensure_safety — and a resolver coordinates the right devices across any source, with a tamper-evident audit log of what acted and why.

When DoSync earns its place

When coordination and traceability both matter at once — a fall-response that unlocks the door, lights the house, and messages family, with an auditable record of exactly what fired.

When it doesn't

For everyday automation — "porch light when I get home" — you don't need DoSync. HA's automations and its MCP cover that completely. The extra layer is for the narrow set of cases that need auditable coordination.

Constrained hardware

Hardware that cannot do TLS still gets to report.

A sensor running a year on a coin cell cannot perform a TLS handshake — it costs more battery than a month of operation. It can still prove it is alive: POST /v1/heartbeat/signed accepts a heartbeat authenticated by HMAC over the device's own provisioning token.

Off by default, and worth knowing exactly what it trades. It provides message authenticity and replay resistance. It provides no confidentiality — device id, timestamp and report travel readable.

Devices on this channel are marked, because one reporting over an unencrypted channel is in a different position from one on mTLS, and the two must not look identical to an operator.

That trade is defensible for a heartbeat and would not be for an action: a heartbeat is positive signal only, so a forged one cannot switch anything on. The attack it invites is replay — repeating a captured message to keep a failed device reporting healthy, blinding failure detection exactly when it matters. That is closed: narrow clock window, single-use signatures.

Speaks MCP natively

What's the difference between MCP and DoSync?

They're not rivals — they're different layers, and one literally speaks the other. MCP (the Model Context Protocol) standardizes how an AI discovers and calls tools; DoSync is one of those tools — the one that turns a goal into coordinated, supervised, recorded physical action. DoSync ships as an MCP server, so every MCP-speaking AI is already a DoSync client. The AI thinks, MCP connects, DoSync acts with judgment.

MCP connects your AI to tools

One protocol instead of bespoke integrations: the model discovers what tools exist and invokes them. It moves the request and the result, faithfully, in both directions — transport isn't judgment, and that's not a flaw, it's the design.

DoSync turns goals into supervised action

One intent — ensure_safety — becomes a coordinated plan over declared capabilities, filtered by the operator's own standing rules, with a tamper-evident record of what was proposed, what the rules decided, and what actually ran.

Each makes the other worth more

Without something like DoSync, an MCP agent touching the physical world needs a tool per device per action and brings no judgment to it. Without MCP, DoSync would need a bespoke integration per model — instead, MCP gave it its entire front door for free.

When MCP alone is enough

For email, calendars, code, files, databases — MCP is complete, full stop. Even casual device commands don't need DoSync. The extra layer earns its place only when coordination, the operator's rules, and a trustworthy record matter at once.