Skip to content
harness.talk

For agents · protocol

Protocol.

Everything an agent must know to speak to harness.talk without reading the source. Short on purpose. Each rule has an anchor so problem responses can point at it.

Reference grammar

A canonical reference is BOOK.CHAPTER[.VERSE[-VERSE]] with a lowercase book id. Human forms are accepted on input and always normalised on output.

ref       := book "." chapter [ "." verse [ "-" verse ] ]
book      := 2–3 lowercase letters, optionally prefixed by 1|2|3   (gn, ps, 1jn, re)
chapter   := 1..N                                                  (N from /api/v1/books/{id})
verse     := 1..M                                                  (M from the chapter)

Accepted on input, never emitted:
  "John 3:16"  "Jn 3.16"  "1 John 5:7"  "Psalm 119:176"  "Song of Solomon 2:1"

Book ids are listed at /api/v1/books. They are stable and will never be renumbered.

Quartet addressing

127.BOOK.CHAPTER.VERSE. Book is the canon ordinal (Genesis 1 … Revelation 66). Chapter and verse are 1-based. A zero collapses scope: verse 0 is the chapter, chapter 0 is the book, 127.0.0.1 is the corpus. Octets are limited to 255 by IPv4 — no chapter exceeds 150 and no verse exceeds 176, so nothing is unaddressable.

GET https://harness.talk/api/v1/resolve/127.43.3.16     # John 3:16
GET https://harness.talk/api/v1/resolve/127.19.23.0     # Psalm 23 (chapter)
GET https://harness.talk/api/v1/resolve/127.66.0.0      # Revelation (book)
GET https://harness.talk/api/v1/resolve/127.0.0.1       # corpus index

# locally, with harnessd running:
curl 127.43.3.16:1611

Response envelope

Every verse object is the same shape wherever it appears — alone, in a range, inside a chapter, in search hits, or from the daemon.

{
  "ref": "jn.3.16",
  "display": "John 3:16",
  "book": { "id": "jn", "name": "John", "ordinal": 43 },
  "chapter": 3,
  "verse": 16,
  "text": "¶ For God so loued þ world, that he gaue his only begotten Sonne: ...",
  "source": "kjv-1611",
  "sha256": "…64 hex…",
  "quartet": "127.43.3.16",
  "url": "https://harness.talk/foundation/jn/3#v16"
}

Fields are additive. New keys may appear; existing keys will not change meaning or type within /api/v1.

Hashes and the Merkle root

leaf(v)   = SHA-256( v.ref + "\n" + v.text )          # UTF-8, no trailing newline
node(l,r) = SHA-256( bytes(l) || bytes(r) )             # raw 32-byte digests, not hex
                                                        # odd leaf pairs with itself
root      = hex( fold over all 31,102 leaves in canon order )

published at  /.well-known/harness.json  →  corpus.merkleRoot
and inside    /exports/kjv.jsonl.gz      →  first line

The leaf rule is deliberately trivial. If you cannot reproduce it in your language in five lines, it is wrong. Inclusion proofs (a leaf's sibling path to the root) are specified but not yet served — see Storage & integrity.

Errors

All errors are application/problem+json (RFC 9457). type is a URL into this page; title is the machine code below; status is the HTTP status; detail is for humans and may change.

titlestatusmeaning
ref_unparseable400Input is not a recognisable reference. Grammar is on /agents/protocol.
book_unknown404No book matched the id, name, alias, or ordinal.
chapter_out_of_range404Chapter exceeds the book's chapter count (given in `max`).
verse_out_of_range404Verse exceeds the chapter's verse count (given in `max`).
quartet_invalid400Not a 127.b.c.v address, or an octet > 255.
source_not_ingested501The source exists in the registry but has no verified data for this request. Nothing is substituted.
query_empty400Search requires ?q=.
not_found404Nothing at this address.
HTTP/1.1 404
Content-Type: application/problem+json

{
  "type": "https://harness.talk/agents/protocol#book_unknown",
  "title": "book_unknown",
  "status": 404,
  "detail": "No book with id 'zz'. See /api/v1/books for the 66 ids."
}

Caching and headers

  • Scripture responses are immutable for a given corpus: Cache-Control: public, max-age=31536000, immutable plus a strong ETag. Send If-None-Match and expect 304.
  • Search and index responses use a short public cache (max-age=300).
  • X-Harness-Corpus carries the source id; X-Harness-Root carries the Merkle root, on every 200.
  • CORS is open (*) for GET. There is no authentication because there is nothing to protect — the API only reads.

Stability

/api/v1 is frozen at the field level: keys are additive only, ids never renumber, hashes never change for a given source id. A new corpus (a corrected KJV edition, the Geneva text) gets a new source id and a new root; the old one keeps serving. Breaking changes go to /api/v2 and /api/v1 stays up.