Andreas Ritter
Personal AI Engineering · Search & LLM Observability

Closing the loop on search and LLM discovery

Search engines and frontier language models answer questions about people and companies every day, often from stale weights or homonym collisions. Instead of guessing what they say, I built a zero-cookie, API-driven observability studio on the edge to measure, verify and improve it week by week.

Cloudflare Workers & D1 SQLite · 9 Direct APIs (OpenAI · Anthropic · Gemini · Brave · GSC · Bing · CF GraphQL) · Zero cookies · Strict CSP
Direct APIs & Crons 9 APIs Web-standard fetch & Web Crypto RS256; 0 npm runtime packages
Weekly LLM Matrix 6 × 5 Probes DE/EN entity & utility-AI discovery across grounded + weight-only modes
Longitudinal Signal 28d EWMA Half-life recency kernel + two-tier Claude Sonnet/Opus 5.5 drift judge
Visitor Overhead 0 ms TTFB Async ctx.waitUntil referrer tally; zero cookies, beacons or 3rd-party calls

Type your own name or your company's core domain into three frontier chat interfaces and you will get three plausible, subtly incompatible biographies. In my case, ungrounded models routinely merged three different people in Zürich: an electrical engineer from ETH Zürich's High Voltage Laboratory (D-ITET) leading Energy at inpeek AG, a namesake control-systems researcher at ETH's IDSC institute (D-MAVT), and a Zürich commercial attorney. Worse, interactive chat frontends hide retrieval chunks, personalize on session history, and give you no way to tell whether an outdated claim came from a missing webpage signal or frozen pre-cutoff weights.

Treating LLM visibility as an engineering control loop required fixing both sides of the equation at once. First, I turned andreasritter.ch into an explicit machine-readable source: structured ProfilePage JSON-LD carrying a formal disambiguatingDescription, a clean Markdown twin at /index.md advertised via HTTP Link response headers, a concise /llms.txt index, and Content-Signal: search=yes, ai-input=yes, ai-train=no in robots.txt. Every push to main runs automated snippet, schema and live-edge verification before pinging IndexNow.

Prompting a chat window tells you what one session improvised once. Polling five grounded and ungrounded APIs on a fixed Monday schedule tells you whether your engineering actually moved the needle. Design principle behind andreasritter-telemetry

Programmatic API probes instead of frontend spot-checks

To measure what outside systems actually retrieve, I built a second, isolated Cloudflare Worker (andreasritter-telemetry) that polls nine upstream APIs on deterministic cron schedules and writes normalized time series into Cloudflare D1. Every night it pulls verified AI crawler activity from Cloudflare's GraphQL Analytics API and query rankings from Google Search Console (signing PKCS#8 RS256 service-account JWTs directly via Web Crypto), paired with a daily GitHub Actions job that syncs Bing Webmaster and Copilot index stats outside Cloudflare's shared Worker egress IPs.

Every Monday at 06:30 UTC, the Worker dispatches a bilingual German and English benchmark across OpenAI's Responses API, Anthropic's Messages API, Google's Gemini API, Brave Search llm-context and Brave Answers. Three entity prompts verify biographical and project facts; three non-branded discovery prompts test whether inpeek AG surfaces organically when Swiss utilities ask about migrating from innosolvenergy to SAP S/4HANA Utilities or verifying mass billing runs with AI. Running OpenAI, Claude and Gemini both with live web search and without it isolates exactly what live retrieval fixes versus what parametric memory still remembers.

Separating real momentum from single-run LLM noise

Single-week LLM diffs are noisy by nature: a model may cite /index.md on Monday, paraphrase HTML on the next run, or shift phrasing after a silent provider checkpoint upgrade. Every Tuesday morning, a two-tier judge extracts structured entities, ranks and claims with Claude Sonnet 5.5 (cached in D1 so historical runs are never re-billed) and hands them, together with 28-day half-life exponentially weighted moving averages across Search Console, Bing, bot crawls and human AI referrals, to Claude Opus 5.5 (with automatic Gemini 4 fallback) in closed-book JSON mode. Stochastic one-run blips are separated automatically from confirmed multi-week shifts.

System Architecture · Interactive Schematic

Two isolated Workers, nine APIs, one closed verification loop

Select any subsystem node or numbered tab below to trace its data conduits, authentication boundary, cron schedule and Cloudflare D1 tables.

Closed-loop SEO and LLM observability architecture for andreasritter.ch Signal flow from the public Cloudflare Worker and machine-readable Markdown/JSON-LD endpoints through daily edge/search collectors and weekly 5-provider grounded/ungrounded LLM probes into Cloudflare D1, Tuesday 28-day EWMA + Claude Opus 5.5 drift synthesis, and the Zero-Trust Access telemetry studio. STAGE I · PUBLIC SURFACE STAGE II · SCHEDULED COLLECTORS & PROBES STAGE III · STORAGE & EWMA JUDGE STAGE IV · ZERO-TRUST ctx.waitUntil · 0 ms TTFB AI & search referrer upsert CLOSED-LOOP VERIFICATION · JSON-LD disambiguation, /index.md, /llms.txt, check_site.py, seo_aio_gate.py & IndexNow 01 · PUBLIC WORKER andreasritter.ch worker/media-ranges.mjs • Static Assets !-glob bypass • Link: </index.md> + /llms.txt • ProfilePage JSON-LD schema • Content-Signal: ai-input=yes Zero cookies · Zero JS trackers 02 · DAILY 05:17 & 23:50 UTC Edge & Search Collectors • Cloudflare GraphQL (25 crawler UAs) • Google Search Console (RS256 JWT) • Bing Webmaster + Copilot Index via GitHub Actions (bypasses ThrottleIP) + IndexNow ping on main deploys 03 · MONDAYS 06:30 UTC · 6x5 MATRIX Multi-LLM Grounding Probes • OpenAI Responses (gpt-6.1-sol) • Anthropic Messages (claude-sonnet-5-5) • Google Gemini (gemini-4-hydrogen) • Brave Search (llm-context) & Answers Grounded (RAG) + Ungrounded (Weights) + Live provider model currency check 04 · CLOUDFLARE D1 SQLite Ledger (11 tbls) • Parameterized .bind() SQL • Balanced AST (depth <= 18) • Scanner 403/404 purge • redactSecrets() wire scrub Brave ToS ephemeral guard 05 · TUESDAYS 06:30 UTC EWMA & Drift Judge • 28d half-life kernel 2^(-dt/28) • Sonnet 5.5 cached extraction • Opus 5.5 cross-channel judge • Blip vs. confirmed_shift Gemini 4 automatic fallback 06 · ACCESS STUDIO telemetry. andreasritter.ch • CF Access + RS256 in-Worker JWT verify • Fail-closed 403 • 3 Design Editions: 00 Studio 01 Monograph 06 Kunstkammer 2D • Live SSE Run Console • Multi-turn LLM Wire follow-up debugger strict CSP 'self' workers_dev: false no_bundle: true 0 npm runtime deps

01 · Public Edge & Machine-Readable Surface (andreasritter.ch)

Static subresources (/assets/*.css, *.js, /assets/img/*, fonts) bypass the Worker entirely via negative globs for zero Worker invocations. Document requests pass straight through env.ASSETS.fetch() while ctx.waitUntil asynchronously aggregates non-bot 2xx/3xx external Referer hosts and AI utm_source citations (chatgpt.com, claude.ai, perplexity.ai, copilot.microsoft.com, gemini.google.com) without cookies or client beacons. HTTP Link headers advertise /index.md alongside JSON-LD ProfilePage disambiguation and Content-Signal directives.

Schedule / Trigger
Every request · 0 ms TTFB overhead
Security & Auth
Public HTTPS · Strict CSP ('self') · Zero cookies
Endpoints / Modules
HTML /, /index.md, /llms.txt, /robots.txt, /sitemap.xml, worker/media-ranges.mjs
D1 Persistence
edge_referrers_daily (via ctx.waitUntil)
API & Protocol Surface

Nine direct API integrations, zero SDK bloat

Every collector runs on Web-standard fetch and crypto.subtle inside plain ES modules (no_bundle: true) with zero runtime npm packages. If any secret is absent, its lane degrades cleanly without blocking sibling collectors.

Integration & Endpoint Cadence Auth & Engineering Pattern Verified Signal
Cloudflare GraphQL Analyticsapi.cloudflare.com/client/v4/graphql Daily 23:50 UTC Scoped Analytics Read token · Balanced binary AST filter 25 search, RAG user-fetch & training bot UAs across HTML, /index.md & /llms.txt, plus HTTP 401/403/429 WAF block alerts
First-Party Edge Referrer Hookworker/media-ranges.mjs · ctx.waitUntil Real-Time Edge In-Worker D1 binding · Zero cookies · Zero client JS Human click-through visits from chatgpt.com, claude.ai, perplexity.ai, Copilot, Gemini, Search & Scholar
Google Search Console APIgoogleapis.com/webmasters/v3 Daily 23:50 UTC PKCS#8 RS256 JWT signed natively via crypto.subtle Lag-compensated DE/EN query impressions, clicks, CTR & weighted SERP rank climbs
Bing Webmaster & Copilot Indexssl.bing.com/webmaster/api.svc/json Daily 05:17 UTC scripts/sync_bing.py via GitHub Actions -> D1 HTTP API Bypasses Bing ErrorCode 17: ThrottleIP on shared Worker egress IPs; tracks Bing & Copilot grounding queries
IndexNow Instant Notificationapi.indexnow.org/indexnow On Main Deploy Verified key file + post-deploy smoke gate (check_live.py) Pings Bing, Copilot and partner AI search indexes immediately when meaningful site/ content changes
OpenAI Responses APIapi.openai.com/v1/responses · gpt-6.1-sol Mon 06:30 UTC Live web_search tool vs. grounded=0 parametric probe URL citations (HTML vs. /index.md), DE/EN entity fact recall & Swiss utility SAP S/4HANA discovery
Anthropic Messages APIapi.anthropic.com/v1/messages · Sonnet & Opus 5.5 Mon & Tue 06:30 web_search_20250305 probe + Two-tier closed-book Drift Judge Grounded vs. trained-memory comparison on Mondays; cached feature extraction & cross-channel synthesis on Tuesdays
Google Gemini APIgenerativelanguage.googleapis.com · gemini-4-hydrogen Mon 06:30 UTC google_search grounding chunks + automatic Drift Judge fallback Google-grounded citation attribution, parametric memory gap & live model catalog currency checks
Brave Search & Brave Answersapi.search.brave.com · llm-context & chat/completions Mon 06:30 UTC Independent search index · Ephemeral RAM scoring per Brave ToS Verifies independent non-Google/non-Bing retrieval context while scrubbing raw snippet prose before D1 write
Verification Outputs

What the studio surfaces, and why it matters

Dashboards that only count pageviews miss how technical buyers and recruiters actually research today: inside grounded AI answers that summarize before anyone clicks.

Interactive Synthetic Sample · Zero Network Calls

Explore the full telemetry studio with 365 days of synthetic data

Because the private production instance on telemetry.andreasritter.ch is gated behind Cloudflare Access and still building up its first multi-month baseline, I generated a public interactive sample directly from the production Worker code and SQLite schema. Switch 7d / 30d / 90d / 365d windows, compare Grounded vs. Trained Memory answers, inspect 28-day EWMA drift reports, trigger simulated live SSE runs, and flip between 00 Studio, 01 Monograph and the 06 Kunstkammer 2D circuit bench.