Skip to content

How Octy's answers are signed

Every Ask Octy™ answer, on this site and on atlanticagenticlabs.com, is issued with a signed receipt. The receipt records the question, the answer and the passages the answer was drawn from. Atlantic Agentic signs it with a key dedicated to Octy receipts. Any holder of the receipt can verify that the answer and its sources match what Atlantic’s service returned.

Each answer has an Evidence button, which opens a panel showing:

  • How the answer was produced. “Quoted from the documentation” when the answer consists of the passages themselves (“Quoted from the documentation and published knowledge” on atlanticagenticlabs.com when published knowledge is among them), or “Explained by a language model from these passages” when a model wrote an explanation from them.
  • Each source passage, quoted exactly as indexed, with a link to its page and section, and whether it comes from the documentation or from Atlantic’s published knowledge.
  • The version of each source. For the documentation, the release and the date the site was built. For published knowledge, the date the item was published.
  • How this answer was made. The mode: Search, which uses no model, or Explain. For an explanation, the model that wrote it and where it ran, how the router chose it, the number of models tried after the first, and the tokens read and written. The recorded cost of the answer in euro, with the US dollar figure it was converted from. The time spent finding the passages and, for an explanation, writing the answer. When a version 2 receipt verifies, the model, the tokens, the escalations and the cost are read from the signed receipt and marked Signed.
  • The signature status, verified in the browser (see Signature status).
  • Download receipt, which saves the receipt as a JSON file.
Status shown Meaning
Signed by Atlantic Agentic · verified The receipt’s signature is valid, and the answer, the question and every quoted passage match the receipt.
The answer does not match its receipt The signature is valid, but the answer, the question or a quoted passage differs from the receipt.
Keys could not be loaded, so the signature was not checked The public keys document could not be fetched.
Signature could not be verified The receipt is malformed, its key is not listed, or the signature is invalid.

The receipt is a single JSON object.

Field Meaning
v The receipt format version, 1 or 2. Version 2 adds the seven fields below. All other fields are identical in both versions.
id The receipt’s identifier.
iss The issuer, https://ask.atlanticagenticlabs.com.
profile Where the question was asked: docs (this site) or site (atlanticagenticlabs.com).
kind The kind of answer: retrieval, explained, not_covered, account or commercial.
produced How it was produced: quoted, explained or none.
question_sha256 The SHA-256 of the question as stored, after personal data and secrets were redacted from it. The panel shows that text.
answer_sha256 The SHA-256 of the answer text, or of the empty string when the answer consists of passages only.
passages One entry per source: its number n, its collection (docs or knowledge), its url, and the SHA-256 of the passage text quoted in the panel.
corpus The version of what was searched: the documentation release with a short digest of its text, and the published knowledge revision.
model_ref For an explained answer, a keyed reference to the model used, which identifies the model only against Atlantic’s own records. Otherwise null.
issued_at When the receipt was issued, in UTC.
model Version 2. The model whose reply decided the answer, as {"provider": …, "name": …} (for example {"provider": "Amazon Bedrock", "name": "Claude Haiku 4.5"}), from Atlantic’s own catalogue of models. null when no model was called, as for Search.
tokens_in, tokens_out Version 2. The tokens sent to and received from every model called for the answer, summed. 0 when no model was called.
escalations Version 2. The number of models called after the first. 0 when the first model’s answer was used.
cost_usd_nano Version 2. The answer’s recorded cost in US dollars, as a whole number in units of 10-9 (nano-dollars).
cost_eur_nano Version 2. That cost in euro, in units of 10-9, converted at the European Central Bank reference rate for the day the receipt was issued (or the latest earlier publication). null when no rate is held.
fx_date Version 2. The date of the rate used, as YYYY-MM-DD; null if and only if cost_eur_nano is null.
kid The identifier of the key that signed it.
alg The signature algorithm, Ed25519.
sig The signature, base64url without padding.

All hashes are SHA-256 over the UTF-8 bytes of the text, written in lower-case hexadecimal.

The signature covers the receipt without its sig field, in canonical form:

  • object keys sorted by Unicode code point, at every level;
  • no whitespace between tokens;
  • strings written as JSON strings, with characters outside ASCII written as themselves;
  • whole numbers only.

For the values a receipt holds, this is the JSON Canonicalization Scheme of RFC 8785. The signature is Ed25519 (RFC 8032) over the UTF-8 bytes of that text.

Atlantic publishes the Octy signing keys at:

https://ask.atlanticagenticlabs.com/.well-known/octy-keys.json

The document lists each key in JSON Web Key form (kty OKP, crv Ed25519, the public key in x), with its kid and a status:

  • current: the key new receipts are signed with;
  • retired: a key that signed earlier receipts. Retired keys remain listed, and receipts signed with them continue to verify.

On rotation, the new key is added as current and the previous key is marked retired. A key that is no longer trusted is removed from the list, and receipts signed with it fail verification.

Open the Evidence panel on an answer. The panel accepts receipts of version 1 and 2. A version 2 receipt that lacks one of its seven fields, or holds a field of the wrong type, is reported as not verified. The panel fetches the keys, checks the signature with the browser’s Web Crypto Ed25519 implementation (or a bundled Ed25519 library where the browser does not provide one), and compares the answer, the question and each quoted passage with the hashes in the receipt.

Terminal window
lighthouse-ai verify-answer octy-receipt.json --answer answer.txt

The command fetches the published keys and checks the signature. With --answer, it also checks that the file contains the answer the receipt was issued for, byte for byte. --keys takes a saved copy of the keys document in place of the published one.

The following example uses Python with the cryptography package.

import base64, hashlib, json, urllib.request
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
receipt = json.load(open("octy-receipt.json", encoding="utf-8"))
keys = json.load(urllib.request.urlopen(
"https://ask.atlanticagenticlabs.com/.well-known/octy-keys.json"))
def b64url(s):
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
key = next(k for k in keys["keys"] if k["kid"] == receipt["kid"])
signed = {k: v for k, v in receipt.items() if k != "sig"}
message = json.dumps(signed, sort_keys=True, separators=(",", ":"),
ensure_ascii=False).encode("utf-8")
Ed25519PublicKey.from_public_bytes(b64url(key["x"])).verify(
b64url(receipt["sig"]), message) # raises InvalidSignature if it fails
answer = open("answer.txt", encoding="utf-8").read()
assert hashlib.sha256(answer.encode("utf-8")).hexdigest() == receipt["answer_sha256"]
print("verified")

With OpenSSL 3, write the canonical text to message.bin and the decoded signature to signature.bin, then run:

Terminal window
openssl pkeyutl -verify -pubin -inkey octy-key.pem -rawin \
-in message.bin -sigfile signature.bin

octy-key.pem is the public key from the keys document in PEM form: the 32 bytes of x after the fixed prefix 302a300506032b6570032100, base64-encoded between -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- lines.

A receipt identifies the passages and the answer by hash, and the model by a keyed reference. It contains no IP address, cookie, session identifier or other information about the person who asked. Ask Octy on the docs describes what is kept with each question and for how long.