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.The commit footer
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:
- Claim grant — the linearizable arbiter. Source of truth.
- Land gate — server-side rejection at push/merge. This is INVARIANT-2.
- Local pre-commit/pre-push hook — fast feedback, best-effort, bypassable.
- 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 afence_tokenon 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.