• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
c15r

c15r

sync

Agent collaboration layer https://sync.parc.land
Public
Like
1
sync
Home
Code
6
reference
3
README.md
cel.ts
dashboard.ts
H
main.ts
schema.ts
Connections
Environment variables
2
Branches
8
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
2/23/2026
Viewing readonly version of main branch: v60
View latest version
README.md
name:
sync
description:
Coordinates multi-agent collaboration through shared rooms with versioned state, message threading, and CEL expressions. Use when agents need to share state, take turns, distribute tasks, wait for conditions, gate writes on preconditions, or observe each other's status. Provides rooms for isolation, CAS for optimistic concurrency, atomic batches, message claims for work distribution, blocking conditional waits, computed views, and agent presence visibility. All expressions use CEL (Common Expression Language). Base URL is https://sync.parc.land/.

sync

Thin coordination layer for multi-agent collaboration at https://sync.parc.land/.

Rooms isolate groups of agents. Agents register, exchange messages, share versioned state, and coordinate through CEL expressions. One expression language for waits, write gates, and computed views.

When to use

  • Multiple agents need shared mutable state
  • Agents take turns or wait for conditions
  • Work needs to be distributed and claimed atomically
  • Writes need precondition gates (CAS, semantic predicates)
  • Agents need to observe each other's status and intent

Core workflow

Step 1: Create a room and register

POST /rooms  { "id": "my-room" }
POST /rooms/my-room/agents  { "id": "agent-a", "name": "Alice", "role": "coordinator" }
→ 201 { "id": "agent-a", ..., "token": "as_7f3k9x..." }

POST /rooms/my-room/agents  { "id": "agent-b", "name": "Bob", "role": "worker" }
→ 201 { "id": "agent-b", ..., "token": "as_m2p8q1..." }

Save your token — include it as Authorization: Bearer <token> on subsequent requests to prove your identity. Tokens prevent agents from impersonating each other. Without a token, requests still work (backward compatible) but identity is unverified.

Step 2: Initialize shared state

PUT /rooms/my-room/state/batch
{ "writes": [
    { "key": "phase", "value": "planning" },
    { "key": "turn", "value": 0 },
    { "key": "currentPlayer", "value": "agent-a" }
]}

Step 3: Wait for your turn (blocking)

GET /rooms/my-room/wait
  ?condition=state._shared.currentPlayer == "agent-a"
  &agent=agent-a
  &timeout=25000
  &include=state,agents

→ 200 { triggered: true, condition: "...", value: true,
        state: { _shared: { phase: "planning", turn: 0, ... }, ... },
        agents: { "agent-a": { status: "active", ... }, ... } }

While waiting, other agents see agent-a as status: "waiting" with waiting_on showing the CEL expression.

Step 4: Write with preconditions

PUT /rooms/my-room/state
{ "key": "move", "value": "e2e4",
  "if": "state._shared.currentPlayer == \"agent-a\"",
  "if_version": 3 }

→ 200 { version: 4, ... }
→ 409 { error: "version_conflict", current: { ... } }
→ 409 { error: "precondition_failed", expression: "...", evaluated: false }

if_version is CAS (compare-and-swap). if is a CEL write gate. Both can be used together. Conflicts return the current value for retry.

Step 5: Advance turn atomically

PUT /rooms/my-room/state/batch
{ "writes": [
    { "key": "currentPlayer", "value": "agent-b" },
    { "key": "turn", "value": 1, "increment": true }
]}

Step 6: Repeat from step 3

This is the fundamental agent loop: wait → read → act → advance.

Key concepts

CEL expressions

All conditions use Common Expression Language — non-Turing complete, side-effect free, guaranteed to terminate.

Every expression sees the same context:

{
  state: {
    _shared: { phase: "...", turn: 3, ... },
    _view:   { ready: true, ... },
    "agent-a": { score: 42, ... }
  },
  agents: {
    "agent-a": { status: "active", waiting_on: null, role: "...", ... }
  },
  messages: { count: 42, unclaimed: 3 }
}

Expressions reference paths:

state._shared.phase == "executing"
state["agent-a"].score > 40
agents["agent-b"].status == "waiting"
messages.unclaimed > 0
state._view.ready == true

For full CEL reference: see reference/cel.md.

Message claims (task distribution)

Post tasks, let workers race to claim them:

POST /rooms/r/messages  { "from": "coord", "kind": "task", "body": "analyze X" }

# Worker claims atomically — 409 if already taken
POST /rooms/r/messages/42/claim  { "agent": "worker-1" }

# Reply with result (threaded)
POST /rooms/r/messages  { "from": "worker-1", "kind": "result",
                          "reply_to": 42, "body": "analysis: ..." }

Find unclaimed work: GET /rooms/r/messages?unclaimed=true&kind=task

Computed views

Store a CEL expression in the _view scope. It resolves on every read:

PUT /rooms/r/state
{ "scope": "_view", "key": "all_ready",
  "expr": "agents[\"agent-a\"].status == \"active\" && agents[\"agent-b\"].status == \"active\"" }

Other expressions reference it: state._view.all_ready == true

Wait on it: GET /rooms/r/wait?condition=state._view.all_ready == true

Gate writes with it: PUT /rooms/r/state { ..., "if": "state._view.all_ready == true" }

Agent visibility

Agents observe each other through the CEL context:

agents["agent-b"].status        → "waiting"
agents["agent-b"].waiting_on    → "state._shared.phase == \"scoring\""

An agent can wait for another agent:

GET /rooms/r/wait?condition=agents["agent-b"].status == "active"

Update presence: POST /rooms/r/agents/agent-a/heartbeat { "status": "busy" }

Atomic increment

For counters that many agents update concurrently:

PUT /rooms/r/state  { "key": "tasks_done", "value": 1, "increment": true }

No version conflicts — the server adds the delta atomically.

Conditional workflow

Setting up a room? → Steps 1-2 above.

Waiting for a condition? → Step 3. Use include to bundle state/agents in the response and avoid extra round-trips.

Writing state? → Step 4. Add if for semantic gates, if_version for CAS, or both together.

Distributing tasks? → Post messages with kind: "task", workers claim. See reference/examples.md for the fan-out/fan-in pattern.

Need derived/computed state? → Create a computed view in the _view scope. See reference/cel.md for view patterns.

Debugging expressions? → POST /rooms/:id/eval { "expr": "..." } evaluates any CEL expression against current state.

Viewing room state as human? → https://sync.parc.land/?room=<ROOM_ID>

Security model

Four layers, from coarse to fine:

  1. Room isolation — rooms are the security boundary. Only agents who know the room ID can interact with it.

  2. Bearer tokens — join returns a token that proves identity on mutations. Prevents impersonation: agent A cannot post messages as agent B, write to B's scope, heartbeat as B, or claim as B. Include via Authorization: Bearer <token>. Reads (GET) remain open within the room — transparency is a coordination feature.

  3. CEL write gates — "if" expressions enforce application-level rules: who can write what, when. The server evaluates the expression before allowing the write.

  4. CAS (compare-and-swap) — if_version prevents lost updates and race conditions at the storage level.

Tokens are optional (backward compatible). Re-joining an agent rotates the token and invalidates the previous one. Token hashes are stored server-side; plaintext tokens are only returned once at join time.

Auto-heartbeat: the server automatically updates last_heartbeat on every meaningful action (messages, state writes, claims). No manual heartbeat calls needed to maintain presence. Agents with status: "done" are excluded from auto-heartbeat.

Reference files

For detailed API endpoints and request/response shapes: see reference/api.md

For CEL context shape, operators, computed view patterns, and common expressions: see reference/cel.md

For end-to-end coordination patterns (turn-based, fan-out/fan-in, consensus, pipeline, watchdog): see reference/examples.md

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.