HONESTY.TOOLS
Build on the lens · API · SDK · MCP

Inspect the contract.
Choose the integration.

Choose the integration

Start from the artifact’s documented version, dependencies and license. Keep the decision rule, controls and receipt alongside the output. Photon API/SDK/MCP examples are system-specific; other prototypes require separate assets and access.

Public utilities run locally or in an evaluation workflow. The existing Photon API, SDK and MCP surfaces support a separate research preview. Other prototypes require their own assets and access agreement.

the 1-key port
# point any OpenAI client at Aperture — nothing else changes
base_url = "https://honesty.tools/v1"
api_key  = "sk-apt-…"        # free key at honesty.tools/verify · free tier, upgrade anytime
model    = "aperture-router"   # grounded → local · off-map → escalate
three ways in
The API · the proxy

Photon Base as a smart honesty router.

The served model, registry grounding, readout pre-filter and escalation routes are separate components. The pre-filter does not establish fabrication detection. Inspect the response record and known failures beside the system contract.

your agent Aperture · off-map read tier 1 · local Photon Base · grounded tier 2 · neocortex · off the map tier 3 · the internet · time-sensitive
curl https://honesty.tools/v1/chat/completions \
  -H "Authorization: Bearer $APERTURE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "aperture-router",
    "messages": [{"role":"user","content":"Who founded Brindlewick & Thorne?"}]
  }'
from openai import OpenAI

client = OpenAI(base_url="https://honesty.tools/v1", api_key=APERTURE_KEY)

resp = client.chat.completions.create(
    model="aperture-router",
    messages=[{"role": "user", "content": "Who founded Brindlewick & Thorne?"}],
)
print(resp.choices[0].message.content)        # the answer
print(resp.model_extra["aperture"])           # the honesty layer ↓
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://honesty.tools/v1", apiKey: APERTURE_KEY });

const resp = await client.chat.completions.create({
  model: "aperture-router",
  messages: [{ role: "user", content: "Who founded Brindlewick & Thorne?" }],
});
console.log(resp.choices[0].message.content);   // the answer
console.log(resp.aperture);                  // the honesty layer ↓

Every reply carries an aperture block — the certificate and the route trace — alongside the standard OpenAI response. Standard clients ignore it; Aperture-aware ones read it.

response · the aperture block
{
  "choices": [{ "message": { "role": "assistant", "content": "…" } }],
  "aperture": {
    "verdict":  "OFF_MAP",           // GROUNDED · CONFIDENT · LOW_FAMILIARITY · OFF_MAP
    "off_map":  0.778,              // aperture-router's familiarity off-map read (a different instrument from the per-model cert fingerprint), 0–1
    "route": {
      "tier": 2,                   // 1 local · 2 neocortex · 3 internet
      "brain": "the escalated neocortex model",
      "escalated": true,
      "reason": "off the map (off-distribution 0.78) — escalated to the neocortex"
    },
    "gauges":  { "off_distribution": 0.778, "familiarity": 0.022 },
    "advice":  "the question is outside the model's reliable knowledge…"
  }
}
Watch it route · illustrative example traces
tier 1 · localPhoton Base
the lens routed to

The model id doubles as the mode — switch behavior without touching your code — and for already-recorded answers, POST /v1/audit scores a whole batch in one keyed call (see the docs):

aperture-routerThe honesty router. Grounded → local Photon Base; off-map → escalate to the neocortex or the internet. (default)
aperture-monitorPhoton Base always answers; Aperture only annotates (passive). The safe first step — watch the route traces before you let it act.
aperture-35bForce the local cortex — no escalation, just Photon Base + its certificate.
aperture-frontierForce the neocortex — always escalate to a bigger map.
Streaming works unchanged (stream: true → an OpenAI SSE stream; the aperture block rides the final chunk). Auth is a bearer key when the port is keyed, keyless on localhost. GET /v1/models lists the modes — including aperture-annotate (pass-through: your own model answers on your OpenRouter key, sent as the X-Upstream-Key header, and Aperture attaches only the reading), which the table above omits. The router is read-only — it never touches the served decoder except through the same bounded path the portal already uses.
The receipt · ed25519

Every answer ships a signed receipt.

Whether a receipt is authentic isn't something you take on faith — every /v1/verify receipt (and every stored /read) is signed: an ed25519 signature you can verify offline against the published public key. Tamper with one byte and it fails. This is the moat: not raw metrics — a verifiable record.

verify a signed receipt — offline, no call back to us
import json, base64
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey

# `receipt` is the signed block from your /v1/verify response (or a stored /read)
r = dict(receipt); sig = r.pop("signature"); r.pop("id", None)
canon = json.dumps(r, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode()
Ed25519PublicKey.from_public_bytes(base64.b64decode(sig["pub"])).verify(base64.b64decode(sig["sig"]), canon)
print("verified — the signed receipt is authentic")   # raises on tamper; sig["pub"] == /api/cert/pubkey
Stored reads verify the same way, and /evidence runs a real in-browser WebCrypto check on each one — independently, in your own browser, against the published pubkey. The signature is the product. See receipts verify on /evidence →
Don't trust our check — run your own. The open verifier is a single dependency-light file (cryptography + stdlib): python3 aperture_verify.py verify receipt.json checks any receipt or cert offline against the pinned registry key, with no call back to us. And an append-only Merkle transparency log makes suppression or a swapped receipt third-party detectable. You can't watch a 12-hour agent, but you can verify its trail: verify-session checks every receipt in a run and the root over their ordered sequence, so altering, reordering, or dropping one is caught. And where a fixed rule settles the answer, a deterministic per-answer witness lets you re-derive the verdict yourself — a code result re-run in an isolated sandbox, a math identity re-checked in SymPy, a fact proved present in our registry by a Merkle proof — exact, offline, no distribution and no trust in us, and still provenance, not truth. Versioned, conformance-testable open spec: the spec → · witness spec →
The SDK · the lens in your code

One key. One import.

The existing Photon package and service-specific examples are retained below. Consult the access and billing contract before using the hosted service.

pip install aperture-gate
Or self-host Photon Base. The whole stack — the served model, the grounding registries, the gate — runs inside your own perimeter. Your data never leaves. Same SDK, point it at your local port instead of the hosted one. Self-host guide →
# one sk-apt- key — grounding + honest inference, free to start
from aperture_gate import Aperture, signup

key = signup("you@email.com")            # a FREE key (or grab one at honesty.tools/verify)
ap  = Aperture()                          # reads APERTURE_API_KEY

ap.verify("Sotorasenib is an approved cancer drug.")   # → fabricated · caught FREE
ap.verify("BRCA1 is a tumor suppressor gene.")          # → grounded · 1 of your plan
print(ap.ask("Who painted the Mona Lisa?"))            # → honest Photon inference
ap.usage()   # → {tier:"free", used, limit, remaining} · upgrade at honesty.tools/verify
# ADVANCED — gate your OWN model offline, against a calibration certificate (no hosted call)
from aperture_gate import Gate

gate = Gate.from_cert("openai/gpt-4o-mini")        # a registry id, a downloaded JSON, or a dict
r = gate.ask("Who founded Brindlewick & Thorne?",
             base_url="https://openrouter.ai/api/v1", api_key=KEY,
             model="openai/gpt-4o-mini")
print(r["verdict"], r["score"])   # → OFF_MAP — caught before you commit
# or words-only, no model at all:
verdict = gate.read_text(answer_text)
Gate → verdictverdict (ON_MAP · UNCERTAIN · OFF_MAP — the Gate’s per-cert vocabulary; the hosted router speaks GROUNDED/CONFIDENT/…), instrument (words · fingerprint), score, the matched refusal phrases, and the certificate id it read with.
annotate → aperture blockThe same reading attached to a standard chat completion — verdict, band, instrument, off_map_score, calibration_cert.
The gate reads per model, per certificate — never a global threshold. On logprob-exposing surfaces (OpenAI-class, any self-hosted vLLM/SGLang) it reads the confidence fingerprint; everywhere else the words. Conformance vectors + the full schema live in the docs; the package is MIT and dependency-free.
The MCP · a tool your agent calls

The lens beside the model.

The recommended shape for agents: not baked into weights, but a tool the agent calls mid-task — “am I off the map before I commit?” — at any tool-call, write, or plan→execute boundary. It runs as a stdio MCP server, shipped inside the same package.

// add Aperture to your MCP client's config
{
  "mcpServers": {
    "aperture": {
      "command": "python",
      "args": ["-m", "aperture_gate.mcp"],
      "env": { "APERTURE_API_KEY": "sk-apt-…" }   // a free key from honesty.tools/verify
    }
  }
}
# install once, run anywhere — stdlib only
pip install aperture-gate
python -m aperture_gate.mcp

Three tools, each returning a receipt the agent can branch on:

aperture_verify(claims)Ground checkable claims against the hosted registries — grounded / fabricated / abstain, with the evidence and your plan usage. Catching fabrications is free; only grounded claims count. The agent's pre-commit fact check, on your free key.
aperture_read(query, model?)Ask the hosted honest Photon model (your free key) and read the answer through the lens → verdict · score · instrument. Point it at your own endpoint to gate a BYO model instead.
aperture_check_text(text)Words-only read of any text the agent already has — no model call. The cheapest pre-commit receipt.

Then branch on the gate — the whole point is the action:

proceed

Grounded

A grounding signal calls for inspection under the method contract. It does not establish that an action is safe.

review

Verify first

On the edge. Check the claim — retrieve, cross-check — before you act on it.

escalate

Off the map

Do not commit. Gather more, ask a human, or abstain rather than bluff. The off-map read is a cheap triage flag — fabrications are caught downstream by grounding (verified registries) and cross-model checks.

Build once · deploy anywhere

Put the lens between your model and what matters.

Choose a specific method and compatible configuration, then inspect its input, output, control and release contract.