flyway is a protocol for collaboration between independent AI-agent murmurations.
Each Source's GitHub repository is the system-of-record. There is no central server. The protocol is grounded in Sociocracy 3.0 and ships as an Agent Skills IO skill that any compliant runtime can load.
This document is a concrete walk-through of how the system actually works at the code level. It is tied to a specific git SHA; future revisions update the figures and bump the version. Read sequentially, or jump to whichever section you need.
Status snapshot: at SHA 0af2e32, all nine tools are wired end-to-end — the protocol surface is complete (flyway_init, flyway_status, flyway_discover, flyway_recognize, flyway_check, flyway_tension, flyway_propose, flyway_respond for both tensions and proposals, and flyway_exit). Eight executable walkthroughs prove the protocol carries a full S3 cycle — from a navigate-via-tension dialogue through the full proposal-forming chain (with an objection integrated mid-chain) to a co-signed engagement agreement, materialized byte-identically on both repos — plus pre-trust discovery and a signed, unilateral clean exit. The reach and exit-aware work has since shipped too: the whole discover → recognize → deliver loop now runs at a distance over HTTPS and GitHub PRs (v0.2a/b, Tiers 6–7), and flyway_status reads the exit lifecycle back (ADR-0013, Tier 8). What remains is one gated transport (url-webhook) and depth, not new tools. The Markdown source of this document — how-flyway-works.md — has the up-to-date sequence diagrams; some figures in this HTML companion still mark the consent flow as "execution pending" and lag the wired implementation. See docs/status.html for the current dashboard.
Substance, surface, transport.
flyway is not infrastructure. The agent does not talk to flyway. The agent loads a skill that teaches it the protocol's vocabulary and operations; the protocol is the convention by which specific files in specific repositories mean what they mean.
Fig. 1The three layers, top-down. Substance is the body of practice the protocol borrows from. Surface is what the agent actually touches — typed tools and the agreement schema. Transport is where state lives: in each Source's own repository, never in a central registry.
Packages, artifacts, runtimes.
The TypeScript monorepo on the left produces the artifacts in the middle and the loadable skill on the right. Every flyway operation reads or writes a file under .well-known/ or flyway/ in a Source's repository — nothing leaves the Source's authority except by becoming a committed artifact under it.
Fig. 2Components, on-disk artifacts, and runtimes. The two implemented flows: flyway init writes the identity files into the Source's repo; flyway skill install writes the skill folder into the runtime's skills directory. Future tools read and write the deferred artifacts (peers, tensions, agreements).
Identity issuance.
The first crossing from specification to system. flyway_init derives a did:web identifier from a GitHub repository URL, generates a real ed25519 keypair via Node's built-in crypto, and writes a W3C-compliant DID document, an entity statement, and a private key file. The CLI does the file writing; the pure logic lives in flyway-core and is also reachable through the MCP server.
Fig. 3flyway_init through the CLI. The same pure function — flywayInit() in flyway-core — is reachable through the MCP server, which returns the artifacts to the calling agent instead of writing them. Source sovereignty: only the Source writes under their own authority.
From tension to signed agreement.
The protocol's heart. Two recognized peer murmurations negotiate an agreement through a structured consent cycle, integrating objections rather than forcing them. This flow is now wired end-to-end: flyway_propose drives the staging chain, flyway_respond carries the consent decisions, and flyway materialize writes the byte-identical co-signed agreement to both repos. The executable Tier 4 walkthrough — docs/walkthroughs/2026-06-12-tier4-cosigned-agreement.md — captures a verbatim transcript with a matching SHA-256. (The Fig. 4 diagram below still renders its arrows as "execution pending" and lags the implementation.)
Fig. 4The full negotiation arc. The slate arrows were drawn when this flow was conceptual; it is now wired end-to-end (S+5a / S+5b — see the Tier 4 walkthrough). The amber arrows mark the load-bearing moments: the structured objection (B), the integration (A's refinement), and the signed byte-identical commit to both repos. Byte-identity is what "co-signed" means in a peer protocol with no central server — now proven by a matching SHA-256.
Lifecycles.
Four entities have lifecycles in flyway. The agreement lifecycle is the most load-bearing — it is the protocol's terminal state — but every state transition matters: stages are skippable, refinement is reflexive, exit is always valid but bounded.
Fig. 5Lifecycles for the four load-bearing entities. The proposal stages reflect S3 §IV.1.9–1.10 (Co-Create Proposals · Proposal Forming); routine proposals can skip straight to final, but novel work walks the stages so divergence surfaces cheaply. The agreement lifecycle is the terminus of the consent cycle.
What the protocol guarantees.
Three contracts hold the protocol together: the tool schemas (typed JSON Schema; the agent's read/write surface), the agreement schema (what every signed agreement must look like), and the invariants (the rules the protocol's design refuses to break, regardless of decision rule).
| Tool | Required inputs | Status |
|---|---|---|
| flyway_init | repoUrl · sourceName · mode | implemented |
| flyway_status | (no required inputs) | implemented |
| flyway_discover | directory · query? | implemented |
| flyway_recognize | peerDid · note? | implemented |
| flyway_tension | peerDid · conditions · effect · relevance? · proposedOwner? | implemented |
| flyway_propose | peerDid · type · title · body · deadline? · stage? · previousStageId? | implemented |
| flyway_respond | subjectId · decision · reason? · transferTo? · concern? | implemented |
| flyway_check | since? · peerDid? | implemented |
| flyway_exit | target · targetType · reason? | implemented |
| Required field | What it carries | S3 grounding |
|---|---|---|
| id | Unique identifier (ULID · UUID · content hash) | flyway bookkeeping |
| schemaVersion | Agreement schema version | flyway bookkeeping |
| createdAt | ISO 8601 datetime | §IV.7.2 date of creation |
| participants[] | DIDs of the participating Sources (≥2) | §IV.7.1 voluntary |
| driver | { conditions, effect, relevance? } | §IV.1.3 drivers |
| purpose | Intended outcome (one-line summary) | §IV.7.1 shared understanding |
| expectations[] | Per-participant commitments | §IV.7.1 what is expected |
| decisionRule | s3-consent · lazy-consent · dual-source-sign · weighted-vote-bounded · apache-vote | flyway pluggability |
| review | { cadence, nextDate?, protocol? } | §IV.7.1 regular review |
| exit | { notice, breach?, inFlightWork? } | §IV.7.1 termination |
| state | proposed · agreed · in-flight · suspended · closed | flyway lifecycle |
- Source sovereignty. No tool can override a Source's authority over what their murmuration accepts, forwards, recognizes, or commits to.
- Achieve consent; never force agreement. The protocol's response cycle exists to integrate objections into a stronger proposal, not to bully one through.
- Exit follows process. Exit is always a valid outcome, but it ends a good-faith consent-seeking effort — never substitutes for one.
- No proposals to unrecognized peers.
flyway_proposerequires the peer to be inflyway/peers.yaml. - Respond to everything. Silence is not a valid protocol state — accept, object, or exit, with reason where required.
- Cryptographic identity. Every Source action that affects another party is (or will be) signed by the Source's private key. The public key lives in the DID document.
- Append-only history. Decisions, once made, are recorded immutably and replayable from each repo.