Solutions engineer · Security technology · AI-built tools

From field problems
to working software.

I'm Ky Gray, a solutions engineer with 20+ years in IT and security technology. I turn real-world operational problems into working software.

Open to Solutions Engineering, AI-enabled SaaS, security technology, and technical customer-facing roles.

Download resume Explore projects ↓

What I bring

Solutions Engineering

Discovery, demos, technical validation, solution design, RFPs, integrations, and handoff.

Security + IT Domain Experience

20+ years across physical security, access control, video, networking, cloud platforms, and APIs.

AI-Assisted Product Development

Turning operational problems into working SaaS, voice AI, and workflow apps.

Business Translation

Connecting customers, sales, and engineering to turn requirements into practical solutions.

Proof of Work

Working applications, not mockups. Each one solves a problem I've seen in solutions engineering, security delivery, field service, or contractor operations.

Engineering case studies: the constraints, decisions, failures, and measured results behind NightAgent and Ask Ky.

SE Command Center opportunity dashboard with active opportunities and attention metrics
01 / Solutions engineering

SE Command Center

Interactive demo + guided tour

Keep every technical opportunity, dependency, deadline, and next action visible from discovery through handoff.

View project details →
SightFlow workspace showing security survey and engineering projects
02 / Security system design

SightFlow

Carries each security project from field survey to equipment planning, BOM, and print-ready handoff documents.

View project details →
Ask Ky assistant showing suggested questions Ask Ky answer with supporting source labels
03 / AI portfolio assistant

Ask Ky

A Claude API assistant that answers questions about my background from a curated knowledge base, and shows its sources.

View project details →
PowerQuote business overview showing urgent customer follow-up priorities
04 / Contractor operations

PowerQuote

Interactive demo + guided tour

Keep customer requests, conversations, quotes, and invoices moving in one place.

View project details →
PicTalk capture screen with Take Photo, Tap to Talk, and Save This Stop buttons PicTalk saved stops showing camera photos with transcribed voice notes
05 / Field capture

PicTalk

Live app · Try it on your phone

Offline-first site walks: photos and voice notes save on the phone, sync to Firebase, are transcribed by Deepgram, and become an AI summary and quote with the Claude API.

View project details →
NightAgent demo page: a simple call panel with a status circle and one Start call button beside a live ticket board
06 / AI service agent

NightAgent

Live voice demo · Hands-free, call to outcome

An AI voice agent for a security integrator. Sam answers after-hours calls, opens a triaged ticket, then calls the customer back to confirm the fix. ElevenLabs Agents, Python FastAPI, Supabase.

View project details →
Bluey, a blue orb, answering a clear request to text the boss about running late by simply writing the message, with Copy and Play again buttons Bluey answering the vague request My boss wants a report by asking what the report should cover
07 / AI companion

Bluey

Live alpha · Try it on your phone

An AI companion for people who don't think of themselves as AI users. A built-in "brain" decides whether to just do the task, ask one question, or suggest a better way, so no prompt engineering is needed. OpenAI API on Vercel.

View project details →
PC Medic Today screen: Your PC looks healthy, with Speed, Storage, Battery, Updates and Stability tiles in plain English
08 / Windows diagnostics

PC Medic

Windows installer · Download and run

A Windows app that checks the real computer before it answers: hardware, logs, updates, crashes, and performance. Plain English for home users, raw evidence for technicians, and AI help only with the user's approval.

View project details →
PropertyIQ portfolio overview dashboard showing 55 synthetic properties, 4 flagged as underperforming, and an Ask PropertyIQ chat panel
09 / Private AI analytics

PropertyIQ

Case study + simulator demo · Self-hosted, synthetic data

A self-hosted AI analytics and lending prototype. Code does the math from PostgreSQL, a local Qwen3 model only explains it, and every figure traces to its source. No external LLM API.

View project details →

Other projects

WeldMateWelding field companion
10 / Learning & field tools

WeldMate

Calculate, learn, practice, and reference core welding concepts in one mobile-first field companion.

View project details →
Last Light Outpost base defense game at wave 19 with turrets and upgrade options
11 / Interactive game design

Last Light Outpost

Defend a generator, build your base, and adapt your strategy through escalating zombie waves.

View project details →

How I build

Field experience, workflow design, and AI-assisted development, from idea to working software fast.

01

Solve real problems

I start with the workflow, not the technology: repetitive tasks, disconnected processes, and friction I've seen in the field.

02

Design the experience

I map steps, roles, and handoffs the way I'd scope a customer solution, then keep the interface simple.

03

AI-assisted development

I own the requirements, architecture, UX, and testing, and use Claude Code, ChatGPT, and Gemini to build faster. My background in IT, SQL, PHP, scripting, and APIs lets me check what gets built.

04

Ship and improve

I deploy with GitHub, Vercel, and Firebase, use Supabase, Firestore, and SQL for data, and keep refining each tool through real use.

ClaudeChatGPTGeminiClaude CodeClaude APIElevenLabsDeepgramNext.js & ReactJavaScriptPythonFastAPISupabaseFirebaseSQLGitHubVercel
01 / SE Command Center

Keep the next move clear on every opportunity

The problem

SE work (discovery, demos, RFPs, security questionnaires, handoffs) is spread across tools, so blockers, owners, and deadlines get lost.

The workflow

Opportunities move by stage from discovery to handoff. My Focus shows what needs attention, dependency tracking shows who you're waiting on, and calendar views turn deadlines into a plan. An Impact view shows the pipeline supported per SE hour. Suggest next step has Claude draft the next action, owner, and due date; nothing changes until the SE saves it.

Try it yourself

Explore a fictional SE workspace with 26 sample opportunities, RFP and InfoSec deadlines, and a guided tour.

Launch Interactive Demo ↗

Fictional data, no sign-in. Changes stay in your browser tab.

How I built it

Built in a few hours over about 60 iterations with ChatGPT and Claude, modeled on how I ran opportunities as an SE. Next.js and TypeScript on Vercel; my own workspace is behind a server-checked password.

Technologies & design

Next.js & TypeScript Interactive demo and guided tour Claude API ChatGPT Claude GitHub Vercel Stage-based pipeline RFP & InfoSec tracking Dependency tracking Calendar planning SE impact & pipeline ROI
02 / SightFlow

One project record from survey to handoff

The problem

Security projects lose time and accuracy when field notes, device layouts, estimates, and installation instructions are managed separately.

The workflow

A guided site survey by area feeds a design workspace for equipment, labor, and BOM, then produces sales and installer handoff documents.

How I built it

Built from years of walking sites, over 149 iterations with ChatGPT, Claude, and Gemini. A static JavaScript app on Vercel with Supabase sign-in and project storage, JSON import and export, and built-in self-checks.

What's inside

A labor engine, cable takeoffs by type, IDF assignments with Mercury controller capacity validation, Verkada license and PoE rules, automatic NVR balancing, and lift scope review.

Demo project

A fictional 16-area hospital with 271 device records, 43 reader locations, 26 cameras, and about 41,000 feet of cable, producing a complete work order and sales BOM.

Technologies & design

JavaScript Supabase Auth Supabase (Postgres) JSON import and export Camera photo capture Print-ready handoff documents Built-in self-checks Vercel
Open SightFlow (sign-in required) ↗
03 / Ask Ky

Turn a static résumé into a conversation

The problem

Recruiters have specific questions a résumé can't answer at a glance: has he done this, with which tools, and how does it fit our role? Scrolling a long portfolio to find out takes time they don't have.

The solution

Ask Ky turns the portfolio into a conversation. Visitors ask in their own words and get a short answer with the sources it came from.

  • Typed or spoken: tap the microphone and the browser's speech recognition sends the question.
  • Suggested questions help a visitor get started, and follow-ups like "tell me more" keep the context.
  • Check fit for a role: paste a job description and see how my background maps to each requirement.
  • Next steps: download my resume or leave contact details without leaving the chat.
  • Stays on topic: off-topic or unsupported questions get a polite boundary, not an invented answer.

How it works

A Vercel serverless function keeps the API key on the server, limits input, and rate-limits. Keyword retrieval picks the most relevant of about 40 knowledge-base sections, Claude answers only from them, and the server drops any citation it didn't send.

Claude Haiku 4.5 replies in JSON: the answer, the sections it cited, and whether it really answered. The browser shows the answer as plain text, never HTML.

Check fit for a role uses the same function but sends every section, so a match isn't limited by what retrieval picked. Visitor questions are logged, so I can see what recruiters actually ask and fill gaps in the knowledge base.

How I built it

I curated the knowledge base: about 40 sections on my experience, certifications, and every project, updated whenever a project changes. I chose keyword retrieval with synonyms over embeddings because it's simple, free to run, and easy to debug when an answer misses.

Two test scripts keep it honest. A retrieval test runs 106 realistic recruiter questions, many worded differently from the knowledge base on purpose, through the real retrieval code at no API cost: 105 find a section that answers them. A red-team script attacks the live endpoint with prompt injections and jailbreaks (see how I hardened it).

Technologies & design

Claude API JavaScript Vercel serverless function Keyword retrieval Source-grounded answers Server-side input limits Job-fit matching Voice input (Web Speech API) Prompt-injection test script GitHub
How I hardened it →
04 / PowerQuote

A clearer path from first contact to payment

The problem

Small electrical contractors can lose track of customer requests when calls, texts, quotes, and follow-ups live in different places.

The workflow

PowerQuote keeps every customer request in one place, from the first message to the paid invoice.

  • Leads and conversations in one inbox, with urgent requests flagged for a person to follow up.
  • Quotes built line by line with parts, labor, and tax, sent to the customer by secure link.
  • Invoices and customer feedback close out each job.
  • Company dashboards surface the next action; a platform view shows activity and quote progress across companies.
  • English and Spanish, with role-based access for each company's team.

Try it yourself

Explore a fictional electrical contractor account with sample leads, quotes, and invoices, plus a guided tour.

Launch Interactive Demo ↗

Fictional data only; external messaging is disabled.

Technologies & design

Next.js & React Supabase Role-based access Real-time messaging English and Spanish Interactive demo and guided tour Vercel
Open PowerQuote ↗
05 / PicTalk

Talk through the site walk instead of typing it up later

The problem

On a site walk, contractors take dozens of photos and quick notes. By the time they're back at the office, the context is gone, and someone has to rebuild it from memory before the estimate can start. Details like model numbers and what the customer asked for get lost.

The experience

Take a photo, tap to talk, save the stop. PicTalk pairs each photo with a voice note and its transcript, and groups stops by job.

  • Works with no signal: installs like an app; stops wait on the phone, then upload and transcribe automatically.
  • Describe photo: Claude reads the photo, copies model and serial numbers exactly, and notes visible condition, without guessing.
  • Wrap-up notes: record field notes and customer comments before ending a job. On Android, words appear as you speak, and you can pause and fix the text.
  • PDF report: each photo with its transcript and the time it was taken, shared straight from the phone.
  • AI job summary: ranked action items linked to their stops, marked as AI-written; only an approved summary goes in the PDF report.
  • Piccolo: turns a finished job into a work order, parts list, and quote. Every line links to its photo; the estimator edits, prices, and finalizes. Field techs never see prices.
  • Help when stuck: tap ? and ask PicTalk's help chat, by typing or by voice.

Piccolo finalizes a numbered version that can't be changed and exports it as a PDF, CSV, or JSON. A company can invite estimators, field techs, and installers, and an admin console tracks each job from captured to quoted, won, and installed. Each final records what the estimator changed from the AI's draft, so later drafts reuse the company's own wording, part numbers, and prices.

How it works

  • Stops queue in IndexedDB, upload to Firebase Storage, then write one Firestore record, so a record never points to missing files.
  • Cloud Functions send audio to Deepgram with a security-trade vocabulary.
  • Live words: a Cloud Function trades the server-held Deepgram key for a 30-second token, so the key never reaches the phone. Words show gray while Deepgram decides and white once final, and pausing closes the connection so silence isn't billed. If the connection drops, the full recording is transcribed instead, and typed text is never overwritten.
  • Describe photo: the tap just marks the stop, so it works offline. A Cloud Function claims the request so it runs once, waits for the voice note's transcript, shrinks the photo, and sends both to Claude. A delete during the run wins.
  • Claude returns JSON in a fixed schema. Code checks every line points to a real stop, marks unconfirmed part numbers Verify, and never invents prices.
  • No sign-up to start: everyone gets an anonymous account, and signing in with Google or an email link keeps that same account, so nothing has to move.
  • Security rules limit every record to its owner or company role, tested against Firebase emulators.
  • AI summaries and photo descriptions are capped per job and per account per day, to keep costs predictable.
  • Engineering Mode shows whether a slow stop was the phone's signal, the upload, or the speech-to-text service. It's off by default and shows each user only their own data.
  • The Evaluation Lab cuts the signal at the worst moments. The first run caught three bugs; after the fixes, all 21 runs pass (October 4, 2026).

Try it yourself

QR code that opens PicTalk at pictalk-6cbff.web.app

Scan with your phone's camera. No sign-up: seven example jobs to explore. Then tap Piccolo (quick sign-in) for a sample work order, parts list, and quote.

Open PicTalk ↗View the code on GitHub ↗See the Evaluation Lab ↗

Demo: designed for phones, up to 10 stops per job. Voice recordings are deleted after 5 days.

Where it's going

Next: quote approval by secure link, email delivery, and export into estimating tools and CRMs.

How I built it

I built PicTalk with Claude Code, Anthropic's AI coding agent, and learned Firebase, Node.js, and Git along the way. I started with the site walk itself (photo, voice, save) and made it work with no signal before adding any AI.

Then I made the hard parts measurable. Engineering Mode shows where the time goes on each stop, and the Evaluation Lab drives the real app in a phone-sized browser while cutting the signal. Its first run found that losing signal mid-sentence kept only the words heard before the drop. Now a lost signal transcribes the whole recording, and all 21 runs pass. I also tested on a real Android phone with made-up customers.

Technologies & design

Claude Code React Vite Firebase Auth (anonymous, Google, email link) Cloud Firestore Cloud Storage Cloud Functions Deepgram speech-to-text Live streaming (WebSocket) Short-lived API tokens Claude API Structured JSON output Claude vision (photo descriptions) Offline-first (IndexedDB) Engineering Mode (observability) Evaluation Lab (offline simulator) Installable PWA Service worker Role-based security rules Emulator test suite Firebase Hosting
Scripted demo, sample data · built from the app's real screens

Take a photo and say what you see: PicTalk saves both as one stop, describes the photo, and lets you fix any word.

How a PicTalk job is saved, transcribed, and summarized 1. On the phone, the PicTalk web app saves the photo and voice note to the phone first, in IndexedDB, so it works with no signal. 2. When online, it uploads the photo and voice note to Firebase Storage under the user's folder; rules allow owner-only access and voice files are deleted after 5 days. 3. Only after both files upload, it writes the stop record to Firestore with the file paths, job, time, and status. 4. The new record triggers the transcribeStop Cloud Function, which downloads the voice note and sends it to Deepgram with security-trade keyterms. 5. Deepgram nova-3 returns the transcript. 6. The function saves the transcript and status on the same stop record, and the phone's live listener shows it on the stop card. 7. After End Job, once the transcripts are ready, the generateJobSummary Cloud Function reads them without changing them and asks the Claude API for JSON: a summary and prioritized action items, each tied to its source stops. It checks every stop reference and retries once. Wrap-up notes (field notes and customer comments) are transcribed live: a Cloud Function issues a 30-second Deepgram token, the phone streams audio to Deepgram over a WebSocket, and batch transcription is the fallback when the connection drops. They are the summary's highest-priority input. 8. The draft is saved separately and marked as an AI draft; the user edits and approves it, and only an approved summary goes into the PDF. A job with no speech gets no summary. 1 Phone: PicTalk web app (offline-first) Photo + voice note saved on the phone first (IndexedDB), so it works with no signal upload when online (anonymous sign-in) 2 Firebase Storage photos/{user}/{stop}, voice/{user}/{stop} Owner-only rules; voice files deleted after 5 days after both files are uploaded 3 Firestore: the stop record users/{user}/stops/{stop}: file paths, job, time, status. Written last, so it never points to files that aren't there new record triggers 4 Cloud Function: transcribeStop Downloads the voice note from Storage Adds security-trade keyterms (PoE, NVR, ...) audio 5 Deepgram speech-to-text (nova-3) Returns the transcript transcript 6 Transcript saved on the same record Status: transcribed, no speech, or failed The phone's live listener shows it on the stop after End Job, once transcripts are ready 7 Cloud Function: generateJobSummary Reads wrap-up notes first, then stop transcripts (never changes them). Claude API returns JSON: a summary and action items, each tied to its sources; checked; retries once draft saved separately 8 Review, approve, export Marked AI draft; user edits and approves it Only an approved summary goes in the PDF No speech in the job means no summary Stops are grouped into jobs; one job is open at a time. Wrap-up notes are transcribed live: a Cloud Function issues a 30-second Deepgram token, the phone streams audio over a WebSocket, and batch transcription is the fallback.
How a PicTalk job is saved, transcribed, and summarized · the actual data path

Engineering Mode pictures were taken in the local test environment, where speech-to-text and the AI are free stand-ins, so their times show near zero. Upload, sync, and offline timings are real browser measurements.

Piccolo pictures show the made-up "Try Piccolo" sample job on the test site, drafted by Claude; the prices were entered by hand, as an estimator would.

Phone pictures are from testing on an Android phone with made-up customers.

06 / NightAgent

Stay with a service call from the first ring to a confirmed fix

The problem

After-hours calls reach an answering service that can only take a message. Emergencies wait with routine requests, and nobody checks that the fix held.

The experience

Sam, the AI voice agent, answers the night desk for a demo security integrator:

  • Checks safety first, finds the account, confirms the caller's details, and opens a ticket on a live dispatch board. Emergencies page the on-call tech.
  • Takes messages for any department and hands billing and sales calls to two specialist AI agents, Jordan and Riley.
  • After the simulated repair, NightAgent calls the customer back. The answer closes, reopens, or escalates the ticket, or creates a sales lead.
  • Built for non-technical users: one button, plain-English status, voice or typing.
  • Options for slower speech and bigger text, one of five voices on each call, and it installs on a phone's home screen like an app.

How it works

ElevenLabs Agents handles speech and voice in real time. Sam calls tools on a Python FastAPI backend (look up customer, create ticket, page tech, take message), authenticated with a shared secret. The model suggests a priority, but rules in code decide: it can raise priority but never downgrade an emergency, and a ticket lifecycle in code prevents skipped stages. Every step is saved to Supabase, and a live Business Impact panel counts calls, fixes, and leads, with no invented revenue.

The follow-up call is a second ElevenLabs agent. A single-use pass ties it to the ticket, the agent reports what the customer said in one structured tool call, and code decides the outcome:

  • Confirmed fix: the ticket closes.
  • Problem came back: the ticket reopens and the priority is re-checked.
  • Repair never worked: it escalates to the service manager.
  • Upgrade interest: a sales opportunity for the account executive, value TBD unless the customer names a budget.
  • Unclear: a person follows up instead of the AI guessing.

Every call also gets a call check: up to nine checks, mostly computed from the call's records, with two graded by ElevenLabs from the transcript: no unsupported promises, and the caller's details confirmed before acting.

How I engineered it

ProblemAfter-hours calls need the right urgency. A missed emergency can leave a site unsecured overnight; a false one sends a technician out at night for nothing.
ConstraintThe AI can't be the final judge of priority, and the demo is open to anyone, so it has to be safe to leave running.
DecisionRules in code set the final priority and decide what happens after each call. Sam suggests a priority; the code can accept a higher one but never lowers an emergency.
Hard partThe same problem arrives in different words ("our gate is stuck open", "the gate still sticks"). Some calls sound odd but aren't a problem yet, like a cat staring at the electrical panel; others are worse than they sound, like a burning smell from the alarm panel.
What I tried firstPutting the rules only in Sam's instructions. With this model that wasn't reliable: Sam sometimes skipped reading back the caller's name and number. Moving the next step into each tool's answer, so the server tells Sam exactly what to do, fixed it.
Evidence21 regression tests run 3 times each against the live agents, including five prompt-injection attempts, plus 24 voice tests with real audio in noise and over a phone line. Every fix is re-tested against every test.
LimitsReal-call samples are still small, voice tests use recorded voices and a simulated phone line, and dispatch is simulated.

Guardrails and testing

  • Never asks for alarm codes, explains bypasses, or invents account details, arrival times, or prices.
  • Calls are time-limited, rate-capped, and accepted only from approved sites.
  • Engineering Mode times every tool call; the Evaluation Lab scores tests and real calls separately, with sample sizes.
  • Voice tests: 18 of 18 phone numbers heard exactly, about 1.7 seconds from the caller's last word to Sam's reply.
  • Failure injection replays known failures (a duplicate call, a paging outage) through the real server code in a sandbox.
  • A fixes log lists 14 problems found this way: why each happened, what changed, and whether the fix still holds in the latest runs.

Jargon Bench: does speech-to-text hear security jargon?

QuestionHow often do Deepgram and ElevenLabs hear trade terms like Verkada, Wiegand, NVR, and PoE correctly, and does keyterm boosting help?
Method44 recorded field sentences, each sent to Deepgram nova-3 and ElevenLabs scribe_v2 three times, with and without boosting. The scorer and accepted spellings were frozen before the first run.
ResultBoosting raised accuracy from 62.1% to 89.7% (Deepgram) and 79.3% to 95.4% (ElevenLabs), adding 9 to 21 ms. Unboosted, "Wiegand" became "weekend"; boosted, it sometimes wrote terms that weren't said.
LimitsOne speaker and 44 clips, so the results are directional, not definitive.

Try it yourself

  1. Press Start call (or type) and report a problem, for example: "This is Sunset Dental, 310-555-0142. Our back door won't lock."
  2. Sam opens a ticket. Hang up and watch it run: dispatched, en route, onsite, completed.
  3. When the button rings, tap Answer and tell Sam how the repair went, then see the outcome and Business Impact update.

Or ask about an invoice to meet Jordan, ask about adding cameras to meet Riley, or pick a scenario in Demo Mode to skip the first call.

QR code that opens the NightAgent demo at nightshift-dispatch.vercel.app/demo

Scan with your phone's camera. Press Start call and talk to Sam, or type instead, then watch the ticket on the dispatch board.

Try NightAgent ↗View the code on GitHub ↗

Made-up demo data; please don't share real names, numbers, or alarm codes. Conversations are processed and recorded by ElevenLabs. Later steps and staff are simulated.

Technologies & design

ElevenLabs Agents (4 agents) Multi-agent handoffs Real-time voice streaming (WebSocket) Python FastAPI Agent tool calls Rule-based triage Lifecycle state machine Event history Supabase / Postgres Signed webhooks (HMAC-SHA256) Web Audio Plain-language, accessible UX Agent evaluation Agent regression testing Voice testing with real audio Prompt-injection testing Failure injection Vercel
Scripted demo, sample data · the caller, Sam's lines, and the ticket are made up

A customer calls the after-hours line, Sam takes the call, a high-priority ticket lands on the board, and the call report checks how Sam did.

How a NightAgent call goes from first ring to confirmed fix 1. The caller talks to Sam from the demo page in the browser, by voice streamed over a WebSocket or by typing; calls end after 5 minutes. 2. ElevenLabs Agents handles speech recognition, the conversation, and Sam's voice. Sam checks safety first and tells the caller to call 911 if anyone is in danger. Browser calls are accepted only from approved sites. 3. Sam calls tools on the Python FastAPI backend, sending a shared secret: lookup_customer, create_ticket, page_on_call_tech, and take_message, and can hand the call to Jordan (billing) or Riley (sales). Server-side rules set the final priority: the model can escalate a ticket but can never downgrade an emergency. 4. The ticket and an event history for every step are saved in Supabase Postgres; the database key stays on the server. 5. When the call ends, Demo Mode moves the ticket through dispatched, technician assigned, en route, onsite, and work completed, one simulated step every 3 seconds, each labeled as simulated. The allowed order of stages is enforced in code. 6. The call button rings: a second ElevenLabs agent, the follow-up agent, calls the customer back with the ticket's details. A single-use pass ties the call to its ticket, and the agent reports what the customer said with one tool, record_follow_up_outcome. 7. Routing rules in code decide the outcome: close the ticket, reopen it and re-check the priority, or escalate it; open a new linked ticket; create a sales opportunity for the account executive with the value left to be determined; or create a callback task for the right team. 8. A Business Impact panel counts calls, emergencies, follow-ups, confirmed fixes, and leads live, with time saved estimated from real conversations only and no revenue figures. Sam never asks for alarm codes or gives bypass steps, and never invents arrival times or prices. 1 Caller: browser demo page Voice streamed over a WebSocket, or typed chat Calls end automatically after 5 minutes speech, in real time 2 ElevenLabs Agent: Sam Safety first: 911 if anyone is in danger Approved sites only (browsers) tool calls + shared secret 3 FastAPI tools Lookup, tickets, paging, messages, handoffs Rules in code set the final priority: the model can escalate but never downgrade an emergency ticket + every step saved 4 Supabase (Postgres) Tickets plus an event history for each one Database key stays on the server when the call ends 5 Demo Mode runs the job Dispatched, assigned, en route, onsite, done: one simulated step every 3 seconds, labeled Allowed stage order is enforced in code work completed 6 The phone rings: follow-up agent Sam calls back knowing the ticket's details A single-use pass ties the call to its ticket record_follow_up_outcome 7 Routing rules in code Close, reopen and re-triage, or escalate New linked ticket, AE lead (value TBD), or a callback task for the right team counted live 8 Business Impact panel Calls, emergencies, follow-ups, fixes, and leads Time saved from real conversations; no revenue Sam never asks for alarm codes or gives bypass steps, and never invents arrival times or prices.
How a NightAgent call goes from first ring to confirmed fix · the actual data path
07 / Bluey

Get better results from AI without learning prompt engineering

The problem

Many people don't think of themselves as AI users. They don't know what to ask or how much context to give.

The experience

Bluey is a friendly blue orb you talk to in plain language. A clear request gets done right away; a vague one gets one question first. When there's a better way, he finishes the task, then mentions it.

  • Steer buttons under every draft (Shorter, Warmer, More specific) teach by doing: each sends a plain message in your own chat.
  • Scam check: paste a text, email, or screenshot for a clear verdict, the red flags, and what to do next.
  • Practice talks: rehearse a hard conversation, then get kind feedback.
  • Reads PDF, Word, and CSV files, speaks his replies, creates PDF, Word, and Excel files, and shows openly licensed photos from Wikipedia.
  • Easier to use: bigger text, a slower voice, and simpler words.
  • A real character with a backstory and gentle humor, so he never sounds the same twice.

How it works

A Vercel serverless function keeps the OpenAI key on the server and calls the Responses API with a strict JSON schema: the reply, a mood for the orb, and a hidden "brain" record (mode, goal, and an initiative level from 0 to 4). Every OpenAI endpoint has input limits and hourly and daily caps.

Memory and optional Google sign-in: Bluey remembers your name and goals with an Undo on every save, never keeps sensitive data, and syncs across devices through Supabase with row-level security. Without sign-in, everything stays on your device.

Brain Lab: 27 test conversations (39 release-gate tests on the beta branch) run through the real chat endpoint, scoring task success, initiative, question discipline, and character. They caught "Make it shorter" dropping every fact from an email; after the fix, revisions kept every fact in 10 of 10 runs.

How I built it

Designed over a week with ChatGPT: who Bluey is for, when he acts or asks, his personality, and the memory database. Since October 6, 2026, built with Claude Code, with every feature gated on Brain Lab or browser tests, including on a real iPhone.

Technologies & design

ChatGPT Claude Code OpenAI Responses API Structured output (JSON schema) Photo understanding Speech-to-text Text-to-speech PDF, Word, and Excel generation Vercel serverless functions JavaScript LLM evaluation Regression testing Cross-browser troubleshooting Supabase Auth and Postgres (row-level security) Google sign-in (OAuth) Character and personality design User-controlled preferences Mobile-first, plain-language UX Vercel

Alpha in active testing. Chat history stays in your browser; please don't share sensitive information.

08 / PC Medic

Give everyday Windows users a technician who looks before answering

The problem

When a computer acts up, people get generic advice written for someone else's computer. A good technician looks at this computer first. PC Medic makes that first look available to anyone.

The experience

PC Medic installs like any Windows program. A three-second read-only check gives a one-line verdict and five status tiles: speed, storage, battery, updates, and stability.

  • Home mode speaks plain English; Technician mode shows raw values, error codes, and every Windows tool.
  • Ask in your own words: "can I add more RAM?" reads the actual slots and modules.
  • Investigations: "it keeps freezing" runs the right checks, correlates Windows logs, crashes, and drive health, ranks the likely causes, and offers the next test.
  • Guided fixes measure before and after. PC Medic never changes anything itself.
  • Deep checks: security posture, blue screens with the likely driver, Windows Update errors explained, and a read-only scan as administrator.
  • Technician reports ready to print and sign.

How it works

A local Python server runs read-only PowerShell and performance-counter checks. It answers on the PC when it can; otherwise Claude (with read-only tools and cited web search) or ChatGPT helps, only after the user approves, with serial numbers, names, and addresses stripped first. Every answer says who answered it.

It's secured like any local web server: bound to 127.0.0.1, DNS-rebinding and CSRF protection, per-account access on shared PCs, and API keys in Windows Credential Manager. A per-user installer (PyInstaller and Inno Setup) needs no admin rights and updates from GitHub Releases.

How I built it

Built with ChatGPT through version 1.16, then with Claude Code from October 10, 2026, which added investigations, guided troubleshooting, Deep checks, the redesign, and the installer. Over 200 automated tests mock every AI call, and install and upgrade were tested on real hardware. Not done yet: code signing and testing on more computers.

The deep scan needed administrator rights without running the whole app as administrator. PC Medic starts a second copy of itself through the Windows UAC prompt that runs only fixed read-only steps, writes only its own result file, and exits. A real-machine check also caught another AI's mistake: it had said my Lenovo laptop's RAM was soldered, and PC Medic correctly read removable SO-DIMM modules.

Technologies & design

Python Windows PowerShell Windows performance counters (PDH) Claude API Tool use Web search with citations OpenAI API Data minimization Local server security (DNS rebinding, CSRF, per-account access) Windows Credential Manager PyInstaller Inno Setup GitHub Releases updates UAC elevation (ShellExecuteEx runas) Crash dump analysis Security posture assessment Evidence correlation Windows event log analysis Windows 11 (Fluent) design Plain-language and technician UX ChatGPT Claude Code Regression testing

For Windows 10 and 11 laptops and desktops. The installer isn't code-signed yet, so Windows may show "Windows protected your PC": choose More info, then Run anyway. Works offline; AI answers need your own Anthropic or OpenAI key.

09 / PropertyIQ

Let a private AI explain the numbers without ever doing the math

The problem

Lending teams want AI answers, but their data can't go to a hosted model, and language models are unreliable at math. PropertyIQ runs the model next to the data, and the model explains results but never calculates them.

The experience

An analyst sees 55 synthetic properties across office, retail, industrial, and multifamily. Rule checks flag 4 as underperforming: occupancy below 85%, NOI down 10% or more year over year, or NOI at or below 90% of budget. Ask "Why was Westlake flagged?" and the answer links to its inputs, formulas, and record IDs.

It has grown into a lending workbench:

  • Loan screening: DSCR, LTV, debt yield, and stress tests, exported to PDF and to Excel with live formulas.
  • Document intake: rent rolls and T-12s from Excel, CSV, or scanned PDFs via local OCR, reviewed before use.
  • Red flags: 13 document checks, a market check, and California rules, each with its evidence and a suggested action.
  • Underwriting comparison: the analyst approves each adjustment with a reason code, and a summary built in code reports the result, for example DSCR moving from 1.58 to 1.00, failing the 1.25 minimum.
  • Debt dashboard: 46 synthetic loans, a maturity wall, a DSCR × LTV risk map, and a covenant watchlist.
  • AI Engineering Lab: request traces and a model on/off comparison.
  • Admin: a live security checklist, an internet lockdown switch, and backups restored and checked row by row.

How it works

Application code calculates NOI, trailing-12-month totals, variance, and occupancy from PostgreSQL. A code router picks a fixed, access-scoped query, and only verified facts reach a local Qwen3 model on Ollama. Every number it writes is checked; on a mismatch, a summary built in code is shown instead.

Following one question: the analyst asks "Summarize our underperforming assets." The API queries only the data that analyst may see, code computes the figures and rule results, the model writes the summary from those facts alone, and the interface shows it next to the formulas and source records.

Four roles with fund-scoped access enforced in SQL; a hidden loan returns the same "not found" as one that doesn't exist. It's a prototype on synthetic data; production hardening is still to do.

How I built it

I built PropertyIQ with Claude Code on one Windows 11 laptop: Next.js 16 and React 19 for the interface, a FastAPI (Python) API, PostgreSQL 17 in Docker, and a 4-billion-parameter Qwen3 model served by Ollama. Documents are read with RapidOCR and pdfplumber, and exports use ReportLab and openpyxl, all on the same machine.

One rule shaped every module: code does the arithmetic and makes the decisions, and the model only explains. The loan tools use no AI for any number, each Excel export is recalculated in OpenOffice during testing and must match the app, and traces never store the question or answer text.

Try it yourself

The real app runs locally, so a browser simulator recreates its main screens with synthetic data.

Launch simulator demo ↗

Synthetic data only, no sign-in. It runs in your browser and nothing is saved or sent. The chat is scripted; in the real app, answers come from a local model.

Technologies & design

Ollama Qwen3 (local model) Python FastAPI Next.js & React PostgreSQL Docker RapidOCR Deterministic calculations Output number checks Role- and fund-based access Request tracing Claude Code
10 / WeldMate

Turn welding reference material into an interactive learning tool

The challenge

Welding students and field users often move between calculators, formulas, notes, procedure information, and practice material. WeldMate brings those activities into one focused mobile experience.

The experience

Calculators (heat input, fillet, V-groove, carbon equivalent), an eight-section learning path, quizzes, weld-symbol and inspection practice, and WPS practice cards, saved in the browser.

How I built it

Built with Google Gemini as a single mobile-first tool.

Technologies & design

Google GeminiHTML5CSSJavaScriptLocal StorageResponsive mobile UIInteractive calculationsVercel
Open WeldMate ↗
11 / Last Light Outpost

Build a base that can survive the next wave

The challenge

Make an accessible browser game where the player can see the consequences of each choice as enemy waves grow stronger.

The experience

Defend the last working generator for miles through escalating zombie waves. An active prototype I keep refining through play.

  • Fight, collect, build: zombies drop coins the player must pick up, then spend on walls, turrets, carrying capacity, facilities, and crew.
  • Choose a run: commanders with different abilities, several starting bases, and a full 56-wave survival mode.
  • AI Director: Fair adapts pressure to the player's defenses and eases off near defeat; Ruthless never lets up.
  • Forward operations: short missions with one clear goal at a time, like escorting a truck or landing a plane.
  • Daily challenges, bonus missions, and online leaderboards.

How I built it

The whole game is one HTML file of plain JavaScript, with no engine or build step. Progress saves in the browser and syncs to Supabase in its own game schema. Instead of passwords, each device gets a random ID and secret, and a temporary transfer code moves progress to another device. A service worker makes it installable and playable offline, with keyboard, mouse, and touch controls.

Technologies & design

Browser game Interactive systems Progression design Responsive controls Vercel
Play Last Light Outpost ↗

Engineering case study · Ask Ky

How I hardened a public-facing LLM app

Anyone can type into Ask Ky, so every message is untrusted input. Here are the controls, and their limits.

01

The key stays on the server

The Claude API key is read only inside the serverless function. Visitors never see error details.

02

Every input has a limit

Questions are capped at 500 characters, history at 4 turns, and job descriptions at 8,000. Replies are capped at 600 tokens.

03

Answers stay grounded

Only retrieved knowledge-base sections reach the model. Citations to anything else are dropped, and answers render as plain text.

04

Built to resist prompt injection

Visitor text only enters as a user message, and the prompt holds no secrets, so a leak reveals rules, not data.

05

Tested, not assumed

A red-team script attacks the live endpoint with overrides, prompt extraction, jailbreaks, and injected job descriptions. In a 9-case run (September 30, 2026), every attack was declined.

06

Privacy in the knowledge base

Names from my executive protection work are generalized, and my contact details are never given to the model.

Known limits

  • Rate limits live in server memory and reset with new instances: enough for casual abuse, not a determined attacker.
  • The browser sends the conversation history, so an earlier reply could be forged. Signing replies on the server is the next fix.
  • Refusals rely on the model following its rules; there's no separate classifier.
  • Visitor questions and contact-form details are kept in Vercel's logs for review.
About me

Security expertise meets product thinking.

20+ years across IT, networking, software, and electronic security. As a solutions engineer, I turn complex customer requirements into designs, estimates, demos, integrations, and deployment plans.

Now I pair that with product thinking and AI-assisted development. I'm looking for roles that bridge customers, sales, engineering, and technology.

Let's talk about what you're building.

Solutions engineering, security technology, and useful software are where I do my best work.

Back to Home ↑

Connect on LinkedIn ↗

Email Ky

Send Ky a message directly from the portfolio.