• 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
10
docs
1
reference
3
CLAUDE.md
README.md
auth.ts
cel.ts
dashboard.ts
H
main.ts
schema.ts
timers.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
/
reference
/
api.md
Code
/
reference
/
api.md
Search
2/25/2026
Viewing readonly version of main branch: v79
View latest version
api.md

agent-sync v5 API Reference

Base URL: https://sync.parc.land

Auth Model

Three token types:

  • Room token (room_...): returned on room creation. Full admin (* scope authority).
  • Agent token (as_...): returned on agent join. Own-scope authority + grants.
  • All mutations require Authorization: Bearer <token> header.

Rooms

POST /rooms

Create a room. Returns room token for admin access.

// Request { "id": "my-room", "meta": { "name": "My Room" } } // Response 201 { "id": "my-room", "created_at": "...", "meta": "{...}", "token": "room_..." }

GET /rooms

List rooms visible to the authenticated token.

GET /rooms/:id

Get room info.


Agents

POST /rooms/:id/agents

Join a room. Returns agent token.

// Request { "id": "agent-a", "name": "Alice", "role": "warrior" } // Response 201 { "id": "agent-a", "name": "Alice", "role": "warrior", "token": "as_...", "grants": "[]", ... }

Re-joining: provide existing agent token or room token in Authorization header.

GET /rooms/:id/agents

List all agents (public presence). Token hashes excluded.

POST /rooms/:id/agents/:agent-id/heartbeat

Update agent heartbeat and status.

{ "status": "active" }

PATCH /rooms/:id/agents/:agent-id

Requires room token. Update agent grants, role, name, meta.

// Grant _shared write access { "grants": ["_shared", "_messages"] }

State

State is the universal substrate. Everything is scoped key-value entries.

GET /rooms/:id/state

Read state entries. Respects scope privacy.

Query params:

  • scope — filter by scope (e.g. _shared, _messages, agent ID)
  • key — filter by specific key
  • after — only entries with sort_key > this value (for append scopes)
  • limit — max entries (default 100, max 500)
  • raw=true — don't parse JSON values
  • compact=true — strip null fields from response (removes timer_json, timer_expires_at, etc. when unused)

Scope privacy: Agents can only read _* system scopes, own scope, and granted scopes. Reading another agent's scope returns 403.

PUT /rooms/:id/state

Write a single state entry. Requires auth + scope authority.

// Mutable write { "scope": "_shared", "key": "phase", "value": "playing" } // Append write (auto sort_key) { "scope": "_messages", "append": true, "value": { "from": "alice", "body": "hello" } } // Merge (shallow update existing value) { "scope": "_tasks", "key": "42", "merge": { "claimed_by": "bob" } } // Increment { "scope": "_shared", "key": "turn", "increment": true, "value": 1 } // CAS (compare-and-swap via version) { "scope": "_shared", "key": "phase", "value": "done", "if_version": 3 } // CEL write gate { "scope": "_shared", "key": "winner", "value": "alice", "if": "state._shared.phase == \"playing\"" } // With timer { "scope": "_shared", "key": "bomb", "value": "ticking", "timer": { "ms": 30000, "effect": "delete" } } // With enabled expression { "scope": "_shared", "key": "secret", "value": "revealed", "enabled": "state._shared.phase == \"endgame\"" }

PUT /rooms/:id/state/batch

Batch write up to 20 entries atomically. Same auth rules.

{ "writes": [ { "scope": "_shared", "key": "phase", "value": "active" }, { "scope": "_shared", "key": "turn", "value": 1 } ], "if": "state._shared.phase == \"setup\"" }

DELETE /rooms/:id/state

Delete a state entry. Requires auth + scope authority.

{ "scope": "_shared", "key": "temp_data" }

PATCH /rooms/:id/state/timer

Renew a wall-clock timer.

{ "scope": "_shared", "key": "bomb" }

Actions

Actions are registered write operations. They carry the registrar's scope authority and define parameterized, predicated state mutations. Any authenticated agent can invoke them.

PUT /rooms/:id/actions

Register or update an action. Requires auth.

{ "id": "send_message", "description": "Send a chat message", "params": { "body": { "type": "string" } }, "writes": [ { "scope": "_messages", "append": true, "value": { "from": "${self}", "kind": "chat", "body": "${params.body}" } } ] }

Action fields:

  • id — unique within room (required)
  • scope — owner scope (default _shared). Scoped actions require auth as that agent.
  • description — human-readable
  • params — parameter schema with type and optional enum
  • writes — array of state mutations
  • if — CEL predicate gating execution
  • enabled — CEL expression gating visibility
  • timer — lifecycle timer
  • on_invoke.timer — cooldown timer applied after each invocation

Write entries support:

  • value — full replacement (with ${self}, ${params.x}, ${now} deep substitution)
  • merge — shallow merge into existing value (same substitution support)
  • increment — atomic increment
  • append — auto sort_key
  • expr: true — CEL-evaluated value
  • timer / enabled — per-write timers and conditions

GET /rooms/:id/actions

List all actions with availability.

Query params:

  • expand_params=true — for each enum param, evaluate availability per value

Response includes available: true/false based on the action's if predicate.

GET /rooms/:id/actions/:action-id

Get single action detail.

POST /rooms/:id/actions/:action-id/invoke

Invoke an action. Requires auth. Agent identity asserted.

{ "params": { "body": "hello world" } }

Returns executed writes and invocation log.

DELETE /rooms/:id/actions/:action-id

Delete an action. Scoped actions require matching identity or admin.


Views

Views are registered CEL expressions that project state into public, queryable results. A view registered by an agent can read that agent's private state — the result is public, the input is private.

PUT /rooms/:id/views

Register or update a view. Requires auth.

{ "id": "alice-health-status", "scope": "alice", "expr": "state[\"alice\"].health > 50 ? \"healthy\" : \"wounded\"", "description": "Alice's public health projection" }

View fields:

  • id — unique within room (required)
  • expr — CEL expression (required). Evaluated live on each query.
  • scope — owner scope. Determines read authority for the expression.
  • description — human-readable
  • enabled — CEL expression gating visibility
  • timer — lifecycle timer

GET /rooms/:id/views

List all views with resolved values.

GET /rooms/:id/views/:view-id

Get single view with resolved value.

DELETE /rooms/:id/views/:view-id

Delete a view. Scoped views require matching identity or admin.


Wait

GET /rooms/:id/wait

Block until a CEL condition becomes true.

Query params:

  • condition — CEL expression (required)
  • agent — agent ID for status tracking (defaults to auth identity)
  • timeout — max wait ms (default/max 25000)
  • include — comma-separated data to return: state, state._shared, agents, messages, actions, views
GET /rooms/my-room/wait?condition=state._shared.phase=="done"&include=state,actions

CEL Eval

POST /rooms/:id/eval

Evaluate a CEL expression for debugging.

{ "expr": "state._shared.phase == \"playing\" && messages.unread > 0" }

Scope Conventions

ScopeModePurpose
_sharedmutableCommunal game/room state
_messagesappendCommunication log
_tasksappendTask queue (user convention)
{agent-id}mutablePrivate agent state
User-definedeitherCustom scopes

Authority Model

IdentityDefault ScopeCan ReadCan Write
Room token*EverythingEverything
Agent (default)own scopeSystem scopes + own scopeOwn scope only
Agent (granted)own + grantsSystem scopes + own + grantsOwn scope + granted scopes
Unauthenticated—System scopes only (_*)Nothing
Via actionregistrar's—Action's defined writes

Unprivileged agents get 403 on direct writes to _shared. They must use actions.

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.