← Back to Portfolio

AI Fluency Capstone — Build-in-Public Story

Author: Syeda Munazza Bukhari | Track: General AI Fluency & Impact Project

🛠️ The System & Stack Choices

For the Navigant Student Guidance workflow, I deployed n8n Community Edition inside a Docker container on Windows 11. This runtime connects to a live Notion student intake database and calls the Google Gemini API for reasoning and classification.

I started the integration on Gemini 2.5 Flash. Later, while hardening the system against concurrency failures, I moved the execution engine to gemini-3-flash-preview, which handled tool-calling and structured output more reliably under load.

I chose a self-hosted, containerized stack over Claude Desktop or a purely cloud-based automation tool for one practical reason: cost and control. Running n8n via Docker gave me zero execution costs and direct control over my own API tokens, instead of being limited by a volatile free-tier message cap.

🏆 The Real Engineering Win

My biggest success was moving past a simple linear automation and designing a goal-seeking agent that grounds its answers in real data instead of guessing.

Large language models will naturally hallucinate entry criteria and numerical thresholds when asked about university admissions requirements. To stop this, I built a custom JavaScript tool — uk_university_requirements_lookup — and wired it directly into the n8n agent node. This forced Gemini to make a tool call and cross-reference a verified data structure instead of inventing an answer, which eliminated hallucinated requirements during student profile processing.

⚠️ The Real Limitation & Hardest Break

The system did not work perfectly on the first real test, and I'm documenting the failure honestly rather than smoothing it over.

Failure 1 — Rate limiting: During a stress test with multi-row data pulled from the Notion API, the workflow triggered an HTTP 429 concurrency error from the Google AI Studio provider. Multiple overlapping sub-node tool calls fired at once and exceeded the provider's rate limit.

Failure 2 — Unmapped data: Separately, when the workflow processed a student record with an unmapped major (Psychology) that fell outside my existing data structure, the agent hit a hard boundary. The JavaScript logic had no path for the unexpected value and the run froze instead of failing gracefully.

🔧 The Fix

That last decision is the one I'm most glad I made: when the agent doesn't know something, it should say so and stop — not guess. That's the standard I'm holding this system to as I keep building it.

🚀 What I'll Build Next

The next upgrade is to replace the local JavaScript lookup dictionary with a persistent, relational PostgreSQL database container running in the same Docker network. That will let the Navigant Student Guidance Agent run proper multi-row, relational queries across a much larger set of active university criteria — instead of a hand-maintained lookup table.