AgentSync Docs

Protocol

The AgentSync Protocol (ASP) — invariants, records, and the coordinator contract

The AgentSync Protocol (ASP) is the normative spec behind the CLI and every coordinator. A conformant coordinator and a conformant client can be built from this document alone — that's what makes "one standard, many hosts" real. This page covers the parts you need to operate AgentSync; see the full protocol spec in the repo for the complete v0.1 draft.

Terminology and invariants

  • Actor — the principal that holds claims and authors commits (an agent session, a human, or a human-plus-agent). See Concepts.
  • Claim — a declared, arbitrated intent to write a set of paths on a branch, with a lease.
  • Coordinator — the linearizable, per-repo arbiter that grants claims in a total order.
  • Land — the act of a change entering a protected branch (push or merge).
  • Protected branch — a branch the host gates (typically main).

Three invariants govern everything:

  • INVARIANT-1 — no two actors ever simultaneously hold overlapping write-claims.
  • INVARIANT-2 — no change that violates a live claim can land on a protected branch.
  • INVARIANT-3 (agent-agnostic) — enforcement and claim-granting depend only on git and the filesystem, never on a vendor-specific signal. Vendor signals may enrich awareness only.

Repo-local metadata layout

AgentSync state lives under .agentsync/ at the repo root:

.agentsync/
  config.yaml            # repo policy (committed)
  tasks/
    AG-001.yaml          # task registry (committed)
  claims/
    <actor>.json         # mirror of granted claims (cache + audit)
  events.log             # append-only JSONL audit
  CONTEXT.md             # generated live landscape for agents to read (gitignored)
  state/                 # coordinator-cached derived state (gitignored)

The coordinator's linearizable log is the source of truth for who holds what. The .agentsync/claims/*.json files are a local mirror for audit and for offline/advisory reading. In advisory mode, the mirror is all there is, and the deterministic guarantee does not hold.

config.yaml

version: 0.1

repo:
  provider: github            # github | gitlab | native | none
  default_branch: main

branches:
  pattern: "agent/{task_id}-{slug}"   # branch-per-agent
  require_clean_worktree: true

commits:
  style: conventional
  require_agent_footer: true   # enforce the Agent/Task/Base-SHA footer
  squash_on_merge: true

claims:
  lease_ttl: 30m               # liveness window; safety comes from fencing tokens
  exclusive_paths:             # hard-locked: only one actor at a time, no exceptions
    - "db/migrations/**"
    - "package.json"
    - "pnpm-lock.yaml"
    - "schema.prisma"
  shared_paths:                # advisory-only: overlap allowed, surfaced as a warning
    - "docs/**"
    - "README.md"

integration:
  merge_strategy: squash
  require_tests: true
  use_merge_queue: true

agents:
  max_parallel: 30

coordinator:
  url: ""                      # empty = advisory mode. Set to a self-hosted or
                               # RemoteHost-hosted coordinator URL for the guarantee.

When commits.require_agent_footer is true, every commit carries a trailer block:

profile: add settings update endpoint

Agent: agent-12
Task: AG-012
Base-SHA: 8f41c2a
Claimed-Paths: src/profile/**, tests/profile/**

The footer is how the land gate and merge-plan attribute and validate a change using only git — satisfying INVARIANT-3.

The deterministic land gate

Enforcement bites where it is unbypassable: when a change tries to land on a protected branch.

edit locally           commit                 push / merge to protected branch
(always allowed)  -->  (local hook warns) -->  COORDINATOR GATE (deterministic)
                                               reject if the change touches paths held by
                                               another actor's live claim, or carries a stale
                                               fence token.

Tiers, from guarantee to convenience:

  1. Claim grant — the linearizable arbiter. Source of truth.
  2. Land gate — server-side rejection at push/merge. This is INVARIANT-2.
  3. Local pre-commit/pre-push hook — fast feedback, best-effort, bypassable.
  4. Optional live-revert daemon — edit-time prevention for exclusive_paths. Heavy, opt-in, never required for the guarantee.

Coordinator API

Any host — the free reference coordinator, or a RemoteHost-hosted coordinator — implements the same contract (REST + WebSocket):

  • POST claim → grant or deny, with a fence_token on grant.
  • POST renew → extend a lease (heartbeat).
  • POST release → release a claim (happy path).
  • GET subscribe(repo) → live stream of claim and activity changes (WebSocket or SSE).
  • GET conflicts(repo) → current predicted conflicts.
  • POST ready(task) → mark a task ready for review.
  • GET merge-plan(repo) → recommended merge order.
  • POST verify-land(repo, branch, changed_paths, fence_token) → the land-gate decision (grant/deny). Used by the server-side hook and the PR merge gate.

On claim, the coordinator, in a single linearizable step per repo, computes overlap against all live claims, denies on any overlap with a different actor's write-claim, and otherwise grants the next fence_token and sets lease_expires_at. exclusive_paths always deny on any overlap; shared_paths never deny.

Fencing tokens make crash recovery safe: every grant carries a monotonic token. If an actor's machine dies and its lease lapses, another actor may acquire the path and receives a higher token. If the original actor revives and tries to land under its now-stale token, verify-land rejects it deterministically — safety comes from the token, not wall-clock time.

Modes

  • Coordinated mode (a coordinator URL is configured) — deterministic. INVARIANT-1 and INVARIANT-2 hold. Free via self-host, or zero-config via a RemoteHost-hosted coordinator.
  • Advisory mode (no coordinator) — degraded. Agents read each other's committed claims and coordinate politely, but there is no arbiter, so there is no guarantee. This mode exists for zero-setup trial and read-only awareness, and is always labeled non-deterministic in output.

On this page