Skip to main content

Market Intelligence · Enterprise & Government AI

I catch the government partnerships we used to miss entirely

I built the thing that finds out first: a watch list of named officials, 24 government sources, and two workflows that read every announcement, score it, and put the ones worth acting on in front of sales while the conversation is still open. Before it, a UAE government partnership usually reached us after it had been signed, and most of the time it never reached us at all, because our bigger competitors were already in the room.

ai71 Head of Growth & AI Jul 2025 to Present
On this page

In short

Problem

Bigger competitors were already engaged by the time a UAE government partnership surfaced, and most of the time sales never found out at all.

What I built

Google Alerts on named officials, 24 government sources, and two n8n workflows that scrape and score every mention into one sheet.

Result

Signals that used to pass unnoticed reach Slack within a day, scored, with the named people on both sides and a proof excerpt.

from usually never

Within a day

Time To Know

from 0

24

Government Sources

from 0

5,000+

Signals On Record

How this is measured

The 24 government sources and the signal count come from the monitor's own Google Sheet, read on 26 August 2026: the sources tab lists 24 entities and the signals tab had passed 5,000 rows. That count is everything the system has recorded since it started, including the historical prefill, and it includes rows the analyzer rejected as well as the ones it validated. The split between them is not stated here because it was not measured. "Within a day" is the design rather than an observed average: Google Alerts arrives as a daily digest and the workflow polls it every hour, so a signal reaches Slack within a day of Google indexing the announcement. "Usually never" is the before-state as sales leadership described it, not a measured figure. I claim no revenue and no pipeline from this. It surfaces a conversation; whether anything comes of it belongs to the commercial team.

Constraints

  • Google Alerts stopped authenticating under my own work account, so the entire input layer had to move onto a separate free inbox before anything else could run
  • I chose the native n8n HTML scraper over robust body detection, which means a bot-protected site is recorded as blocked rather than read
  • Everything it reads is public news, so a partnership that was never announced anywhere is invisible to it

What was mine

I built both workflows, the watch list and the source list myself, end to end. The problem came from sales leadership and I was in the discussion when it came up. I report to the Chief AI Advisory and Business Officer, the Director of Marketing and the Director of Commercial. Acting on a signal is the commercial team's work and not mine: the system says a conversation is happening, and everything after that is theirs.

What this actually watches

I called it UAE partnership monitoring, but it's actually kind of like monitoring any relationships going on with the UAE government and other governments or other organizations, anything like this.

Sales found out after the fact, or never

This came up from the pain point of sales leadership: sometimes we get to know there's some talk going on. I think it's something along the lines of an MoU signed or some other talking going on.

We realize that, because we have less of a footprint in terms of sales, our bigger competitors are already talking to them, already have engagements, and it's difficult for us to engage in a meaningful way.

I was in the discussion with them, and it would be good to know something in advance. I said, "Let me explore. I have some ideas."

I reused what already works

This is what I created, so I'm not doing everything from scratch. I'm reusing something which is already working. For instance, Google Alerts is very good for going through anything that gets mentioned.

I came up with the names you can see in Google Sheets for all senior people and influential government figures and sheikhs inside the UAE. I took the names down.

The list is grouped the way the government is: federal leadership and the core Cabinet, a foreign affairs cluster, trade and the newer portfolios worth watching, Abu Dhabi royal leadership and deputy rulers, Abu Dhabi senior officials, and the Dubai Executive Council. Every name carries its own query, pairing the ways that person is written about with the words that mean something is happening. Alongside it sits a second list of 24 government entities. Each one carries its base URL, its news listing, and whether it offers RSS, a sitemap or a search. The last column says which of those to prefer.

Originally I had them under my own email, but that stopped working because of authentication. I created a free email dedicated just for this, so I fixed that problem.

The dedicated inbox that fixed the authentication problem. Every digest that lands here is raw input, and the workflow polls it every hour on the half hour. (click to enlarge)

Two ways in

I had to do it in two ways: prefill what already exists, and set it up so we can pick up any future mentions.

Both ways in, on one canvas. The hourly monitor runs along the top, the historical prefill along the bottom, and they write into the same sheet. (click to enlarge)

Mapping where the doors already are

Another actual reason why I ended up doing this whole thing was that we wanted to map strategically for our go-to-market based on where government already has existing relationships. Using our relationships and being plugged in, we can open the doors. That's another way for us to see which countries and which projects would be beneficial for us to monitor, track, and have a positive signal.

Filling in what already happened

Now, moving to prefilling, I had two workflows on n8n. One was using Perplexity mostly as a main source of raw information.

Which I triggered from a Google Sheet. I did research with Perplexity. I converted everything using OpenAI models to JSON. I split it and normalized it, and after that I scraped every single article and processed this by analyzing each article and updating it into the sheet.

If it failed, I just did nothing because it was enough to go through, so I didn't need to solve it for every single one, even if it had some bot protection. I used the simple tool, nothing complex, just to simplify. Otherwise, I would have to do it with more robust body detection, but I chose just a simple HTML scraper, which is native on n8n.

What that looks like underneath:

  • The trigger is a checkbox. Ticking "Start AI Research" against a government entity posts that row to an n8n webhook. The list of what to research and the button that runs it are the same object.
  • Perplexity runs on sonar-deep-research. It asks for official announcements from the last 365 days that name a non-UAE country next to a word meaning something happened: met with, held talks, hosted, delegation visit, joint statement, MoU, agreement, signed.
  • GPT-5.2 turns the reply into structured JSON, then every article is fetched one at a time, 3 seconds apart, with a 60 second timeout.
  • Anything on wam.ae, the state news agency, returns headers n8n cannot parse, so those URLs go through a reader proxy instead of being fetched directly.
  • A failed fetch still writes its row, with the reason classified: blocked by a firewall, headers the parser choked on, or the status it came back with. What could not be read is a filter away rather than lost.
Ten nodes. Note the branch below the scraper: the error output is wired to its own sheet write, which is why a blocked fetch leaves a record instead of disappearing. (click to enlarge)
What the prefill produced. The source_id column names the government entity each row came from, so a signal can be traced back to the source that was researched rather than to a search. (click to enlarge)

The hourly monitor

The other one was slightly different. The trigger was Google Alerts email, and I processed this: a monitoring email for new emails coming in every hour.

What I'm doing is just processing this as a raw email:

  • Extracting links
  • Checking existing links
  • Splitting
  • Filtering for new URLs
  • After that, scraping
  • If it fails, recording
  • If it doesn't fail, taking them through the loop and analyzing those Google Alerts for each scraped website
  • Flattening the results
  • Updating or adding the signal
  • If it reaches our threshold, sending the Slack alert notification

The parts that needed real work:

  • Pulling the links is its own model call, because a Google Alerts digest is not a tidy document. It has to tell a daily digest from a single alert, map every link back to the query that found it, and unwrap the Google redirect to reach the real destination. Then it throws away the furniture: unsubscribe links, full-coverage links, images, social profiles.
  • Before the analyzer sees a page it is stripped of scripts, styles, comments and embedded images. Then it is capped at 180,000 characters: the first 130,000 plus the last 50,000, because a long page buries the announcement at one end or the other.
  • GPT-5.5 returns one structured record: who met whom, which countries, what kind of instrument, the named people on both sides, a proof excerpt, a confidence and a score. It is told never to invent a fact, a date, a name or a country, and to return null rather than guess.
  • Every record carries a fingerprint built from the URL, the people, the countries, the interaction type and the date. So the same meeting reported by three outlets collapses into one signal.

The rule the whole thing turns on is what counts as eligible. The default is that a non-UAE country has to be named explicitly, and a region does not count: Asia is not a country. But there is a second door. A UAE-only announcement still qualifies on three conditions. It has to be a government-led strategic initiative. It has to carry a concrete delivery signal that implies real budget: a named programme, an investment figure, a rollout timeline or a procurement step. And it has to touch something we could sell into. So the monitor catches DIEZ launching District IO and Block 14 on AED 11bn and AED 1.8bn. It catches the Suqia water award opening a $1 million cycle around digital transformation. Neither involves a foreign government at all.

The alert does not fire on the score. The score sets the priority label inside the message. What decides whether Slack hears about it is whether the analyzer marked the record validated. That needs a named country or a qualifying domestic programme, a real delivery mechanism, and no downgrade for being ceremonial. Everything else lands in the sheet and waits. That is the point: an alert channel that fires on everything gets muted in a week.

Once the alerts were set up and I activated it, it started to run the next day. I just needed to do a few manual triggers to test everything.

What did not work was the first version of the dedupe. It looked like it was working and was quietly doing nothing. It checked each URL against the sheet one at a time. On a real Google Alerts digest it dropped every new URL, because the lookup only ever returned rows that were already there. It passed every test I ran, because I was testing one item at a time and n8n was filling the empty result for me. Only a real digest exposed it. At some point it died, so I needed to redo it. I fixed it using Claude Code, rebuilt that half to read the whole sheet once and filter in code, and made it more robust.

The principle underneath is that an alert is only worth building if it can say no. Anything can watch a keyword. The work is in the rules that throw things away: a region is not a country, a ceremonial meeting is not an engagement, a courtesy visit with no next step is not a signal. A channel that fires on everything gets muted in a week, and a muted channel is worth less than no channel, because everyone still believes it is working.

Thirteen nodes. The dedupe runs before the scraper, so a URL already in the sheet is never fetched or paid for twice. (click to enlarge)
The sheet keeps everything, including what it threw out. Rejected rows, rows needing review and failed fetches sit alongside the validated ones, which is what makes the alert channel quiet enough to stay useful. (click to enlarge)

The Systems behind This

The playbooks and AI skills used in work like this are published: the same systems with the client details stripped out, ready to run.

Or just say hello