ColloqGitHubv0.1 · research prototype · Apache 2.0
One conversation. Every server keeps its half.
Colloq is a language for systems where several servers must agree on a
protocol: an inference gateway and its routers, an agent and its tools, two
services that keep drifting apart. You write the exchange once. The compiler
gives each side a checked endpoint, and the runtime carries it over shared
memory, TCP, QUIC or Iroh.
$ colloq check examples/route.colloqconv.json
valid conversation example.route (2 roles, 11 states)
$ colloq compile examples/route.colloqconv.json
wrote build/route.colloqplan.json
conversation sha256:92c198d0…
plan sha256:016d5975…$ colloq run-plan build/route.colloqplan.json --transport quic --wire compact
✓ client and server report the same semantic trace
What it is for
Three servers, one agreement.
Every system below has the same problem: two or more processes must follow the
same protocol, including its failures, and today that agreement lives in a
client library, a server handler and a schema file that drift apart.
Inference routing
Gateway, router, experts
A request arrives, a router decides between a cached answer and a model,
tokens stream back, and the client may cancel mid-stream. Deadlines and
cancellation are part of the type, so no side invents its own handling.
choice · stream · cancel · deadline
Agents and tools
Turn order that holds
An agent process and its tool services must agree on who speaks next, what
a retry means and when a run is finished. Colloq compiles that order into the
plan both sides run. An out-of-turn call is not caught by a policy layer that
reads generated code. The endpoint state machine has no such edge.
roles · loops · terminal states
Service pairs
Two services that drift
The classic pair: a handwritten client, a handler and a schema file that
disagree after the third change. One conversation replaces all three, and
the identity changes when the meaning changes.
projection · content identity
Colloq is not a web framework and not a hosted service. If one process does all
the work, you do not need it.
The old way, the new way
Same exchange. One file instead of four.
A gateway asks a router for an answer within 20 ms, and the router replies from
cache, from a model, or hands the case to a person. Here is where that agreement
lives today, and where it lives in Colloq.
The usual way
4 files, 3 languages, 2 teams
# route.proto — the shape, but not the order
service Router {
rpc Route(Request) returns (Answer);
}
# client.py — deadline and retry, written here
resp = stub.Route(req, timeout=0.02)
# is a retry safe? the proto does not say# server.py — the branches, written again
if cached: return Answer(kind="cached", ...)
if score > 0.9: return Answer(kind="infer", ...)
return Answer(kind="review", ...)
# handler.py — "review" handled? nobody checks
The order of messages lives in two handwritten files.
A new branch compiles on one side and crashes on the other.
Timeouts and cancellation are convention, not type.
Nothing tells you the two sides still agree.
With Colloq
route.colloq — one file, both sides
conversationRoute(request: Request) {
roles gateway, router
gateway -> router: request within 20ms
choice router {
cached { router -> gateway: CachedAnswer; end }
infer { router -> gateway: ModelAnswer; end }
review { router -> gateway: ReviewTicket; end }
}
on transport.timeout -> timed-out
}
The order is the program. Each side is derived from it.
A new branch changes the plan identity, so a stale peer is refused.
The deadline and the failure are part of the type.
Both peers compare identities before the first frame.
Concern
The usual way
Colloq
Where the protocol lives
A schema file, plus both implementations
One conversation
Who checks the order
Nobody, until production
The checker, before you run it
Timeout and cancellation
Client convention
Declared transitions
Failure handling
Generic exception per service
A declared state per failure
Detecting a change
Version numbers and hope
Content identity, refused on mismatch
Changing transport
Rewrite the plumbing
Run the same plan on another transport
How it works
Write the agreement once. The compiler splits it.
From that one file, the compiler derives a local state machine for each role.
Nobody writes this: the router's machine below comes out of
colloq project, and the gateway gets the exact
mirror of it. Two servers cannot disagree about a protocol neither of them wrote.
build/endpoints/router.colloqendpoint.json — derived, not written
A branch label is part of the type. A role can only send a transition the
plan declares, and the receiver checks it before it advances.
Failure is in the language
A timeout or a reset is a declared transition to a declared state, not a
generic exception that each service handles differently.
One identity across the cluster
The conversation and the compiled plan are content addressed. Both peers
exchange those identities before frame zero, and a mismatch stops there.
Transports
The meaning survives the wire.
The same compiled plan runs over shared memory, TCP, authenticated QUIC and
Iroh. Every transport reconstructs the same semantic trace, so a laptop run and
a two-host run mean the same thing.
The systems Colloq targets will not be written only by people. Models and
evolutionary search already propose changes to routing, placement and whole
subgraphs. That is the reason the conversation is typed and content addressed:
machine-authored change needs a substrate where meaning is checkable, not a pile
of text files where a rename looks like a rewrite.
The graph is the program
Edit structure, not text
The source of truth is a typed, content-addressed graph. Text and visual
editors are projections of it. A generator issues typed transactions and
fills typed holes, so formatting and names never change the meaning.
Evolution as a transaction
Propose, gate, canary, keep or revert
A candidate passes type and effect checks, then capability and budget
checks, then bounded evaluation, then a policy decision, then a canary
rollout. Promotion and rollback are steps, not incidents.
Authority never inherits
A child gets no rights by birth
A candidate cannot acquire a capability because its parent had one. Lineage
is immutable, gates cannot be written by the candidate itself, and some
invariants stay outside the region a generator may edit.
None of this is finished, and the project keeps a scoreboard rather than a
slogan: what is derived today, what provenance still lives in git, which limits
are drafts, and which gaps are not on the roadmap at all.
Read the goal and where it stands.
Colloq is a language and a runtime. Nothing in it depends on a model. One
optional binding lets a typed model choose the label at a choice state, with an
explicit confidence threshold and a declared escalation branch. Remove it and
the conversation still compiles, still runs and still checks.
See the optional chooser.
Evidence
Every number here is reproducible.
Colloq publishes a fixed workload, a hand-written baseline and the full report,
so a claim can be checked instead of believed. These are the current medians on
an Apple M4 over 500 iterations.
1.83 µscompact checked transition
0.125 µsto start two sessions from a plan
51.6 µsplan compilation, once per plan
4transports, one semantic trace
The whole exchange currently costs 1.51× a hand-written Rust pair, down from
1.68× with the compact wire, against a target of 1.25×. The compact encoding is
still JSON, so a binary codec is the next measurement. The benchmark exists to
make that number move in public.