Elisabeth NnamaniOpen the desk
Portrait of Elisabeth Nnamani

AI Engineer · Nigeria
Open to AI engineering roles

Systems that survive contact with reality.

I build multi-agent orchestration, retrieval grounded in schemas that actually exist, and inference that keeps working with the network unplugged.

I am an AI engineer. Most of what I build sits in the same place: the layer between a language model and a system that has to be correct.

That layer is where the interesting failures live. A model that writes fluent SQL against columns nobody has. A retrieval step that splits a transaction table mid-row and hands back an amount with no date attached. A pipeline that reports success because the frontend quietly fell back to mock data. None of these throw an error. They return something plausible, which is worse.

So the work is rarely the model call. It is the chunking strategy, the schema the output has to survive, the gate that stops a run before it writes to production, the isolation policy that lives in the database instead of in a code path someone can forget. I care about the parts that hold when conditions are not ideal — which, in the market I build for, is most of the time.

Five systems, one argument

PrismOSMulti-agent system · 2026 · LiveSeven agents that are required to disagree before any code ships.Atlas AIAutonomous data engineering · 2026 · LiveNatural language to production dbt models, grounded in the catalog your organization already has.FinSightDocument intelligence · SaaS · 2025 — 2026 · LiveTurning a messy bank statement into clean rows, for a market that bank-linking APIs do not serve.FarmTwinOffline-first local inference · 2026 · 7-day sprint · SubmittedA cited agronomic advisor that runs entirely on a 2014 laptop with the network unplugged.FlowMindAI product · SaaS · 2025 — 2026 · LiveRemoving the triage tax that kills productivity systems.

How the work changed

Freelance AI EngineerIndependent · 2025 — Present

Owning the system, not just the surface.

Building LLM-backed products end to end, for clients and for myself: FinSight, FlowMind, PrismOS, Atlas AI, FarmTwin.

This is where the work moved past the interface. Orchestration and agent design, retrieval that has to stay grounded, tenant isolation enforced in the database, billing that survives a webhook, deployment across platforms that each break differently. Five products shipped, each one teaching a failure mode the last one did not have.

Freelance Web DeveloperIndependent · 2023 — 2024

Learning to ship on someone else's terms.

Websites and web apps for small businesses and early-stage founders: landing pages, booking and contact flows, dashboards and content-managed sites, built with React, Next.js and Tailwind CSS.

Most projects started as a loose brief with a fixed budget. I scoped them, agreed what was in and what was out, shipped to the client's date, and handed over something they could run without me, usually a CMS and a short written guide. That is where I learned the code is the smaller half of the job.

Grouped by what I do with them

Orchestrating models
LangGraph · LangChain · LlamaIndex · MCP · Multi-agent systems · SSE · WebSockets · Structured output
Running inference
Groq · LLaMA · Mistral · Qwen · llama.cpp · Q4_K_M quantization · gpt-oss
Grounding retrieval
RAG pipelines · Semantic chunking · sqlite-vec · DataHub knowledge graphs · Citation enforcement · Benchmark rubrics
Serving it
FastAPI · Python · Node.js · Express · Next.js · TypeScript
Storing it safely
PostgreSQL · Supabase · Row-level security · SQLAlchemy async · asyncpg · SQLite
Building the product around it
Next.js · React · TypeScript · Tailwind CSS · Motion · Recharts · Design systems
Shipping it
Docker · Vercel · Railway · Render · Neon · Alibaba Cloud SAE · Git · Paystack

Seven things that cost me something

Every principle below came from something that went wrong. None of them are opinions I arrived at in the abstract, and I would not trust them if they were.

The expensive failures return an answer

The bugs I remember all have the same shape. Nothing throws. Nothing logs. The system returns something plausible and you carry on.

Fixed-size chunking split a transaction table mid-row, so the model got an amount with no date attached and answered confidently. An environment variable set at runtime where Next.js needs it at build time made a frontend fall back silently to fixtures, and the application looked like it was working. A Tailwind v4 migration compiled cleanly and simply did not apply any styles.

So I have stopped treating a green run as evidence. The question is not whether it completed. It is whether I can name what it would look like if it were quietly wrong.

Learned on FinSight · Semantic chunking around section headers, row boundaries as hard splits

Set the gate before you run the test

I wanted Pidgin voice input in FarmTwin more than any other feature in it. I am a native speaker and it is the language a large share of the users actually speak.

I defined a 40% word error rate gate before I ran a single clip. Whisper base failed. The Nigerian-English fine-tune failed. The datasets that might have fixed it were gated or unpublished inside the sprint window. The feature shipped as English-only, labelled honestly in the interface.

The gate existed precisely so that decision would be forced by data rather than by how badly I wanted the feature. A threshold you set afterwards is not a threshold.

Learned on FarmTwin · ADR-011 — 15-clip evaluation, feature scoped to English

Grade your own work down

My first benchmark pass scored the model I had chosen at 98.8. I had been generous on partial credit, in the direction that happened to suit me.

I re-graded against a stricter reading of the same rubric and it came out at 87.6. That number is less flattering and considerably more useful.

A benchmark you have quietly rigged tells you nothing. It only tells other people something, and briefly.

Learned on FarmTwin · Qwen2.5-3B chosen over Llama-3.2-3B on citation fidelity, 83.5 to 72.9

Name the cost of the call

I categorize transactions with a model and no rule table. The honest description of that is a permanent per-upload token cost traded against zero rule maintenance.

I could describe it as the elegant choice and leave the sentence there. It would read better and mean less.

Every architectural decision I am confident about, I can state what it costs. The ones I cannot state a cost for are usually the ones I have not thought about hard enough.

Learned on FinSight · Model-only categorization, 40-transaction batching

Put the guarantee in the system, not the code path

Per-user isolation lives in row-level security policies in the database. It does not live in a middleware function that a future endpoint might forget to call.

Approval checkpoints reconstruct their context from persisted output rather than holding it in memory, so a paused run survives a restart. A gate that evaporates on redeploy was never a gate.

The pattern is the same each time: move the guarantee somewhere it cannot be skipped by someone who is in a hurry, including me.

Learned on Atlas AI · Three resumable phases rebuilt from agent_runs.output_json

Patch what works

Across three versions of PrismOS, every capability added after v1.0 went in as an incremental patch against working architecture. Agent 0, the designer role, project memory, feature classification. Several proposed rebuilds were rejected.

Auth, rate limiting and webhooks were cut and written down as deferred, rather than half-built and left looking finished.

A rewrite is the most expensive way to avoid understanding the thing you already have.

Learned on PrismOS · Versioned blueprint as single source of truth, v1.0 through v1.2

Build for the market you are actually in

Stripe does not serve Nigerian payment rails, so FlowMind and FinSight run on Paystack, and the migration touched the schema, the status enum, webhook verification and the whole billing interface. It was not a client library swap.

FarmTwin runs with the network unplugged on a 2014 laptop because that is the hardware and the connectivity the farms actually have. FinSight parses statements because bank-linking APIs do not cover Nigerian banks at all.

None of this is a constraint I am working around. It is the specification.

Learned on FlowMind · Paystack migration, NGN and USD pricing

Tell me what breaks

I am most useful on systems where a wrong answer is expensive and the failure does not announce itself. Open to AI engineering roles and selected contract work.

© 2026 Elisabeth Nnamani