ChanlChanl
Agent Architecture

The Modern Data Stack Wasn't Built for Agents

Snowflake, dbt, and Fivetran were built for humans asking batch questions. Agents need streaming signals, per-entity memory in under 100ms, and write-back.

DGDean GroverCo-founderFollow
April 16, 2026
14 min read
Architecture diagram of an agentic data layer with event log, signal extraction, entity store, and improvement loop

The data team just finished a six-month migration to Snowflake plus dbt plus Fivetran. Dashboards refresh every morning. The exec team is happy. Someone printed a lineage graph and pinned it above the coffee machine.

Two desks over, the agent team is trying to ship a customer-facing bot. They need per-customer memory in under 100ms on the first turn. Structured extraction from every transcript, live. And the agent's own outputs written back somewhere durable. They look at the data stack. Nightly batch. SQL-over-warehouse. Ingest tools that treat the agent as a data source, never a participant.

Same company. Same substrate. Completely different requirements. And the pipeline the data team just spent six months standing up is not the one the agent team needs. It was never going to be.

The data stack we have is a read path for humans

The modern data stack, built roughly 2018 to 2024, solved one problem well: getting operational data into a warehouse so analysts could answer questions. Sources go through Fivetran. Warehouse is Snowflake. dbt models it. Looker or Hex reads it. At the end of the pipeline is a human sitting in a browser looking at a chart.

Every decision in that architecture follows from that end state. Batch, because nobody refreshes a dashboard mid-second. SQL, because analysts write SQL. Immutable tables, because revision history is for compliance and not for closed-loop use. It's an elegant design for the problem it was designed for. That said, the numbers suggest the maintenance tax is steep. Reporting has engineers on this stack spending roughly 70% of their time on maintenance, and tool sprawl hits unmanageable once a data team is carrying fifteen point solutions instead of five. (Nexla)

Everyone with a data team already has a version of the diagram below on a whiteboard somewhere. Draw it one more time, because the next few sections are about what happens when you put an agent at the end of it instead of a human.

Operational sourcesStripe, Postgres, CRM IngestionFivetran, Airbyte WarehouseSnowflake, BigQuery Transformdbt BILooker, Hex Humanwith a dashboard
The modern data stack: sources pass through ingestion, warehouse, transform, and BI before any human reads them.

Notice where the arrow ends. A human. Reading. On a schedule. Every decision in this stack, from latency budgets to caching to governance, is tuned for a person clicking a chart.

Why do agents break the warehouse on both sides?

The obvious problem is latency. A dashboard that refreshes at 6am is fine for a quarterly review. It's useless for an agent that has to know the customer's current subscription tier, last three tickets, and open billing dispute before the second token of its response. The warehouse is three orders of magnitude too slow for the read path. Not a little slow. Wrong-architecture slow.

The less obvious problem, and the one almost nobody is talking about, is that agents are not just a new consumer at the end of the pipeline. They are also a new producer. Every conversation spits out structured signal: extracted facts, scorecard grades, tool call traces, corrections a human had to apply to keep the agent honest. The old stack has no owner for any of that. Fivetran pulls from your sources. It does not know what to do when the sink is producing its own canonical data.

So you have an architectural gap on both sides. Read side: the warehouse can't serve fast enough and doesn't hold the right shape of data. Write side: nothing in the modern data stack was designed to own what the agent creates. Industry analysis through 2026 has landed on the same read. The stack is either consolidating into fewer vendors or being displaced by AI-native platforms built for this exact gap. (Definite, Modern Data 101)

So we need a new picture. Not a replacement for Snowflake, but a new set of layers that sit in front of it and take over the read and write paths for agents. That's what the rest of this is about.

Four layers the agent stack actually needs

An agentic data layer has four pieces: an event log, a signal extraction step, an entity and memory store, and an improvement loop. Each one maps directly to a failure mode of the batch stack. None of this is hypothetical. Each layer is already being built, either as its own category or inside the streaming revival that's been quietly going on underneath.

Layer 1: Event log, not a nightly dump

The conversation, not the row, is the atomic unit. Every utterance, tool call, agent response, and outcome gets appended to an event log with a stable schema. This is the opposite of the nightly Fivetran pull that condenses a day of activity into a single row update. The event log keeps the sequence and the structure, which is what everything downstream needs.

Kappa architecture, powered by Kafka and the wave of streaming databases built on top of it, is the closest existing pattern. Materialize and RisingWave both position themselves as serving AI agents specifically, with Materialize emphasizing strong consistency for operational workloads and RisingWave optimizing for high-throughput event streams. (Kai Waehner, Materialize, RisingWave)

The shape of an event in this log is simple, but the discipline of writing everything through it is what makes downstream extraction and memory tractable. A typical event might look like this.

event.ts·typescript
type ConversationEvent =
  | { type: 'message.inbound'; interactionId: string; entityId: string; text: string; ts: string }
  | { type: 'message.outbound'; interactionId: string; agentId: string; text: string; ts: string }
  | { type: 'tool.call'; interactionId: string; name: string; args: unknown; ts: string }
  | { type: 'tool.result'; interactionId: string; name: string; result: unknown; ts: string }
  | { type: 'interaction.ended'; interactionId: string; outcome: 'resolved' | 'abandoned'; ts: string };

Every event carries an entityId (the customer), an interactionId (the conversation), and a timestamp. That schema decision sounds trivial. It is the thing that makes signal extraction and entity memory possible six months later without a painful retrofit. Get it wrong now and you'll be paying for it when you have a million rows of undated, unscoped text blobs.

Layer 2: Signal extraction is its own step, not a side effect

Raw events are not useful to the agent on the next turn. What is useful is: "this customer mentioned churn risk with 0.87 confidence, source was message id X, extracted at Y." Signal extraction turns the event stream into structured, confidence-scored fields with provenance attached.

The old stack puts dbt at this layer, and dbt assumes the input is already structured rows. Conversations aren't rows. You need an extraction step that runs an LLM or a classifier against unstructured text, emits typed output, and keeps a pointer back to the source event. It has to run in streaming, not in nightly batch, because the agent on the next turn is the one who needs the extract.

We wrote a deeper treatment of why this extraction pattern matters for the Signal side of the loop in a previous post on conversations as CRM data. The short version is that every extracted field should carry four things: value, confidence, source event, and extractor version. Without all four, you lose the ability to debug, audit, or retrain.

Layer 3: Entity store, the thing the agent reads

The entity store is where everything converges into a per-customer view the agent can read in milliseconds. Facts, preferences, open issues, prior scorecard grades, compliance flags. Keyed by entity. Freshness measured in seconds. Latency measured in single-digit milliseconds.

Feature stores are the closest existing precedent. Feast, Tecton, and Chalk have spent years solving the "online features at low latency" problem for ML inference. Feast's recent MCP integration explicitly positions the feature store as a governed context and memory layer for AI agents, which is exactly the reframe this layer needs. (Feast, Tacnode)

But an entity store for agents is broader than a feature store. It needs natural language content, not just float vectors. It needs per-entity TTLs because a stale preference is worse than no preference. It needs write-back during the conversation, not just read at inference. And it needs to be scoped by agent as well as entity, since a support agent should not inherit everything a sales agent learned about the same customer. We went deep on the build side of this in build your own AI agent memory system, which walks through what actually breaks when real users show up.

Here is what reading and writing to that store looks like in practice, using a typical agent SDK shape.

entity-memory.ts·typescript
// Pre-turn: read everything relevant to this customer.
const memories = await sdk.memory.search({
  entityType: 'customer',
  entityId: 'cust_123',
  query: 'subscription, billing, preferences',
  limit: 20,
  minConfidence: 0.6,
});
 
const context = memories.map((m) => m.content).join('\n');
 
// Post-turn: write what the agent learned this conversation.
await sdk.memory.create({
  entityType: 'customer',
  entityId: 'cust_123',
  content: 'Asked about the Team plan. Wants SSO. Decision maker by April.',
  metadata: {
    confidence: 0.82,
    source: 'extraction',
    interactionId: evt.interactionId,
    extractorVersion: 'churn-v3',
  },
  ttlSeconds: 60 * 60 * 24 * 180, // 180 days
});

Two calls. Read before the turn, write after. The agent never talks to Snowflake on the hot path. That's the whole point of this layer.

The honest trade-off: you now have two sources of truth for the same customer. A stale preference in the entity store will outvote a fresh one in the warehouse, because the agent only sees the hot read. Write-back reconciliation, version skew between extractor outputs, and right-to-erasure across both stores are all real problems the dbt world never had to think about. There isn't a clean answer yet. Most teams pick the entity store as authoritative for anything the agent learned itself, and the warehouse for anything the agent didn't touch.

Customer service representative

Customer Memory

4 memories recalled

Sarah Chen
Premium
Last call
2 days ago
Prefers
Email follow-up
Session Memory

“Discussed upgrading to Business plan. Budget approved at $50k. Follow up next Tuesday.”

85% relevance

Mem0, Letta, and the wave of memory-specific frameworks have turned per-customer entity stores into their own category in 2026. Benchmarks, papers, and tooling around memory scoping, conflict detection, and graph-based relationships are all maturing fast. (Mem0, Atlan)

Layer 4: Improvement loop, the part most teams skip

Layer 4 is the one most teams skip, and it's also the one that turns "infrastructure" into "infrastructure that gets better." Every extracted signal, scorecard grade, tool result, and conversation outcome flows into an evaluation pipeline that retrains extractors, updates prompts, and grades the agent. Observability lives here too, and it stops being a separate category.

OpenTelemetry published GenAI Semantic Conventions in the last year that define how spans, tool calls, and prompts should be named and attributed. Langfuse, LangSmith, Arize Phoenix, and Helicone all consume OTel or OpenInference traces now. For the first time, the improvement loop has a standard wire format instead of four vendor-specific ones. (dev.to, LangChain)

We covered what to instrument in production in AI agent observability: what to monitor. That post still holds up. What's new is that traces are no longer just debugging artifacts. They are input for the next version of the agent. Grades feed the eval harness. Eval results feed prompt updates. Prompt updates feed back into the event log as a new agent version. Close the loop or don't bother.

How the four layers connect

The four layers are not a pipeline in the dbt sense. They're a loop. A conversation generates an event, the event generates a signal, the signal updates the entity store, the agent reads the entity store on the next turn, the conversation produces an outcome, and the outcome flows back into extractor retraining. The diagram below traces one turn through that loop.

Inbound message Append message.inbound Read entity memory Preferences, history, flags Response Append message.outbound Stream new events Update entity with extracted signal Stream events + outcomes Grade, evaluate, retrain Updated prompts and extractors Customer Agent Event log Signal extract Entity store Improve loop
The agentic data loop: conversation becomes event, event becomes signal, signal updates entity, agent reads entity on next turn, outcome feeds improvement.

Read that diagram as a single turn, then imagine it looping thousands of times a day per customer. The entity store never goes cold. Signals compound. The improvement loop tightens the gap between what the agent knows and what actually happened. This is the shape that Fivetran, Snowflake, and dbt are simply not built to produce. Not because they're bad products. Because they were optimized for a different end user.

Batch did not die. Snowflake got demoted.

Nobody is suggesting you rip out Snowflake. Snowflake stops being the serving layer and becomes the long-memory and analytics layer. The hot entity store answers the agent. Signals flow into the warehouse for cohort analysis, model training, and audit. The data team still does its work, but the work moves up the stack: extraction schemas, freshness SLOs on the entity store, signal versioning, improvement-loop governance. None of that was on the dbt roadmap, and pretending otherwise is how you end up with a dbt job that runs an LLM over yesterday's transcripts and calls it agent memory.

Layer 1Event logKafka, streaming DB Layer 2Signal extractionLLM, classifiers Layer 3Entity storeper-customer memory Layer 4Improvement loopevals, grades, traces Warehouselong memory + analytics Agent runtime
Four layers of the agentic data stack, with batch warehouse relegated to long memory rather than primary serving.

That's the mental model. Four layers serve the agent in real time. The warehouse sits off to the side as archival and analytical storage. You're not replacing your data stack. You're growing a new one alongside it that owns everything the old one was never built for.

What does a data team own in an agentic stack?

The work does not disappear. It moves. A data team in an agentic stack owns the pieces below, and most of them are new categories of work, not renamed old ones.

What they owned beforeWhat they own now
Ingestion pipelines (Fivetran jobs)Event log schema and retention
dbt models and testsExtraction schemas and extractor versioning
Table freshness SLOsEntity store freshness and TTL policy
BI dashboardsScorecard definitions and grading pipelines
Data quality testsConfidence calibration on extracted signals
Warehouse cost monitoringLatency and cost on the hot read path
Compliance (row-level security)Entity scoping, agent scoping, right-to-erasure

Every one of those is a real job someone has to do. Miss the extraction schemas and the agent reasons over garbage. Miss freshness SLOs and the entity store quietly lies. Miss right-to-erasure at the entity layer and you have a GDPR incident, not a data quality incident. The data team does not shrink when agents arrive. It just starts working on a different substrate.

The work on the Chanl side of this is pretty literal. Signal runs layer 2 against every conversation. Memory runs layer 3 as a per-entity, per-agent, TTL-aware store. Monitoring and Scorecards close layer 4 by capturing outcomes and grading against the same extraction schemas the agent used. You do not have to wire all four together yourself. But you do have to decide, as a team, who owns what.

Signal, Agents, Improve map onto real layers

Build, Connect, Monitor is how we usually describe Chanl. Underneath that, there's an older framing that maps more directly onto this architecture: Signal, Agents, Improve. Signal is what comes out of every conversation. Agents are the runtime that reads and writes memory. Improve is the loop that closes the gap. It isn't positioning. It's the shape of the four-layer stack above.

Go back to the two teams from the opening. The data team's migration isn't wasted. Keep the warehouse. You're going to want it for analytics, audit, and long memory. But stop pretending it's the stack the agent team asked for. Start the event log. Start extraction. Start the entity store. The batch world keeps running, and the streaming world starts compounding alongside it. That's how you end up with an agent that gets better week over week instead of one that quietly drifts until someone files a ticket.

Run Signal, Agents, and Improve on Chanl

Event log, signal extraction, per-entity memory, and a grading loop in one platform. Works with any voice, chat, or messaging runtime.

See how it fits your stack
DG

Co-founder

Building the platform for AI agents at Chanl — tools, testing, and observability for customer experience.

The Signal Briefing

One email a week. How leading CS, revenue, and AI teams are turning conversations into decisions. Benchmarks, playbooks, and what's working in production.

500+ CS and revenue leaders subscribed

Frequently Asked Questions