Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.meshagent.com/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The SyncClient is the Room API for live shared documents (MeshDocuments). Use it when multiple humans or agents need to read and edit the same structured document in real time.

CLI commands

Start with the CLI help, then use a few common commands:
bash
meshagent room sync --help
meshagent room sync create --room myroom docs/briefing.mesh --schema ./briefing.schema.json
meshagent room sync show --room myroom docs/briefing.mesh
meshagent room sync inspect --room myroom docs/briefing.mesh

Why use the Sync API?

  • Keep shared state in a live document instead of relying only on chat history.
  • Let multiple participants collaborate on the same structured content at once.
  • Define document schemas that help users and agents write valid data.

How it works

You create or open a document by path. Opening a document starts a live synchronization session so local changes propagate to other participants in the room. The Python SDK also exposes describe when you want the current JSON state without opening a sync session, and sync is available when you already have encoded changes to send. For the Python, JavaScript, TypeScript, and .NET standalone room examples on this page, start the script through meshagent room connect --room={ROOM_NAME} --identity={AGENT_NAME} -- <command> so MeshAgent injects the room connection environment automatically. For example: meshagent room connect --room=my-room --identity=participant-name -- python3 documents-writing.py. The Dart sample still shows the explicit protocol factory flow.

Permissions and grants

The Sync API is controlled by the sync grant on the participant token. In practice, sync grants are path-based and can be marked read-only. That lets you give a participant access to specific document paths without opening the entire sync surface. See API Scopes and Service YAML.

Defining Your Document Structure

To define the structure of a MeshDocument, you start by creating a schema using the MeshSchema class. A schema:
  • Documents the structure of your MeshDocument for anyone in your organization.
  • Ensures agents and users don’t write invalid data to the document.
  • Allows agents to automatically generate, manipulate, and validate structured documents.
  • Automatically generates LLM-compatible schemas for structured outputs.
  • Synchronizes documents across all platforms that MeshAgent supports.
Similar to how a web page is structured, a MeshSchema begins with a root element that includes an allowed tag name and optional attributes. Afterward, you can define additional tags, their attributes, and the types of child nodes they can contain.

Example Schema

Suppose you have a basic web page structure and want to define a schema for it.
from meshagent.api.schema import MeshSchema, ElementType, ChildProperty, ValueProperty

schema = MeshSchema(
    root_tag_name="html",
    elements=[
        ElementType(
            tag_name="html",
            properties=[
                # a ChildProperty describes the type of children that
                # an element allows. There can be at most one child
                # property for each element type, but the child property
                # can allow multiple types of child elements.
                ChildProperty(name="children", child_tag_names=["body"])
            ],
        ),
        ElementType(
            tag_name="body",
            properties=[
                # Our body can only contain paragraph elements
                ChildProperty(name="children", child_tag_names=["p"])
            ],
        ),
        ElementType(
            tag_name="p",
            properties=[
                # A ValueProperty property describes an attribute that
                # contains a single value
                ValueProperty(name="class", type="string"),
            ],
        ),
    ],
)

Many LLMs (such as OpenAI) and agent frameworks (such as MeshAgent) support JSON Schemas for defining inputs and outputs. Generating an OpenAI-compatible JSON schema from your MeshSchema requires only one line of code:
json_schema = schema.to_json()

Creating a MeshDocument

To create a MeshDocument based on your schema and enable synchronization across different clients, use the MeshAgent runtime:
import asyncio
from meshagent.api import RoomClient


async def main():
    # Run with:
    # meshagent room connect --room=my-room --identity=participant-name -- python3 documents-writing.py
    path = "hello-world.document"

    async with RoomClient() as room:
        print(f"Connected to room: {room.room_name}")
        document = await room.sync.open(path=path, create=True)
        try:
            await document.synchronized
            document.root.append_child(
                tag_name="body", attributes={"text": "hello world!"}
            )
            await asyncio.sleep(1)
        finally:
            await room.sync.close(path=path)


asyncio.run(main())

API reference

Use the methods below to create documents, open live sync sessions, inspect the current document state, and send low-level sync operations when needed.

create(path, json=None)

meshagent room sync create \
  --room myroom \
  my/path \
  --schema ./schema.json \
  --json '{"key":"value"}'

  • Parameters:
    • path: Document path.
    • json: Optional initial JSON payload.
  • Description: Create a new MeshDocument at the given path. The server infers the schema from the document extension.

describe(path)

doc_json = await room.sync.describe(path="my/path")

  • Parameters:
    • path: Document path.
  • Returns: The current document root as JSON.
  • Description: Read the current state of a MeshDocument without opening a live sync session.
  • Availability: Python exposes room.sync.describe today. Other SDKs can use open() or a lower-level request until they add a helper.

open(path, create=True)

doc = await room.sync.open(path="my/path", create=True)

  • Parameters:
    • path: Document path.
    • create: When true, create the document if it does not already exist.
  • Returns: A MeshDocument tied to that path.
  • Description: Open a live synchronization session for the document. Local changes are sent automatically while the document remains open.

close(path)

await room.sync.close(path="my/path")

  • Parameters:
    • path: Document path.
  • Description: Close the local sync session for that document path. Once closed, local changes are no longer synchronized.

sync(path, data)

await room.sync.sync(path="my/path", data=b"some bytes")

  • Parameters:
    • path: Document path.
    • data: Serialized sync bytes.
  • Description: Send encoded sync data directly to the server. Use this when you already have the wire-format change payload.

Notes

  • Synchronized Changes
    Once a document is opened, any local changes you make in the associated MeshDocument are automatically queued for sending, thanks to sendChangesToBackend. You rarely need to call sync() manually unless you want to send raw data yourself.
  • Reference Counting
    The SyncClient internally tracks how many times a document is opened via the same path. Calling open multiple times for the same path returns the same underlying document. Only when all references are closed (via close()) will the client actually disconnect.
  • Error Handling
    If a request fails, the RoomClient may throw an error (like RoomServerException). Wrap calls in try/catch (or use .catch(...)) to handle them gracefully.
  • Concurrency and Performance
    • For high throughput, ensure that your RoomClient and server are configured for concurrent operations.
    • The SyncClient uses a StreamController internally to manage queued updates, sending them asynchronously to the server.