I build AI systems that reach production — and stay there.

AI Engineer in London, building LLM systems on Google Cloud.

See the work Download CV
12.7 h → minutes
ingestion run, after batching ~62,000 MERGEs into one per table
−60–80%
input tokens, from a classifier in front of the NL→SQL model
+66%
weekly conversations per rep after the playbook launch
Kevin Timothy Muller
§ glance

At a glance

My footprint at Zebra Technologies since December 2025.

9
production services on Google Cloud
487
commits
18
repositories
All 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
§ work

Selected work

Two production systems at Zebra Technologies. Every node in the diagrams opens the decision behind it.

§ nl2sql

Six LLM calls down to one: an NL→SQL analytics endpoint

Zebra Technologies, analytics for a global sales organisation

fig. nl2sql NL→SQL request path. Select a step.

Select a step to see the decision behind it.

Calls per question, before and after (schematic, not to scale)

LLM call 1
LLM call 2
LLM call 3
LLM call 4
LLM call 5
Query 1
Query 2
Query 3

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.

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.

What I'd do next

Build an offline eval set of real questions with known-good results, so every prompt change is scored before it ships.

§ playbook

A sales-playbook service reps used: +66% weekly conversations

Zebra Technologies, a global sales organisation

fig. playbook One account's journey through the playbook service. Select a step.

Select a step to see the decision behind it.

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.

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%.

What I'd do next

Feed call outcomes back per persona, so routing and scripts are measured individually rather than only in aggregate.

§ more

More work

Other production work at Zebra Technologies. Open a row for the detail.

§ research

Research

Two theses, one of them published.

§ dissertation

Deducing the molecular structure of plastics from flow data using deep learning

Question

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.

Method

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.

Finding

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.

fig. dissertation Unimodal MAE per condition (log scale). Every point sits left of the tolerance line.
Mean absolute error per test condition for Z and PDI, log scale, against the acceptable error of 0.06 0.0010.010.1 Acceptable error 0.06 ZPDI Synthetic Synthetic · Z · MAE 0.00162 (PMAE 0.06%) Synthetic · PDI · MAE 0.00206 (PMAE 0.21%)Restricted frequency Restricted frequency · Z · MAE 0.00333 (PMAE 0.12%) Restricted frequency · PDI · MAE 0.00543 (PMAE 0.55%)Artificial noise Artificial noise · Z · MAE 0.0039 (PMAE 0.14%) Artificial noise · PDI · MAE 0.0069 (PMAE 1.84%)Pseudo-realistic Pseudo-realistic · Z · MAE 0.016 (PMAE 0.67%) Pseudo-realistic · PDI · MAE 0.027 (PMAE 7.2%)
Show the numbers
Unimodal results by test condition
ConditionTest accuracyMAE ZMAE PDIPMAE ZPMAE PDI
Synthetic99.93%0.001620.002060.06%0.21%
Restricted frequency—0.003330.005430.12%0.55%
Artificial noise99.69%0.00390.00690.14%1.84%
Pseudo-realistic98.58%0.0160.0270.67%7.2%

What didn't 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.

§ rover

Underwater autonomous tank-cleaning rover

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.

§ workbench

The Workbench: how I engineer with AI

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.

fig. jarvis-flow How Jarvis dispatches work. Select a step.

Select a step to see the decision behind it.

§ brain

Brain repo

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.
§ 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.
§ 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.
§ hooks

Hooks & commands

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.
§ side-quests

Side quests

Things I build outside work, most of them used by real people.

§ 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.
§ 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.
§ journal

Us, Daily

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.
§ music

Music production tools

Trinity College London Grade 8 piano. Now I build tools for my own studio.

§ 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.
§ fl-ahk

FL Studio command layer

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.
§ 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.
§ 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.
§ experience

Experience

  1. Dec 2025 – present

    AI Application Developer → Enterprise Systems Analyst II

    Zebra Technologies, London

    Contract from December 2025, full-time since April 2026. I own the GenAI platform behind a global sales organisation.

    § nl2sql

  2. May 2025 – Dec 2025

    AI Product Engineer

    AI stealth startup

    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.

  3. Sep 2022 – Dec 2022

    Machine Learning Intern

    FIS Global

    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

  1. 2023 – 2024

    MSc Data Science & Analytics

    University of Leeds

    § dissertation

  2. 2019 – 2023

    BTech Electronics & Computer Engineering

    VIT Chennai

    § rover

Recognition

  • Top 4 nationally, InnovateIN48
  • 3rd place, VIT Datahub Datathon
  • AWS Certified Cloud Practitioner
  • Paper on arXiv (2304.08185)
§ about

How I work

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.

§ contact

Get in touch

Email is the fastest way to reach me.

Ask about my work

An agent that answers only from this page and cites the section it used. It says so when something isn't in the record.