Protocol 1.0

The system of record for software evolution

Converge is a transactional software-state store for coding agents. Git is the object store. The product is the transition from one immutable snapshot to the next.

It is not GitHub without a UI. There are no pull requests, comments, stars, or dashboards. Agents resolve a snapshot, work in an isolated workspace, submit a change, attach evidence, and integrate with compare-and-swap.

Deterministic core. Intelligent clients.

Converge does not generate, review, or summarize code. The systems consuming it are the agents. The API is structured input, structured output, stable identifiers, and explicit exit codes.

Hosts

Marketing and documentation live on the product host. Agents, CI, and the CLI talk to the agent host.

Product https://www.converge.seeyon.chat
Agent / API https://converge.seeyon.chat

HTTP control plane:

https://converge.seeyon.chat/v1

Git data plane:

converge@converge.seeyon.chat:payment-service.git

Point the CLI at the agent host:

export CONVERGE_SERVER=https://converge.seeyon.chat

Quickstart

Canonical path for a coding agent. Git stays Git. Converge owns remote software-state that Git does not understand.

Authenticate first

Run converge auth login to authenticate through Seeyon Chat. The CLI opens a loopback callback on 127.0.0.1, stores the short-lived credential with mode 0600, and remembers the selected Converge server.

  1. Resolve master into a snapshot Pin work to an immutable commit, never a moving branch name.
  2. Create a workspace One agent, one task, one frozen base.
  3. Clone, edit, commit with Git Converge does not wrap clone, add, commit, or rebase.
  4. Push the workspace ref and submit a Change Base + result + intent + principal.
  5. CI publishes Evidence against the exact commit Then integrate with compare-and-swap.
export CONVERGE_SERVER=https://converge.seeyon.chat
converge auth login
converge --json auth status

converge --json snapshot resolve payment-service master
converge --json workspace create payment-service --base snp_123 --task TASK-8291

git clone converge@converge.seeyon.chat:payment-service.git
cd payment-service
git checkout abc123
# edit locally
git commit -m "Fix invoice total rounding"
git push origin HEAD:refs/workspaces/wrk_01928

converge change submit payment-service \
  --workspace wrk_01928 \
  --commit def456 \
  --intent "Fix invoice rounding"

converge integrate payment-service chg_8291 \
  --target master \
  --expected abc123

Install

The converge binary is both CLI and server. The installers detect the operating system and CPU, download the matching artifact, and verify it against SHA256SUMS before installation.

curl -fsSL https://www.converge.seeyon.chat/install.sh | sh
export CONVERGE_SERVER=https://converge.seeyon.chat
converge auth login

Windows PowerShell:

irm https://www.converge.seeyon.chat/install.ps1 | iex
$env:CONVERGE_SERVER = "https://converge.seeyon.chat"
converge auth login

Direct downloads: Windows x64, macOS Apple Silicon, macOS Intel, Linux x64, and Linux arm64. Every artifact is covered by SHA256SUMS.

Serve a node:

converge serve

Agents should pass --json on every command. Do not parse prose to decide success.

After the first successful login, the CLI remembers the selected server. Explicit --server and CONVERGE_SERVER values take precedence over the saved server. Use converge auth status to inspect the active principal, credential ID, and capabilities; use converge auth logout to remove the local credential.

Repository

A repository is a namespace and a bare Git object store. It is not a project-management container. New repositories default to refs/heads/master.

POST /v1/repos
{
  "name": "payment-service"
}

{
  "id": "payment-service",
  "default_ref": "refs/heads/master"
}

Identifiers must match ^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$. DELETE archives by default. An archived repository remains readable, but workspace creation, seed sessions, and Git writes are rejected.

Snapshot

A snapshot is an immutable software state. In V1 the code component is a Git commit SHA. Agents should work from a snapshot ID or commit, not from the mutable name master.

POST /v1/repos/payment-service/snapshots/resolve
{ "ref": "refs/heads/master" }

{
  "snapshot": "snp_01J...",
  "commit": "83ab291..."
}

Ephemeral agents can fetch an archive of exactly that commit:

GET /v1/repos/{repo}/snapshots/{commit}/archive

Workspace

A workspace is one agent task on one base snapshot. It is logical metadata. Converge does not keep a server-side checkout. The filesystem belongs to the agent runtime.

POST /v1/repos/payment-service/workspaces
{
  "base": "snp_01J...",
  "task_id": "TASK-8291",
  "working_set": ["src/payment/**"]
}

{
  "id": "wrk_01928",
  "ref": "refs/workspaces/wrk_01928",
  "potential_conflicts": []
}

Working sets are advisory. They never create file locks. Overlap with other active workspaces is reported; V1 does not serialize conflicting work. Statuses: active, submitted, abandoned, expired.

Workspace refs are temporary. An ordinary principal may abandon only its own workspace; repository coordinators require the broader workspace.write capability to act on another principal's workspace. Abandonment and expiry remove refs/workspaces/{id}; a submitted Change keeps its result reachable through the durable refs/changes/{id}/head ref.

Change

A change is the unit of proposed evolution: base state + result state + intent + producer + evidence. It replaces a machine-oriented pull request.

POST /v1/repos/payment-service/changes
{
  "workspace": "wrk_01928",
  "result_commit": "def456",
  "intent": "Fix invoice rounding"
}

Statuses: created, validating, ready, integrated, rejected, superseded, conflicted. Every submitted change keeps refs/changes/{id}/head.

A change becomes ready when required evidence exists in the required state. Readiness does not integrate. Integration is a separate explicit action.

Evidence

Evidence is machine-generated proof about a change. It is more general than a CI status. Converge stores state, summary, producer, and an external URL — not logs, coverage files, or binaries.

POST /v1/repos/payment-service/changes/chg_8291/evidence
{
  "type": "test",
  "name": "unit-tests",
  "state": "passed",
  "producer": "ci:jenkins-prod",
  "summary": "341 tests passed",
  "details_url": "https://ci.internal/jobs/98182"
}

Built-in types: test, build, lint, typecheck, security, policy, review, benchmark, compatibility, custom. States: pending, passed, failed, warning, cancelled.

A coding agent must not be allowed to forge CI evidence. Evidence write is capability-controlled.

Principal and delegation

Every actor is a principal. There is no User object and no Guest / Developer / Maintainer roles.

agent:codex:session-38192
ci:jenkins-prod
validator:security
integrator:master
system:provisioner

People authenticate as human:oauth:…; non-interactive automation uses service:… principals. A third-party OAuth token keeps that same sub and records the application as azp. External agent JWTs may carry delegated_by, task_id, and credential_id. Authorization is capability-based and repository-scoped, for example repo:payment-service:change.create. Ordinary coding agents must not receive repo:payment-service:ref.update or repo:payment-service:integration.execute.

Integration

Integration is the controlled transition of an accepted change into an authoritative ref. Coding agents should not push to master.

POST /v1/repos/payment-service/integrations
{
  "change": "chg_8291",
  "target_ref": "refs/heads/master",
  "expected": "abc123"
}

{
  "integration": "int_19382",
  "previous": "abc123",
  "current": "def456",
  "snapshot": "snp_01JAC..."
}

The ref update is atomic compare-and-swap, equivalent to git update-ref refs/heads/master def456 abc123. If master has moved, Converge returns 409 with REF_CONFLICT.

{
  "error": "REF_CONFLICT",
  "expected": "abc123",
  "actual": "xyz999"
}

Converge never rewrites source to resolve merge conflicts. The agent rebases or regenerates, re-validates, and retries.

Agent workflow

The product model is a pipeline, not a repository page:

Snapshot → Workspace → Change → Evidence → Policy → Integration → new Snapshot

CI must build the exact result commit, not master. That remains reproducible if master moves while the job sits in a queue.

Concurrency

A stale base is a normal concurrent condition. Two agents may start from snapshot A. The first CAS to B succeeds. The second CAS A → C fails with REF_CONFLICT. Agent 2 resolves snapshot B, replays, validates, and CAS B → D.

V1 does not automatically serialize overlapping working sets. Agents may continue, wait, narrow the set, or coordinate outside Converge.

HTTP API

Control plane is HTTP + JSON at https://converge.seeyon.chat/v1. Timestamps are UTC ISO 8601. Mutations return stable identifiers and accept Idempotency-Key. A completed identical request is replayed; concurrent duplicates may return REQUEST_IN_PROGRESS; reuse with a different body is rejected.

JSON decoding rejects unknown fields. Requests beyond the configured body limit return 413 PAYLOAD_TOO_LARGE.

Authentication and service accounts

GET /v1/auth/login

GET /v1/auth/callback

POST /v1/auth/exchange

GET /v1/auth/me

POST /v1/auth/service-accounts

POST /v1/auth/service-accounts/{principal}/tokens

DELETE /v1/auth/service-accounts/{principal}/tokens/{token_id}

OAuth authorization server

GET /v1/oauth/authorize

POST /v1/oauth/authorize

POST /v1/oauth/token

POST /v1/oauth/revoke

GET /v1/oauth/grants

DELETE /v1/oauth/grants/{id}

POST /v1/oauth/clients

GET /v1/oauth/clients

GET /v1/oauth/clients/{id}

PATCH /v1/oauth/clients/{id}

POST /v1/oauth/clients/{id}/secret

Repositories

POST /v1/repos

GET /v1/repos

GET /v1/repos/{repo}

DELETE /v1/repos/{repo}

Snapshots

POST /v1/repos/{repo}/snapshots/resolve

GET /v1/repos/{repo}/snapshots/{snapshot}

GET /v1/repos/{repo}/snapshots/{commit}/archive

Workspaces

POST /v1/repos/{repo}/workspaces

GET /v1/repos/{repo}/workspaces/{workspace}

DELETE /v1/repos/{repo}/workspaces/{workspace}

Changes

POST /v1/repos/{repo}/changes

GET /v1/repos/{repo}/changes/{change}

GET /v1/repos/{repo}/changes

Evidence

POST /v1/repos/{repo}/changes/{change}/evidence

GET /v1/repos/{repo}/changes/{change}/evidence

PUT /v1/repos/{repo}/changes/{change}/evidence/{evidence}

Integration and refs

POST /v1/repos/{repo}/integrations

GET /v1/repos/{repo}/refs/{ref}

PUT /v1/repos/{repo}/refs/{ref}

Blind updates to authoritative refs are denied. The current value must be supplied for CAS.

Hooks and audit

POST /v1/hooks

GET /v1/hooks

DELETE /v1/hooks/{hook}

GET /v1/audit

Observability: /healthz, /readyz, /metrics.

CLI

First-class V1 interface. The same binary serves the node. It does not wrap ordinary Git.

converge auth login
converge --json auth status
converge --json repo create payment-service
converge --json snapshot resolve payment-service master
converge --json workspace create payment-service --base snp_123 --task TASK-8291
converge --json change submit payment-service --workspace wrk_01928 --commit def456 --intent "Fix invoice rounding"
converge --json evidence add payment-service chg_8291 --type test --name unit-tests --state passed
converge --json integrate payment-service chg_8291 --target master --expected abc123
converge --json audit --repo payment-service --task TASK-8291
ExitMeaning
0success
1general failure
2invalid arguments
3unauthenticated
4forbidden
5conflict
6not found
7policy denied
8timeout

Git

Git remains the storage substrate. Transport is SSH. Converge delegates to system Git: git-upload-pack, git-receive-pack, git-update-ref. It does not implement packfiles or the Git wire protocol.

Agents may write their authorized refs/workspaces/*. Converge manages refs/changes/*. Authoritative branches and tags are protected. Multi-ref pushes are checked as one transaction: if any update is forbidden, the full atomic push is rejected.

SSH allows only Git pack operations. No shell, scp, sftp, PTY, or forwarding. Production uses OpenSSH user certificates and AuthorizedPrincipalsCommand to map the certificate principal onto repository capabilities.

Authentication

People: Seeyon Chat browser login

converge auth login opens the production OAuth flow in a browser and receives a single-use authorization code through a loopback callback. OAuth state and exchange codes are short-lived and single-use. The resulting one-hour bearer credential is stored locally with the selected server; rerun login after expiry.

converge auth login
converge --json auth status
converge auth logout

The browser callback only accepts loopback CLI URLs. Session cookies are HttpOnly, Secure, and SameSite=Lax. A newly authenticated identity has no capabilities until an administrator with auth.grant.manage assigns them. Profile scopes such as email and name are never treated as repository capabilities.

Third-party web apps

Seeyon identifies the person. Converge then asks them to consent so a registered application can use their capabilities. This is OAuth 2.1: authorization code, PKCE S256, and rotating refresh tokens. Consent cannot mint access the user does not already have. The issued access token acts as that human:oauth:… principal, limited to the consented scopes. Git bytes stay on SSH; the token is for the HTTP /v1 API only.

An administrator with auth.oauth-client.manage registers the application. Redirect URIs must match exactly; https is required except for http loopback during local development. Client secrets and refresh tokens are stored as hashes.

converge auth oauth-client create billing-dashboard \
  --redirect-uri 'https://dashboard.example/callback' \
  --scope 'repo:payment-service:repo.read' \
  --scope 'repo:payment-service:workspace.create'

# Public SPA (no client secret):
converge auth oauth-client create local-dev --public \
  --redirect-uri 'http://127.0.0.1:4173/callback' \
  --scope repo.read

The create command prints client_id and client_secret once. The app then sends the user to Converge:

GET /v1/oauth/authorize
  ?response_type=code
  &client_id=oac_...
  &redirect_uri=https://dashboard.example/callback
  &scope=repo:payment-service:repo.read%20repo:payment-service:workspace.create
  &state=...
  &code_challenge=...
  &code_challenge_method=S256

After Seeyon login and consent, the app exchanges the code at POST /v1/oauth/token with PKCE (code_verifier) and receives a short-lived access token plus a rotating refresh token. The token’s sub stays the person; azp is the application. Refresh intersects the grant with the user’s current capabilities; if none remain, the grant is revoked. Presenting a consumed refresh token also revokes the whole grant. Access-token lifetime follows CONVERGE_OAUTH_TOKEN_TTL; refresh tokens default to 30 days (CONVERGE_OAUTH_REFRESH_TTL).

Users list and revoke apps they have authorized. The application can call POST /v1/oauth/revoke. Administrators rotate a confidential client secret or disable a client, which immediately rejects its access tokens.

converge auth oauth-grant list
converge auth oauth-grant revoke GRANT_ID
converge auth oauth-client rotate-secret CLIENT_ID
converge auth oauth-client disable CLIENT_ID

CI and agents: service accounts

CI should use first-party service-account tokens instead of browser credentials. An administrator creates the account with the minimum repository-scoped capabilities. The plaintext token is returned only when issued; store it in the CI secret manager and revoke it by token ID when rotated.

converge --json auth service-account create build-ci \
  --scope repo:payment-service:repo.read \
  --scope repo:payment-service:evidence.read \
  --scope repo:payment-service:evidence.write \
  --expires 720h

export CONVERGE_TOKEN='cvg_sa_…'
converge --json auth status

converge auth service-account token service:build-ci --expires 720h
converge auth service-account revoke service:build-ci sat_01…

Service tokens are random opaque credentials, stored server-side only as hashes. They support expiry and individual revocation. Creating, issuing, and revoking credentials is audited.

External agents: JWT/JWKS

External JWT trust is optional. Tokens require sub and exp; iat is validated when supplied. Production deployments should pin issuer, audience, and allowed algorithms. RSA keys are loaded from JWKS and refreshed when a new kid appears.

{
  "sub": "agent:codex:session-38192",
  "iss": "https://identity.example",
  "aud": "converge",
  "exp": 1787579481,
  "iat": 1787575881,
  "task_id": "TASK-8291",
  "delegated_by": "human:zhang",
  "credential_id": "cred_01J…",
  "scope": [
    "repo:payment-service:repo.read",
    "repo:payment-service:workspace.create",
    "repo:payment-service:change.create"
  ]
}

Audit records preserve principal, delegation, task, source address, and credential_id. Long-lived personal access tokens are not part of the model.

Events

After-transition work is asynchronous. V1 delivery is webhooks, at-least-once, HMAC-signed. Every event has a unique event_id. Delivery state survives service restarts; retries use the same event identity until delivery or terminal failure. Failed delivery never rolls back an already completed transition.

POST /v1/hooks
{
  "url": "https://ci.internal/converge",
  "events": ["change.created", "change.ready", "ref.updated"]
}

Core events include workspace.*, change.*, evidence.*, snapshot.created, integration.succeeded, integration.failed, ref.updated.

Policy

V1 supports simple declarative required-evidence policy. There is no general-purpose policy language.

{
  "target": "refs/heads/master",
  "required_evidence": [
    { "type": "test", "name": "unit-tests", "state": "passed" },
    { "type": "build", "name": "build", "state": "passed" }
  ]
}

Unsatisfied requirements fail integration with POLICY_DENIED. Blocking hooks have a 5 second default timeout. Slow checks should publish evidence instead.

Deployment

V1 is one binary, one host, system Git, SQLite in WAL, OpenSSH, a persistent volume, and an HTTPS reverse proxy. The production API is live at https://converge.seeyon.chat. Language is Go. Kubernetes is unnecessary. Interactive login uses Seeyon OAuth; registered third-party apps use Converge as the OAuth 2.1 authorization server.

/opt/converge/converge
/etc/converge/config.yaml
/data/converge.db
/data/repos/

Design envelope: 10,000 repositories, 1,000 active agents, 100,000 changes/day. Metadata p95 < 100ms. Ref transition p95 < 250ms, excluding external blocking hooks.

Not in V1

Repository Web UI, PRs, comments, CI runners, AI features, Redis, Kafka, gRPC, libgit2 as the core engine, microservices, or a distributed database. Login and third-party OAuth consent pages are in scope.