# Kevin Timothy Muller > AI Engineer in London at Zebra Technologies. Builds LLM systems on Google Cloud that reach production: RAG assistants, LangGraph agents and NL-to-SQL analytics. Every fact below is also on https://kennytheboss05.github.io/portfolio/. - Portfolio (AI Engineer): https://kennytheboss05.github.io/portfolio/ - Portfolio (Applied AI): https://kennytheboss05.github.io/portfolio/applied/ - CV (PDF): https://kennytheboss05.github.io/portfolio/cv-ai-engineer.pdf, https://kennytheboss05.github.io/portfolio/cv-applied-ai.pdf - Email: ktimothymuller@gmail.com - LinkedIn: https://www.linkedin.com/in/kevin-t-m/ - GitHub: https://github.com/KennyTheBoss05 ## Profile (#about) Kevin Timothy Muller is an AI engineer based in London, UK, currently at Zebra Technologies. I build AI systems that reach production and stay there. At Zebra Technologies I own the GenAI platform behind a global sales organisation — RAG assistants, LangGraph agents and NL-to-SQL analytics on Google Cloud. I like the unglamorous half most: cutting a 12.7-hour pipeline to minutes, collapsing six LLM calls into one, proving a number right before anyone acts on it. Backend and data are mine end to end; interfaces I ship with AI coding tools. Applied framing: I turn LLMs into tools people actually use, then measure whether they do. At Zebra Technologies I own the GenAI platform behind a global sales organisation; my sales-playbook service launched to a 33-rep London cohort and lifted weekly conversations per rep by 66%. I take a stakeholder problem from first conversation to a shipped, measured tool on Google Cloud, and I care about the unglamorous half: proving a number right before anyone acts on it. I'm an AI engineer in London. I spend most of my time on the half of AI work that doesn't demo well: data pipelines, cost, fallbacks and proving numbers. Backend and data are mine end to end; interfaces I ship with AI coding tools. My eval and verification approach: prove a number against its source before anyone acts on it, as with call durations checked against the recordings across 2,073 calls. Score prompt and model changes against an eval set before they ship; the agent on this page has one covering grounded answers, refusals and prompt injection. And report the trade-off honestly, including negative results like the bimodal dissertation finding. Principles: Prove the number before anyone acts on it. (evidence: 2,073 calls checked against the recordings, section outreach) Put a deterministic fallback behind every LLM call. (evidence: persona routing falls back when the model is unsure, section playbook) Measure the trade-off, including when the new version is worse. (evidence: the bimodal result that didn't meet tolerance, section dissertation) Give agents CLIs before MCPs. (evidence: how the Workbench is wired, section workbench) ## Contact (#contact) Email ktimothymuller@gmail.com. LinkedIn https://www.linkedin.com/in/kevin-t-m/. GitHub https://github.com/KennyTheBoss05. A CV PDF can be downloaded from the page. There is no public phone number. ## At a glance (#glance) My footprint at Zebra Technologies since December 2025. 9 production services on Google Cloud. 487 commits. 18 repositories. Stack: Google Cloud, Vertex AI, Gemini, LangGraph, FastAPI, BigQuery, Cloud Run, Cloudflare Workers, Claude Code. ## Skills (#skills) Languages: Python, TypeScript, SQL, C++, R. AI & ML: LangGraph, LangChain, RAG, Vertex AI, Gemini, OpenAI, PyTorch, TensorFlow, FAISS, evals. Backend & data: FastAPI, asyncio, REST APIs, BigQuery, Firestore, Cloudflare D1, Drizzle ORM, pytest. Cloud & delivery: GCP (Cloud Run, Vertex AI, Cloud Build), Cloudflare Workers, Docker, CI/CD, Git. AI-assisted delivery: Claude Code, Cursor, spec-first and subagent-driven development, custom agent tooling. ## Six LLM calls down to one: an NL→SQL analytics endpoint (#nl2sql) Zebra Technologies, analytics for a global sales organisation. Problem: Sales leaders ask questions in plain English and get back numbers and a chart. The endpoint answered each question with a chain of 4–6 sequential LLM calls, then ran its queries one after another. Every hop added latency and input tokens, and every answer waited on the slowest link. Stakeholder framing: Sales leaders ask plain-English questions of their pipeline data and expect an answer while they are still in the meeting. The endpoint chained 4–6 sequential LLM calls per question, so answers were slow and each one cost more than it needed to. Constraints: Answers are checked against live BigQuery data, charts must always render, and the cost per question could not go up. Decisions: Collapse the chain into one structured Gemini Pro call that returns the original SQL plus two decomposed insight queries. Put a small, fast table classifier first, so the big model only sees the relevant tables and rule blocks. Run every BigQuery execution in parallel with asyncio.gather instead of in sequence. Cut the Pro model's thinking budget to minimal and move the retry path to a fast model. Return chart specs (Vega-Lite) typed from the BigQuery result schema, so a chart never references a column that isn't there. Trade-off: One bigger prompt is a single point of failure: a malformed response now costs the whole answer, so retries go to a fast model instead of repeating the expensive call. A classifier misroute would hide a table the question needs, so the fallback is the full schema. Result: 4–6 sequential LLM calls became 1. The classifier cut input tokens by 60–80%. All BigQuery executions now run concurrently. Next: Build an offline eval set of real questions with known-good results, so every prompt change is scored before it ships. Diagram: Question (plain English): A sales leader asks something like "which regions grew fastest last quarter?" Table classifier (small, fast model): Decides which tables the question needs before the expensive model sees anything. Metric: −60–80% input tokens. Trade-off: A misroute would hide a needed table, so low-confidence routing falls back to the full schema. Relevant schema (tables + rule blocks): Only the chosen tables' schema and their business-rule blocks are injected into the prompt. One Gemini Pro call (structured output): Returns the original SQL plus two decomposed insight queries in a single response. Metric: 4–6 calls → 1. Trade-off: Single point of failure, so the retry runs on a fast model rather than repeating the Pro call. Thinking budget cut to minimal. BigQuery (original SQL): The query that answers the question as asked. BigQuery (insight query 1): A decomposed follow-up query that explains the headline number. BigQuery (insight query 2): A second decomposed query; all three run concurrently with asyncio.gather. Chart spec (Vega-Lite): Chart specs are typed from the BigQuery result schema, so they only reference columns that exist. Answer (numbers + chart): The leader gets the number, the two insights and a chart that renders. ## A sales-playbook service reps used: +66% weekly conversations (#playbook) Zebra Technologies, a global sales organisation. Problem: Reps prepared for calls by researching accounts by hand, and a generic script rarely matched the person on the other end. The ask was a playbook per account, ready before the working day. Stakeholder framing: Sales leadership wanted reps talking to more of the right people, not writing more research notes. Reps prepared for calls by hand, and a generic script rarely matched who they were calling. I worked with the team to define a playbook per account, ready before the working day, and agreed up front how we would measure whether it changed behaviour. Constraints: Contact data costs money per record. The model's persona and sector calls can be wrong. Results had to land in the call consoles reps already use. Decisions: Route each account to a persona and sector with an LLM, behind a deterministic fallback and a kill switch. Gate spend on verification: pay for a contact only once it is verified and in the right region. Generate the playbook with Gemini: personas, objection handling, call and email scripts. Run generation as a Cloud Run batch job with serialised writes, so parallel work never overwrites a record. Grow the test suite as the scope grew, instead of after it. Trade-off: Batch, not real-time: a playbook is hours old rather than instant, in exchange for predictable cost and nothing to fail during a live call. Result: Launched to a 33-rep London cohort: weekly conversations per rep up 66%, meaningful conversations up 46%. Next: Feed call outcomes back per persona, so routing and scripts are measured individually rather than only in aggregate. Diagram: CRM account (input): An account assigned to a rep enters the pipeline. Account research (whitespace): The service researches the account and where there is room to grow. Persona & sector routing (LLM + fallback): An LLM picks the persona and sector to target. Trade-off: The model can be wrong, so a deterministic fallback takes over when it is unsure, and a kill switch turns the LLM step off entirely. Verification gate (spend control): A contact is only paid for once it is verified and in the right region. Trade-off: Slower than buying every candidate up front, but no money is spent on contacts reps can't use. Playbook generator (Gemini): Writes personas, objection handling, and call and email scripts for the account. Cloud Run batch job (serialised writes): Results are written in a batch job with serialised writes, so parallel work never overwrites a record. Reps' call consoles (outcome): The playbook is waiting in the tool the rep already uses. Metric: +66% weekly conversations per rep, +46% meaningful conversations. ## Ingestion pipeline cost fix (#ingestion) Zebra Technologies. 12.7 h → minutes. Replaced ~62,000 per-record BigQuery MERGEs with one batched MERGE per table. A 12.7-hour ingestion run now finishes in minutes, and $3–5 of DML cost is gone from every run. ## Support Assistant, AWS → Google Cloud (#support-assistant) Zebra Technologies. rebuilt on GCP. Migrated the customer Support Assistant off AWS and rebuilt it around a LangGraph router. The router chooses between two Vertex AI Search datastores; inference is Gemini-first with an OpenAI fallback. ## Voice-of-Customer RAG assistant (#voc-rag) Zebra Technologies. cited answers. Shipped end to end: a plan-then-fan-out query planner over Vertex AI Search. Gemini answers cite the source documents they used; the web front end sits behind single sign-on. ## Salesforce Q&A agent (#salesforce-agent) Zebra Technologies. self-correcting SQL. A LangGraph agent over BigQuery that repairs its own SQL on a dry-run failure. Session history is encrypted with AES-GCM, and a detect-and-translate wrapper makes it bilingual. ## AI deck generator (#deck-generator) Zebra Technologies. 355 slots, 42 designs. Rebuilt to fit copy into 355 measured slots across 42 brand-approved designs. Copy is grounded in the sales retrieval corpus, with a web-search evidence leg for anything the corpus lacks. ## Outreach.io integration (#outreach) Zebra Technologies. 2,073 calls validated. Server-to-server auth chain with 16 read-only scopes. Call duration was validated against the recorded media across 2,073 calls before anyone relied on the numbers. ## Deducing the molecular structure of plastics from flow data using deep learning (#dissertation) MSc Data Science & Analytics, University of Leeds, September 2024. Supervised by Prof. Daniel J Read. Recycled plastic can't be reused well without knowing its molecular weight distribution (MWD). Measuring it directly (GPC) is slow and costly; rheology — how the melt flows — is fast, non-destructive and scales to industrial volumes. An LSTM with fully connected layers reads rheological flow curves (G′ and G″ against frequency) generated by a tube-model simulator (Das & Read, 2023) and predicts MWD parameters: Z and PDI for unimodal samples; Zs, PDIs, Zl, PDIl and φl for bimodal ones. 80:20 split, early stopping, up to 100 epochs, run as a CRISP-DM process. Industry accepts 15% error in Z and PDI, which is an acceptable error (AE) of 0.06 in log space. For unimodal plastics every condition stayed within the 15% industry tolerance, including with injected noise and a pseudo-realistic dataset. A model trained on noisy data stayed robust for Z between 1.5 and 3, and spectral analysis showed some frequency sub-ranges predict certain targets better than the full range. Synthetic: accuracy 99.93%, MAE Z 0.00162, MAE PDI 0.00206, PMAE Z 0.06%, PMAE PDI 0.21%. Restricted frequency: accuracy —, MAE Z 0.00333, MAE PDI 0.00543, PMAE Z 0.12%, PMAE PDI 0.55%. Artificial noise: accuracy 99.69%, MAE Z 0.0039, MAE PDI 0.0069, PMAE Z 0.14%, PMAE PDI 1.84%. Pseudo-realistic: accuracy 98.58%, MAE Z 0.016, MAE PDI 0.027, PMAE Z 0.67%, PMAE PDI 7.2%. What did not work: Bimodal plastics did not meet the tolerance. On synthetic bimodal data 7.5–17.2% of predictions fell outside the acceptable error; restricted-frequency MAEs reached 0.13–0.20 and pseudo-realistic ones 0.22. The error trends point to the next step: feature engineering on the low-error frequency regions, and a CNN-RNN hybrid. Also at Leeds: 30-class image classification with an MLP and a CNN in PyTorch, and drone-delivery optimisation using MCDA (VIKOR) with linear programming. The notebook, dissertation PDF and poster are public on GitHub. ## Underwater autonomous tank-cleaning rover (#rover) BTech dissertation, VIT Chennai, 2023. Published on arXiv (2304.08185). I built the SLAM navigation module on ROS Gazebo, running on a Raspberry Pi and driven from a browser UI that sent target coordinates from a pre-loaded RViz map. The paper is public on arXiv; the code repository is private (walkthrough on request). ## The Workbench: how I engineer with AI (#workbench) Most of my code is written with Claude Code. This is the tooling I built so that it stays fast, repeatable and safe across about 30 projects. The rule I work by: CLIs were built for agents, so CLI before API before MCP. ## Brain repo (#brain) A version-controlled library of Claude Code assets: 12 agents, 9 commands, 21 skills, 7 plugin sources and hooks, plus my standing instructions. Agents and commands are global through directory junctions; skills are deliberately not, because they auto-trigger on their description and would shape every session. /wire-up copies only the skills that match a repo's stack. /promote-to-brain moves a locally drafted asset into the brain and links it back; /ingest turns a video, site or file into updates to the tools and workflow docs. Private repository, walkthrough on request. ## Jarvis (#jarvis) A cross-project conductor. One long-lived session dispatches fresh worker processes into about 30 projects, at most 5 at a time. Workers are separate OS processes started in the project folder, not subagents, so each one obeys that repo's own instructions and skills. Task state lives in each project's own .jarvis/ folder; there is no central index. The conductor holds pointers, never payloads. Two lanes: chat (the default) and a plan → execute → test pipeline on a branch. Exactly one human merge gate; workers never push. Private repository, walkthrough on request. Kevin (phone or desktop): I describe the task from wherever I am. Conductor (one long-lived session): Reads each project's task list, picks a lane and starts a worker. It holds pointers, never payloads. Worker (project A): A fresh claude -p process started in the project folder, so it follows that repo's own rules. Worker (project B): Up to 5 workers run at once, each in its own project. Worker (project C): Pipeline workers work on a branch and never push. .jarvis/ state (per project): TASKS.md, state.json and RESULT.md live in each project, so there is no central index to drift. Merge gate (human): Pipeline tasks stop at needs-approval. Merging is my decision, every time. ## ClaudeAnywhere (#claudeanywhere) Start a Claude Code session in any of 30+ project folders from my phone, without opening the laptop. A stdlib-only Python daemon run by two Windows scheduled tasks: a conductor (outbound-only remote control, no inbound ports or tunnels) and a reaper that health-checks it every 5 minutes and closes idle servers. 39 unit tests, with zero real claude calls. Lessons built in: the Claude config file is round-tripped losslessly, and the interpreter is validated before a task is registered, after a three-week silent outage caused by an orphaned Python process. Private repository, walkthrough on request. ## Hooks & commands (#hooks) Small automations around the agent loop. A Stop hook raises a Windows notification when a prompt finishes, linking back to the session. A PreToolUse gate routes structural code searches through a code-graph index instead of grep. Commands: /wire-up, /ingest, /promote-to-brain, /ultra-think, /code-review. Private repository, walkthrough on request. ## JukeBoxxed (#jukeboxxed) A real-time multiplayer party game for 3–10 players, no login: everyone submits a YouTube clip that matches an image, then votes anonymously. Cloudflare Worker (Hono) with Durable Objects on the WebSocket hibernation API, D1 and R2; React, TypeScript and zustand on the front end. Room state is versioned, so clients detect when they are stale; every event is validated end to end with shared Zod schemas. Multi-player Playwright end-to-end tests drive several browsers through a full game. Public link: https://jukeboxxed.pages.dev/. Private repository, walkthrough on request. ## JobBot (#jobbot) A job-application agent that only answers from what it can retrieve, and hands anything uncertain to a human. LangGraph state machine plus browser automation driven by accessibility snapshots, not brittle CSS selectors. Answers come only from FAISS retrieval over two knowledge bases; confidence is 0.6 × the top score + 0.4 × its margin over the runner-up, and low-confidence answers go to me. Dry-run by default, JSONL audit traces for every decision, pytest suite, FastAPI UI. Private repository, walkthrough on request. ## Us, Daily (#journal) A private journaling app for two, in production on Cloudflare Workers. Next.js 16 on Workers with D1 and Drizzle, R2, KV, and Vectorize with Queues for asynchronous RAG indexing, namespaced per relationship. Claude writes the captions, with a deterministic fallback when no key is set; secrets are isolated per environment; nightly cron. 57 Vitest test files. No public link. ## ModulatorX (#modulatorx) A native FL Studio controller plugin in C++17 with the FL Studio Plugin SDK and JUCE 7. Drawable LFO/envelope with tempo sync across 19 grid divisions, MIDI and audio-threshold triggering, per-segment tension and one-pole smoothing, 50-step undo. Lock-free UI → audio handoff through atomics; phase stays aligned across all three trigger modes. Phases 1–6 done; presets are next. Public link: https://github.com/KennyTheBoss05/ModulatorX. ## FL Studio command layer (#fl-ahk) An AutoHotkey v2 command layer for FL Studio, with a two-way bridge into FL's Python API. FL's Python sandbox blocks file I/O, so strings cross a virtual MIDI port as 7-bit CC bursts with request ids and a loop-back guard. Finds panel geometry at runtime by walking FL's window tree, with no hard-coded pixels. Smoke-test script. Private repository, walkthrough on request. ## Stem Extractor (#stem-extractor) A Streamlit prototype for pulling a track apart. Spleeter 2/4/5-stem separation from a file or a link. Key detection (chroma-CQT against major and minor profiles) and BPM detection with librosa. Per-stem time-stretch and pitch-shift. Private repository, walkthrough on request. ## Sample EZ (#sample-ez) A Chrome extension to record, trim and export audio from a tab, the system or a mic. An offscreen document holds the audio graph, because Manifest V3 service workers sleep after about 30 seconds. AudioWorklet raw PCM capture, a zoomable min/max-peak waveform, WSOLA time-stretch, key and BPM detection with grid snap. WAV and MP3 export, no build step, self-check scripts. Private repository, walkthrough on request. ## Music production tools (#music) Trinity College London Grade 8 piano. Now I build tools for my own studio. ## Experience (#experience) AI Application Developer → Enterprise Systems Analyst II at Zebra Technologies, Dec 2025 – present. Contract from December 2025, full-time since April 2026. I own the GenAI platform behind a global sales organisation. AI Product Engineer at AI stealth startup, May 2025 – Dec 2025. Built a full-stack video-to-text app that digitises physical documents from a single recorded scan: on-device C++/OpenCV frame extraction and text detection, printed-vs-handwritten routing across two OCR engines, and vision-LLM quality correction. Machine Learning Intern at FIS Global, Sep 2022 – Dec 2022. Led the analytical engine for FIS Ecoglobe, placing top 4 nationally at InnovateIN48: a multilayer ESG classifier (sentiment plus feature mapping into E, S and G, with a CNN scoring each article's impact), on a corpus I sourced through the X and LinkedIn APIs and BeautifulSoup. Education: MSc Data Science & Analytics, University of Leeds, 2023 – 2024. BTech Electronics & Computer Engineering, VIT Chennai, 2019 – 2023. ## Recognition (#recognition) Top 4 nationally, InnovateIN48. 3rd place, VIT Datahub Datathon. AWS Certified Cloud Practitioner. Paper on arXiv (2304.08185). ## How this site works (#colophon) Both versions of this page are built from one content file by a small Node script with no dependencies, so the facts can't drift between them. The same file generates llms.txt and the agent's knowledge base. The agent (Claude Haiku 4.5 on a Cloudflare Worker) answers only from that knowledge base, cites the section it used, and says "Not in my record" otherwise. It can't run up a bill: a spend-capped API key, Cloudflare Turnstile, per-IP and daily rate limits, short single-turn requests with a cached prompt, an origin check and a kill switch. If it's off, the Ask panel falls back to a search that runs in your browser. Built spec-first with Claude Code.