[ ← Work ]
Role 01 / 03Ongoing
01Jun 2026 — Present

Artificial Intelligence Engineer

Greenboard

Core infrastructure for an automated marketing compliance platform: customer documents in any format go in, and potential violations against internal review rules come out.

Context

Greenboard Go is Greenboard's chatbot service, and the marketing review backend behind it is what I worked on. A financial firm's compliance or marketing team submits a piece of marketing in whatever form it takes: a Google Doc, a slide deck, a video or audio recording, a social media post, a photo. The backend transcribes, parses or runs image analysis on that submission until it is text, sends the text to a large language model provider, and connects the result to a database of SEC and internal company review rules so that potential compliance issues are flagged against the document.

As the company grew, that backend had become hard to work in. It was written in a functional style in Python, spread across several services, and difficult to read. I was brought on to simplify it while preserving all of the core logic, and to standardize how it was put together. The second ask was a benchmark suite. When a transcription provider or a model version changed, the team wanted something that would catch small regressions and give them more confidence in a release. Nothing elaborate, just a reliable check before a push.

What I owned

The entire ingestion backend. That covered everything from a document arriving on SQS, through the data store and the files it held, into the transcription service, parser or image analysis that turned it into text, and on to the language model provider. I refactored all of it.

Once the backend was in shape, the work moved to the front end, where I owned part of a redesign. Before the redesign, Greenboard presented a list of violations that were not tied to any particular place in the document, and reviewers had no fast way to check whether a flag was correct. The redesign connects each citation to the passage it came from, so a reviewer can verify a violation quickly and in context. For editable formats such as Google Docs and docx files, the goal was closer to Grammarly for financial compliance: run the document through the model, surface suggested edits next to each violation, and let the user accept an edit and save the revised document.

Approach

I started by simplifying the system and mapping where it connected to everything else: the front end on one side, the databases and queue on the other. Rather than trying to understand every internal path at once, I found the doors, so to speak, and then worked out which checks and validations each stage needed so that the whole chain could be confirmed to be wired correctly.

The design decision that shaped the rest was to build for adaptability. Document parsing and language model providers are moving quickly, and any of them can become dramatically cheaper or more accurate in a matter of months. I moved the codebase to an object oriented structure with abstract classes at each provider boundary, so that a transcription service, a parser or a model is something you swap in rather than something the pipeline is built around. That structure also made each piece testable on its own. Observability came with it. The service had few tests before, and tracking what every stage was doing, with proper error handling around it, made later debugging far simpler. There were bugs along the way, including one where I sent a PDF directly to an API that expected parsed text, but because the stages were modular and tested separately, each one was contained.

The payoff showed up quickly. Because the pieces were small and interchangeable, it took little time to build an experimental service where a client submits the URL of a firm's website, a crawler built on the Firecrawl API takes screenshots and parses the HTML, the pages are converted to PDF, and the result runs through the same backend to surface possible violations on the site itself.

What outlived it

The modular structure, along with the documentation and unit tests that came with it, is the piece that will keep paying off as providers change. The benchmark suite is the other. Adding a new document and its expected output is a small task, so when an edge case turns up that nobody anticipated, it can be added to the suite and the system is protected against forgetting it in the next release.

What I would do differently

I would simplify further, and I would spend much more of my time up front on system design. I tend to get excited and move quickly into building, and in the middle of a project with this many moving parts it is easy to lose sight of the goal when something breaks. There is security, observability and the actual logic of the program, and behind those the model provider, the transcription service, the document stores, the queue and its dead letter queue, and questions such as what happens when a process runs out of memory and how it restarts safely. Working the whole system through in pseudocode before writing any of it would have answered many of those questions earlier.

I would also do more research before building. Writing new tools is enjoyable, but at a company the job is to deliver a return on the time spent, and many of the services I needed already existed as open source projects or had been solved in public by other people. Finding them is part of the work.

The lessons I took with me are mostly about how to run a large programming project: how to break a problem down, how to explain a thought process so others can follow it, and how to let other people work in the same codebase and give feedback. Using Git the way it is used in industry, with branches, worktrees and pull requests, changed how I run my own projects. Getting comfortable with AWS and cloud hosting in general was the other big one.

Stack
ReactTypeScriptAWS ECSSQSMySQLPostgreSQLCloudWatch