Skip to content
kennyski.com

Kenny Sarnoski · AI engineer

I build AI that ships.

Not demos. Not wrappers. A pipeline that writes its own fuzzing harnesses and re-found a real CVE in three seconds. A detector that catches AI-driven intrusions by the way they narrate themselves. A voice assistant that's the same person on four kinds of hardware.

Every number on this page traces back to a proof file or a test run.

What I do

Hire me for the parts that are hard to fake.

Agents that do real work

LLMs wired to systems that act — with the permission model worked out before the demo.

  • Multi-provider harnesses with genuine tool parity, not lowest-common-denominator shims
  • MCP servers, including a metered one billing per call
  • Tiered consent as architecture: read, act and commit as separate grants
  • Audit trails, paper-mode defaults, human confirmation on anything destructive

Security for the agentic era

Both sides of the fence — finding the bugs, and catching the AI that hunts them.

  • Autonomous vulnerability discovery: harness generation, fuzzing, adversarial validation
  • Runtime detection of LLM-driven intrusion before the destructive step
  • Memory-safety research on widely deployed C libraries
  • Responsible disclosure built into the pipeline, not bolted on after

Evaluation you can audit

Anyone can demo the run that worked. I write down what I expect first, then publish what happened.

  • Predictions locked in writing before the code is written
  • Retros comparing prediction to outcome — including the misses
  • Deterministic reproduction as a gate, not a nice-to-have
  • Adversarial negative corpora designed to trip my own detectors

Voice AI that ships

Real-time speech systems end to end — on hardware, phones and the web.

  • Streaming duplex voice over WebSocket with sub-second turn latency
  • One protocol, many clients: iOS, Android, embedded Linux, browser
  • Rime, Whisper, on-device recognizers — chosen per platform, not per fashion
  • Barge-in, echo cancellation, VAD and voice ID

Retrieval that stays current

Knowledge graphs and hybrid search that keep a model grounded in verifiable data.

  • Graph-backed retrieval with a trained reranker in production
  • Hybrid search: lexical, vector and graph rescoring together
  • Daily ingest pipelines that stay fresher than any training cut-off
  • Embeddable RAG for client sites, on Workers or your own box

Ship it and run it

The unglamorous half: deploys, services, installers, uptime.

  • FastAPI and Node services on AWS behind Caddy, systemd-managed
  • Staged deploys — validate, staging, smoke test, prod
  • Desktop distribution: Tauri, Electron, signed macOS DMG, Windows builds
  • Mobile release paths including Play policy and sideload tiers

Selected work

Things I actually built.

Quarry

In buildPrivate

An eight-stage vulnerability-discovery pipeline.

Point it at a codebase and it hunts memory-corruption bugs on its own — writing its own fuzzing harnesses, proving the crashes in a sandbox, and trying to disprove its own findings before it reports them.

Eight stages, each its own subsystem: recon, hunt, adversarial validation, dedupe, cross-repo reachability tracing, feedback, findings ledger, and CVSS-scored disclosure. Around 66,000 lines with 107 tests.

The part I'm proudest of is harness generation. Given an unfamiliar C library, Quarry reads the headers, infers a fuzzing entry point from the function signatures alone, pairs it with the right cleanup call, generates a libFuzzer harness, and compiles it in a hardened container — no curated template, no hand-written protocol knowledge. Fuzzing backends cover C, Go, Java, Python and Rust.

Validation is adversarial by design: a separate agent with a different prompt tries to knock down each finding before it survives to the report. Findings that can't be reproduced don't ship.

Every milestone was run predict-then-ship — I write down what I expect the run to do, lock it before writing the code, then publish a retro comparing prediction to outcome. The eval directory is predictions and retros side by side, including the ones I got wrong.

Receipts
Given cJSON with no template and no seed corpus, Quarry inferred the entry point from the C signatures, generated a harness, compiled it in 614 ms, and re-found CVE-2023-53154 — a heap over-read in parse_string — in 2.98 seconds and 488,193 executions. Reproduced deterministically across two runs.
Scale
~66k lines · 107 tests
Pipeline
8 stages, recon → disclosure
Fuzz backends
C · Go · Java · Python · Rust
Method
Predict-then-ship, retros published
TypeScriptEffectlibFuzzerAddressSanitizerDockerClaude Agent SDK

Aris Sentinel

In buildOpen source

Catching AI attackers by the one thing they can't stop doing.

Autonomous LLM attackers narrate their own intent. Humans never do. Sentinel scores for that narration and stops the intrusion phases before anything gets encrypted.

When an LLM-driven intrusion runs, its payloads arrive saturated with commentary — ranking targets by leverage, plan-act-observe labels, reasoning about how to evade detection. A human writes a terse obfuscated one-liner. An agent explains itself. That difference is present in the very first payload, well before the destructive step.

Detection is two-tier: a fast local feature filter handles the obvious cases, and anything ambiguous escalates to LLM adjudication. That keeps cost down without letting the subtle cases through.

The design bet is that it looks at the attacker's LLM, not the customer's code — so it's app-agnostic and ships with no per-customer tuning. It productizes the category, self-narration, rather than any one crew's signature, which is what stops it from being obsolete the moment somebody changes their prompt.

The hard part isn't catching attackers, it's not crying wolf at verbose-but-benign code. So the negative corpus is built from exactly the things that should trip it: chatty Docker entrypoints, first-person migration scripts, plan-shaped Kubernetes notes, verbose Terraform.

Receipts
Across a deliberately adversarial benign corpus — verbose Terraform, chatty Docker entrypoints, first-person runbooks — 0 of 12 false positives. Half escalated to tier-2 and all were correctly cleared. Separately, three attacks tier-1 missed came back AGENTIC at tier-2 with ≥0.97 confidence.
Tier-2 adjudication
5/5 correct
False positives
0 of 12 benign samples
Per-customer tuning
None
Validated on
Linux · Windows Server 2022
TypeScripteBPF / FalcoLLM adjudicationGo agentBun
github.com/kennysarnoski-jarvis/aris-sentinel

Aris

Shipping

One character. Four bodies.

A voice assistant that is the same person on an iPhone, an Android, a Raspberry Pi speaker, and the web — one wire protocol, four clients, no backend changes to add one.

Aris isn't an app, it's a character with a cloud brain and interchangeable bodies. The voice pipeline runs on youraris.com — a language model for the thinking, Rime for the voice, streamed back as mono 16-bit PCM at 24 kHz over a WebSocket.

Every client speaks that identical protocol. iOS came first. The Raspberry Pi 5 speaker was added as a thin client doing speech-to-text on-device. Android followed using the platform recognizer. None of them required touching the server.

That's the design bet: put the intelligence in one place and make the bodies cheap. Adding a new surface is a client, not a project.

Bodies
iOS · Android · Pi 5 · Web
Audio
24 kHz mono PCM, streamed
Backend changes per body
Zero
SwiftKotlinPythonFastAPIWebSocketRime TTS
youraris.com

Aris Code

ShippingPrivate

An agent harness, extended until it could hunt bugs.

I forked the open-source T3 Code harness and built the things it didn't have: three more model providers, a cross-session learning layer, and Quarry.

T3 Code is a solid open-source harness for driving coding agents. It ships with Codex support. What I wanted was provider independence and a security pipeline, so I built both on top of it.

Provider work: Qwen, DeepSeek and Kimi K3 adapters, each with full tool parity rather than a lowest-common-denominator shim — memory tools, web search, scratchpad, approval scoping, sub-agent fan-out, and reasoning-effort control wired per provider.

Continuous learning: the agent writes observations as it works, distils repeated failures into one-sentence 'instincts' with confidence that rises on corroboration and decays on contradiction, and injects the surviving ones into later sessions. Instincts corroborated across two or more projects get promoted from project scope to global. Opt-in, fail-closed, and it can never break a turn.

Being explicit about provenance: the harness is upstream open source and I'm one contributor among many there. Quarry, the provider adapters and the learning layer are mine.

Providers
Codex · Qwen · DeepSeek · Kimi K3
Monorepo
~318k lines · 364 tests
Upstream
Fork of T3 Code
TypeScriptEffectBunTurborepoReactElectron

Central Command

Shipping

Trading intelligence as a paid MCP server.

A crypto trading-intelligence MCP server that agents pay for per call — settled in USDC on Base, no accounts, no invoices.

MCPStreamable HTTPx402Base / USDC
centralcommand.io

Embedded RAG for client sites

ShippingClient work

Retrieval chat that drops into someone else's stack.

A custom RAG chatbot for a logistics client — embeddable widget on the front, Cloudflare Worker on the back.

Cloudflare WorkersVector retrievalTypeScript

Memory-safety research

Research

Hands on the libraries everything depends on.

Working the C libraries sitting under most of the internet — libxml2, libpng, libjpeg-turbo, libde265, cJSON, zlib.

ClibFuzzerAddressSanitizerCVE analysis

Work with me

Got something that needs to actually work?

Voice interfaces, retrieval systems, agents with real tools, or a second opinion on an AI build that's stalled. Tell me what you're trying to do.