Skip to content
watchingthat

Seven layers sit between your raw ad logs and AI agent answers you can trust.

Trusting the answers from an AI agent that you point at your log level data needs it to go through seven layers: ingestion, enrichment, unification, semantics, governed access, security and compliance, and consistency across users. Skip on just one and the agent always answer but the answer won't be based on anything that you can trust.

Your business wants to leverage AI to unlock all the insights in all the data it has stored on your ad stack. At first glance the route looks quick and obvious: Land the FreeWheel and Google Ad Manager files in the SQL warehouse, let an agent write SQL and hey presto the agent provides a pretty compelling answer.

The problem though is how it gets there. It does so by guessing, each and every time, what each value of data means and what the IDs stand for. It’s brimming with ignorant confidence. Nothing crashes, nothing complains. It’s dangerous to say the least.

If the raw data is akin to crude oil and your agents your hyper car engines, you need to properly extract, refine, enrich and deliver the data in the right amounts to make the agent the most effective it can be.

A refinery drawn as a stack of seven slabs, pale at the bottom and deep blue at the top. Raw ad log text pours in at the bottom and faint traces of it show in the lowest three slabs. From the bottom up: ingestion (files reconciled), enrichment (dated names), unification (one session), semantics (one meaning), governed access (checked requests), security and compliance (own login) and consistency (one number). One thin line leaves the top slab for your agent.
Figure 1. The seven layers as a refinery: crude logs go in at the bottom, and your agent draws only from the top.

1. Ingestion: files arrive late, corrected and sometimes twice

An agent is only as good as the data it consumes, and ad-server files can keep changing after they are first published. Google says most Data Transfer data arrives 5 to 15 hours after the hour it records, with delayed events taking up to eight days. And in that case a corrected file is posted with _corrected in its name beside the original, so an unaware loader may create duplicate values, or just miss them altogether.

So a naive agent asked at breakfast about last night may end up reading a partial data as a fall in revenue, and blame a partner for a drop that never happened.

A chart of one hour of Google Ad Manager Data Transfer data, its total as loaded against when you ask. Nothing has landed during the hour. Between 5 and 15 hours later the total climbs in steps as files land; asked at breakfast, it sits well below the true total and reads as a drop. Late events keep raising it for up to 8 days. When a _corrected copy lands beside the original, a loader that reads both counts the hour twice. Heights are illustrative.
Figure 2. One hour of Data Transfer data as Google describes its arrival: the total keeps moving long after the hour.

Not only does your ingestion step need to continuously work to keep the data up to date, but your agents need to know that data is very likely to keep changing well after the fact.

2. Enrichment: the agent needs names as they were on the day

Log level data is simply a record of output - typically denoted as events with a data record for that moment in time. By design they only store relevant fields and for compression and efficiency purposes they will store IDs rather than full text strings. Not only that they do not have any metadata of the state of the systems at those moments or indeed how they connect to all the other components in the stack.

So an agent, that thrives on context, can only do so much with just log data. To be fully contextualised IDs need to be resolved into metadata. Local system data sets need to be joined up into a holistic superset. Events need to be joined up to their sessions.

Example data. A log row from 28 September holds only IDs for site, campaign, deal and advertiser. Lookups turn three into names: Entertainment, Private sport and Example Motors. The campaign ID drops onto the campaign's dated name line, Spring launch to 30 September and Autumn launch from 1 October, and lands on Spring launch, its name that day, above that day's revenue bar. A dashed path shows the wrong join to today's name, which files the September row under Autumn launch.
Figure 3. Example data: each ID takes the name it had on the day, so September's revenue stays under September's name.

Metadata is also constantly in flux, so last month’s report needs every version of a setting kept with the dates it applied, which data modellers call a type 2 slowly changing dimension. An agent that joins to today’s metadata files September’s revenue under October’s campaigns, and nothing in the answer shows the switch. Even named, the rows are too scattered to count.

3. Unification: one long-form view is about a hundred rows

What’s in a view? Piecing together just one video view might seem simple and straightforward. But it rarely is because the implications are more nuanced - Videos can play back over 2hrs, live streams even longer. Events are scattered across large timespans and each has significant context that is needed to piece it all together. This leads into trawling hundreds of rows of complex relationships and metadata.

This requires highly sophisticated SQL query building, extensive knowledge of the data schema and knowing how to join between disparate data sets to get the unified data view that provides the full picture

Example data. On the left, 99 log rows from one 45-minute view of a drama episode, in the jumbled order they are logged. A fine thread runs from each row to its place on one session timeline: 4 ad breaks, 16 ads played and 3 failed slots, shown in orange.
Figure 4. Example data: every row of one view gathered into the session it belongs to.

Building this data is precise work, because a careless join returns a result that looks right. For example on Google Ad Manager, a very specialised data field called KeyPart identifies a bid auction in the Bids file and a query in the other files, this level of specialist knowledge is the difference between getting the right record of fact vs a hallucination. And a naive agent left to do this on its own, in its non-deterministic way, rebuilds the SQL on every question, a little differently each time.

4. Semantics: the agent guesses what your fields mean

When is an impression, not an impression, not an impression? FreeWheel, Google Ad Manager and your SSP reports each have something they call an impression but all are different and unique to their local points of view. Ask your agent for your total impressions for yesterday and without proper semantics you’ll get all sorts of crazy numbers.

Example data. Three grey bars of different lengths for yesterday, one per system: a FreeWheel impression event, Google Ad Manager's NetworkImpressions file and an SSP report's impressions column. Lines from all three lead to the agent's guess, marked in orange with a question mark. Below, one blue bar: Impressions, defined once and asked for by name, giving one number.
Figure 5. Example data: one word, three counts, until it is defined once.

Each data feed should provide a schema overlay to help with its own data but it won’t map a FreeWheel ad to the SpringServe supply tag, or to the SSP report that paid for it. Putting the meanings in the prompt fails too, since the IFScale benchmark found that even the best frontier models stop following instructions reliably once a prompt gets overwhelmed by long lists and data.

So the meaning has to sit in the data, defined once, where the agent can ask for a metric by name and get the same calculation every time.

5. Governed access: left alone, an agent scans a month of impressions

Ask a naive agent for all impressions last month and it may write SELECT * FROM impressions with no limit. On billions of rows, that query slows the warehouse for everyone, or autoscaling adds nodes and the cost arrives at the end of the month.

The bigger data set returned to the agent, the less accurate and attentive it becomes. Chroma found that a short, focused input beat the same question wrapped in a long one, and that even one distractor lowered performance.

The same question, all impressions last month, two ways. Left: the agent writes SELECT * FROM impressions, every row of the month is read, and a band as wide as the month floods the agent's window. Right: the agent sends a structured request (source, dates, metrics, group by, filters) to an MCP server, one slice of the month is read, and only a compact daily chart comes back.
Figure 6. The same question two ways, with the structured request keeping both the query and the result small.

The fix is to stop the agent writing SQL on the raw store. Pipe it through an MCP server that works like a linter instead. The agent sends a structured request (data source, dates, metrics, groupings, filters), and the server checks it against what exists, writes the query and/or holds a cache and returns only the answer.

6. Security and compliance: permissions follow the person

Not only can three people ask the same question three different ways but they have three different levels of rights to even ask the question: one may see revenue by advertiser, another only delivery. An agent on one shared service account sees everything that account can see, so all three get the same view breaking all the security and compliance in one go.

Example roles. A revenue lead, ad ops and an engineer, and the same data: four data sources, each with delivery and revenue. Through one shared account all three share one key, every view is full, ad ops sees revenue, and the account can write. Through their own logins, the revenue lead sees everything, ad ops sees delivery only, the engineer sees two data sources, and every view is read-only.
Figure 7. Who the agent is acting for decides what it can see and do.

Leveraging an MCP server will enforce security policies and provide audit level controls. Each agent has their own login, through single sign-on if you use it, so there are no API keys to hand out. The agent sees only what that login sees in the web app, and every tool is read-only, so it can’t create or change reports, monitors or settings.

7. Consistency: three phrasings, one answer

With the right data in front of each person, two people asking the same question on the same day must still get the same number. Agents are non-deterministic by design, so on raw logs each one writes its SQL a little differently and the same question can come back as two stories.

Example data. Three people ask the same question in different words: ad ops in Claude asks for programmatic earnings last week, the revenue lead in ChatGPT asks for programmatic revenue for the last 7 days, and an engineer in your own agent asks to sum programmatic revenue over the past week. Their three lines meet in one request and return one number, $184,200, the same for all three. Below, on raw logs, the same three questions come back as three different numbers: $171,940, $203,515 and $152,060.
Figure 8. Example data: three ways of asking, one request, one number.

The six layers below fix that, with each session built once, each metric given one meaning and each request compiled to the same query. Ad ops in Claude, the revenue lead in ChatGPT and an engineer in your own agent then get the same number. The agent keeps the work it is good at, understanding the question and explaining the answer.

Hold any build, ours included, to a test at every layer

Whoever builds it, the layer should give everyone the same answer within their own permissions, stay read-only and show numbers anyone can check. Those guarantees are won or lost one layer at a time, so test each layer on your own data before anyone acts on an answer.

What breaks without itWhat guards itHow to test it
IngestionA late, empty or _corrected file reads as a revenue drop or a double countCollect every feed as it lands, and alert when one breaks before any agent reads itCompare one hour from the files with the ad server's own report for that hour a day later
EnrichmentAnswers in IDs, or last month's revenue filed under this month's namesLook up every ID in the source system's API, and keep each name with the dates it appliedAfter a campaign is renamed, ask for last month's revenue by campaign. It should show the old name
UnificationAbout a hundred rows per view, rebuilt differently on every queryOne session per view, counted once, joined across ad servers and SSPsCount one view's ads by hand from the raw rows, then ask the agent for the same count
SemanticsThe agent picks one of several impression or revenue fields and doesn't say whichEach metric and dimension defined once, in ad-ops terms, and asked for by nameAsk which data source, dates and metrics it used, then open the same cut yourself and compare
Governed accessA SELECT * over a month of impressions slows the warehouse or scales up the billStructured requests, checked against what exists, compiled the same way every timeAsk for all impressions last month, then look at the query it ran and the rows it read
Security and complianceOne shared service account sees everything, and an agent with write access can change settingsRead-only tools on each person's own login, scoped to what that login can seeHave two people with different rights ask for revenue by advertiser, then list every tool the agent can call. Each tool should only read
ConsistencyTwo people ask the same question on the same day and get two numbersMeaning and query fixed below the agent, so the agent only phrases the answerTwo people ask ten revenue questions you know from the ad server's reports, twice each. The numbers should match
The seven layers in ad-ops terms, with a test for each that you can run on your own data.

Build the refinery, or plug into one that already runs

Could your team build all seven layers? Given enough time, probably. It takes engineers who know FreeWheel’s event types and Google’s corrected files, and someone keeping every ID lookup and name history current. It takes a semantic model for every metric, query governance, per-person access, and alerts that catch a broken feed before your agents do. Then you have to keep every one of them current whenever an ad server changes its log files, on its own schedule and without warning.

You would need a permanent data platform team, and the business’s questions would wait while it maintains the plumbing. Most broadcasters and publishers have it harder: they run FreeWheel alongside SpringServe or Google Ad Manager, plus SSP reports, bid-level logs and SSAI logs.

Two stacks of the same seven layers, fed by the same raw ad logs. Build all seven: every layer is hatched and unbuilt, a person sits on each one, a loop marks the work repeating with every log change, and your agents wait on a dashed line. Plug into one: the seven layers are solid blue with a live dot on each, marked with the Watching That eye as running for you, and your agents are connected on a solid line.
Figure 9. The same seven layers either way: built and kept by your own team, or already running.

That is exactly the crude Watching That was built to refine. The seven layers already run every day for our customers, and A+E Networks cut ad errors 70% in its first quarter on Watching That. When an ad server changes its log files, we update the connector.

So plug your own Claude or ChatGPT into the read-only Watching That MCP server, each person on their own login. Your agents run on refined data from the first question. Your data team spends its time on the questions the business is asking and on the agents that answer them.

Bring three of your own questions and see the layers on your own data

In 30 minutes we'll put three of your revenue questions to an agent connected through the Watching That MCP server, on your own ad stack, and show you each layer at work.

Book a 30-minute walkthrough on your own data

Or read how the Watching That MCP server works first.

Can the agent change anything through the Watching That MCP server?

No. All six tools read data, and none of them can create or change reports, monitors or settings.

How far back can the agent look?

Detailed data covers about the last seven days. For older periods the agent uses daily rollups, and a tool tells it first which dimension combinations those allow.

How do we test the difference on our own data?

Pick ten revenue questions whose answers you know from the ad server's own reports, and have two people ask each one twice, once through your raw-log agent and once through a governed layer. Compare the numbers and the token counts.