ECHO by DXOS

The data model for apps and agents

A typed object graph on the device. Plugins code against it, agents keep their memory in it and read its schema, and data from other systems meets in it. Writes land before the call returns, and peers merge when they connect.

pnpm add @dxos/echo
task.ts
import * as Schema from 'effect/Schema';
import { DXN, Filter, Obj, Query, Type } from '@dxos/echo';
class Task extends Type.makeObject<Task>(
DXN.make('com.example.type.task', '0.1.0'),
)(Schema.Struct({ title: Schema.String, done: Schema.Boolean })) {}
const open = db.query(Query.select(Filter.type(Task, { done: false })));
open.subscribe(() => console.log(open.results.length));
// The subscriber has already run when `add` returns.
const task = db.add(Obj.make(Task, { title: 'Ship the docs', done: false }));
// A CRDT change: it merges with any peer's edit to this task.
Obj.update(task, (task) => {
task.done = true;
});
Why it exists

One graph for apps, agents and external data

Memory for agents

An agent saves what it learned as ordinary objects, linked to the work they describe and found again with the same query an application uses.

A schema you can read at run time

Every type reports its name and version and converts to JSON Schema, so an agent can see what a space holds, and add a type, while it runs.

One graph for external data

Records synced from other systems become objects with foreign keys. A Ref can link a GitHub issue to a Linear task or a note.

The model plugins code against

A plugin declares its types and reads and writes objects. Its UI, its operations and its agents all share them.

What it guarantees

Behavior you can rely on

A write is visible before the call returns

A query over your local objects reflects db.add and Obj.update, and has told its subscribers, by the time the call returns.

org.dxos.echo.query#F-2
A remote answer is evidence, not truth

The index and EDGE can lag this tab. ECHO checks each remote entry against local state and drops what local state contradicts.

org.dxos.echo.query#F-5
One declaration is the schema and the type

A class built with Type.makeObject is both the runtime schema and the TypeScript instance type. There is no second definition to keep in sync.

org.dxos.echo#F-2
A reference is data, resolved when you ask

A Ref field stores a DXN and loads its target lazily. A missing target is a typed error you can catch by tag.

org.dxos.echo#F-4
Live

Two peers, one space

Collaborative editor

The document is one ECHO object, and its text is a CRDT. Alice and Bob each hold a full replica of the space, so each types into their own copy and sees the other’s edits and cursor as they sync. Switch a peer offline and keep typing on both sides: each replica keeps working, and when the peer comes back the edits merge without a conflict to resolve. The diagram is a mermaid block in the same text, so it merges like any other line.

Loading live demo…

Table and board

The space holds one set of companies. The table and the board are two views over the same query, not two copies of the data, and the board groups the companies by status. Drag a card to another column on Bob’s board and the company’s status changes, so its row in Alice’s table changes too.

Loading live demo…

Graph explorer

The graph is a saved query over the companies and the people who work at them. Each node is an object, and each edge is a reference from a person to their company. Hover a node to see the object behind it. The graph follows the query as objects change, so a company added on either peer appears in it.

Loading live demo…

Infinite canvas

The diagram is Composer’s architecture as nested drawings: a box with a level beneath it references another drawing. The drawings are ECHO objects in the same space as the other demos, so they sync, merge and work offline like the document and the table. Open a box to follow the reference down a level.

Loading live demo…
Architecture

How the packages fit

The @dxos packages in your process, echo-react, echo and echo-client, reach echo-host, index-core and EDGE through QueryService.