The first multi-agent system I built was at Google. At first glance, the product looked simple. A user opened a chat interface and asked a business question.
They could ask:
- βWhat was revenue last month?
- βWhy did paid subscriptions decline?
- βWhich customer segments contributed most to growth?
- βWhich customers are likely to churn?
- βWhat will revenue be next quarter?
- βCan you build a churn prediction model?
The user did not need to upload a dataset, write SQL, identify a table, or select a machine-learning algorithm. The system was expected to determine what data was required, retrieve it from BigQuery, validate it, analyze it, and return an understandable answer.
But behind that simple interface was a complex, governed analytics workflow.
This was not just an exploratory data analysis tool. It was a conversational analytics and machine-learning system that combined natural-language understanding, metric governance, SQL generation, query validation, data-quality controls, analytical execution, machine learning, evaluation, and human oversight.
The Core Problem
Business users often know the question they want answered, but they do not always know:
- βwhich table contains the data;
- βhow the metric is officially defined;
- βwhich joins are approved;
- βwhat filters must be applied;
- βwhich comparison period is appropriate;
- βwhether the request requires descriptive analytics, diagnostic analysis, forecasting, or machine learning.
For example, a user may ask:
Why did paid subscriptions decline last month?
That question sounds straightforward, but the system must resolve several details before producing an answer.
A general-purpose language model could make assumptions about these questions. In an enterprise analytics environment, however, assumptions can produce incorrect business decisions.
The system therefore needed governance before generation.
The End-to-End Workflow
The final architecture followed this general flow:
Each stage had a clearly defined responsibility.
That separation became especially important after the first version exposed weaknesses in answer quality, hallucination, query reliability, and latency.
Intake Agent Versus Orchestrator
One of the most important design decisions was separating the intake agent from the orchestrator. They were not the same component.
The intake agent interpreted the userβs request. For a question such as βWhy did paid subscriptions decline last month?β the intake agent extracted:
- βuser intent;
- βprimary metric;
- βrequested date range;
- βcomparison period;
- βdimensions;
- βfilters;
- βbusiness context;
- βpotential ambiguity;
- βrequested output type.
It also classified the task. Examples included:
- ββWhat was revenue last month?β β descriptive analytics
- ββWhy did revenue decline?β β diagnostic analytics
- ββWhich customers are likely to churn?β β predictive machine learning
- ββWhat will revenue be next quarter?β β forecasting
- ββBuild a churn model.β β supervised model-development workflow
The output of the intake agent was structured rather than conversational. For example:
{
"intent": "diagnostic_analysis",
"metric": "paid_subscriptions",
"date_range": {
"current_period": "previous_calendar_month",
"comparison_period": "month_before_previous"
},
"dimensions": [
"country",
"acquisition_channel",
"subscription_plan"
],
"filters": [],
"requires_clarification": false
}The intake agent did not decide every downstream action. It understood and structured the request.
The orchestrator managed workflow execution. Its responsibilities included:
- βdeciding which component ran next;
- βpassing approved state between stages;
- βchecking whether validation succeeded;
- βtriggering retries;
- βstopping invalid workflows;
- βrequesting user clarification;
- βenforcing human-review requirements;
- βpreventing agents from bypassing controls.
We implemented the orchestrator primarily as deterministic workflow logic rather than as a completely autonomous AI agent. The AI could classify the request and recommend an analytical route. The application decided whether that route was permitted.
For example:
This distinction mattered because a free-thinking supervisor agent could skip steps, repeat work, create unnecessary model calls, or route a request directly into analysis before the data had been validated.
The orchestrator acted as the control plane.
Metric Governance and the Semantic Layer
Before generating SQL, the system retrieved approved business definitions. The language model was not allowed to invent the meaning of a metric.
For example, the approved definition of paid subscriptions could include:
- βofficial metric name;
- βmetric description;
- βapproved calculation;
- βrequired filters;
- βsource tables;
- βapproved joins;
- βtime-column definitions;
- βdimension mappings;
- βdata owner;
- βdata freshness expectations;
- βaccess restrictions.
A structured metric definition drove SQL generation directly. For example, the generated query could look like this:
SELECT DATE_TRUNC(subscription_date, MONTH) AS subscription_month, country, acquisition_channel, COUNT(DISTINCT subscription_id) AS paid_subscriptions FROM `project.analytics.fact_subscriptions` WHERE subscription_status = 'active' AND is_trial = FALSE AND payment_status = 'paid' AND subscription_date BETWEEN @start_date AND @end_date GROUP BY 1, 2, 3 ORDER BY 1, 2, 3;
The SQL generation agent did not have permission to execute the query directly.
This was intentional.
The component creating the query was not allowed to be the only component deciding whether the query was correct or safe.
Three-Layer SQL Validation
We validated SQL using three complementary approaches:
- deterministic validation scripts;
- LLM-based semantic validation;
- human evaluation.
Each layer caught a different class of failure.
Deterministic scripts checked rules that could be enforced reliably in code. These checks included:
- βvalid SQL syntax;
- βallowed statement types;
- βapproved datasets and tables;
- βprohibited operations;
- βpresence of date filters;
- βrequired metric filters;
- βapproved join paths;
- βrestricted columns;
- βuse of query parameters;
- βrow-level access requirements;
- βprohibition of SELECT *;
- βquery-size limits;
- βestimated bytes processed;
- βtimeout and cost thresholds.
The system also performed a BigQuery dry run before execution. The dry run helped estimate query cost and identify query errors without processing the full dataset.
Deterministic validation was appropriate for controls that should not depend on probabilistic reasoning. For example, an LLM should not be responsible for deciding whether a DELETE, UPDATE, or unapproved table reference is permitted. Those rules belong in code.
A query can be syntactically valid and still answer the wrong question. The LLM validation layer examined whether the generated SQL matched:
- βthe userβs intent;
- βthe approved metric definition;
- βthe requested date range;
- βthe comparison period;
- βthe expected dimensions;
- βthe analytical granularity.
For example, the LLM validator could detect that:
- βthe query calculated total subscriptions rather than paid subscriptions;
- βtrials were not excluded;
- βthe date comparison used 30 days rather than calendar months;
- βthe query grouped by country but omitted acquisition channel;
- βthe query answered βwhat changedβ but not βwhy it changed.β
The LLM validator returned a structured decision:
{
"status": "failed",
"issues": [
{
"type": "metric_mismatch",
"description": "The query does not exclude trial subscriptions."
},
{
"type": "date_mismatch",
"description": "The query uses rolling 30-day periods instead of calendar months."
}
],
"approved_for_execution": false
}Human reviewers evaluated SQL and answers against known business questions and expected results. The review process included:
- βpredefined test questions;
- βapproved reference queries;
- βknown metric outputs;
- βedge cases;
- βambiguous requests;
- βcomplex joins;
- βincomplete data scenarios;
- βquestions that should trigger clarification.
Human review was especially important during early development because it exposed failure patterns that automated evaluations did not yet capture. For example, a response could contain technically correct SQL but still be misleading because the analytical interpretation overstated causality.
Human evaluation helped us assess the full user experience, not just SQL correctness.
Query Execution and Data Retrieval
After the SQL passed validation, the application executed the query through a controlled BigQuery service account.
The execution layer applied:
- βscoped credentials;
- βread-only permissions;
- βdataset allowlists;
- βtimeouts;
- βscan limits;
- βrow limits;
- βlogging;
- βquery identifiers;
- βuser-level access checks.
Agents did not receive unrestricted warehouse credentials. They interacted with approved tools such as:
get_metric_definition() get_table_schema() validate_sql() estimate_query_cost() execute_bigquery_query()
This tool-based design reduced risk and made each action auditable.
Returned-Data Validation
Successful query execution did not mean the data was ready for analysis.
The returned dataset was validated before entering the EDA or modeling workflow.
- βwhether any rows were returned;
- βrequired columns;
- βexpected data types;
- βdate coverage;
- βfreshness;
- βmissing values;
- βduplicate keys;
- βimpossible values;
- βvolume anomalies;
- βjoin duplication;
- βmetric reconciliation;
- βgranularity;
- βclass balance;
- βtarget availability;
- βpotential data leakage.
For example:
{
"status": "passed_with_warnings",
"row_count": 1864,
"date_coverage": {
"minimum": "2026-05-01",
"maximum": "2026-06-30"
},
"warnings": [
"Acquisition channel is missing for 4.8% of rows.",
"One regional source is 18 hours behind the expected refresh time."
],
"blocking_issues": [],
"approved_for_analysis": true
}This stage addressed an important reality:
A query can be valid while the returned data is still incomplete, stale, duplicated, or inappropriate for modeling.
Routing Into Analytics, EDA or Machine Learning
Once the dataset passed validation, the orchestrator routed it based on the original request.
What was revenue last month?
The system calculated:
- βtotals;
- βaverages;
- βcounts;
- βrates;
- βtrends;
- βperiod-over-period changes.
Why did subscriptions decline?
The system examined:
- βsegment contributions;
- βcountry-level changes;
- βacquisition-channel changes;
- βplan-level changes;
- βshifts in customer mix;
- βstatistically significant deviations;
- βcorrelated business drivers.
For an EDA request, the workflow evaluated:
- βdistributions;
- βmissingness;
- βduplicates;
- βoutliers;
- βcorrelations;
- βcardinality;
- βtarget relationships;
- βtemporal patterns;
- βclass imbalance;
- βpotential leakage.
For forecasting requests, the system validated:
- βtime granularity;
- βhistorical coverage;
- βmissing periods;
- βseasonality;
- βtrend stability;
- βexternal-event considerations.
For supervised machine-learning requests, the workflow included:
- βtarget validation;
- βleakage checks;
- βtrain-validation-test splitting;
- βpreprocessing;
- βbaseline creation;
- βcandidate model training;
- βcross-validation;
- βerror analysis;
- βexplainability;
- βmodel recommendation.
What Went Wrong in V1
Our first version demonstrated the potential of the system, but it also revealed several weaknesses. Only about 60% of answers consistently met our internal quality bar.
The most common issues included:
- βhallucinated metric definitions;
- βincorrect table selection;
- βinvalid or incomplete SQL;
- βmissing filters;
- βincorrect date interpretation;
- βunsupported causal claims;
- βanalysis based on incomplete data;
- βrepeated agent calls;
- βlong response times;
- βinconsistent answer formatting.
The initial architecture gave too much freedom to the model. Some agents received overly broad prompts. Some responsibilities overlapped. Agents occasionally reinterpreted decisions that had already been made upstream. In some cases, the system generated SQL, executed it, and interpreted the results without enough independent validation between stages.
We also learned that adding more agents could increase latency without improving quality. Every additional agent introduced:
- βanother model call;
- βanother prompt;
- βadditional state;
- βmore potential failure points;
- βmore opportunities for conflicting conclusions.
The goal therefore became controlled specialization, not maximum agent count.
How We Improved Answer Quality
We introduced several changes.
Agents stopped passing long unstructured narratives to one another. Instead, they exchanged typed objects containing:
- βintent;
- βmetric;
- βdimensions;
- βfilters;
- βdate range;
- βquery;
- βvalidation status;
- βwarnings;
- βdata profile;
- βanalytical result.
The orchestrator enforced allowed workflow transitions. Agents could no longer bypass validation stages. The workflow knew exactly what should happen when:
- βa metric was unavailable;
- βSQL validation failed;
- βa query exceeded the cost limit;
- βdata was incomplete;
- βuser clarification was required;
- βhuman review was mandatory.
Metric definitions were retrieved from approved sources instead of being generated from model memory. This reduced inconsistent calculations and hallucinated business logic.
We separated SQL generation from SQL approval. Deterministic scripts handled security and rule-based checks. An LLM handled semantic alignment. Human evaluators reviewed representative queries and answers.
Returned data had to meet defined quality requirements before analysis could proceed. This prevented polished explanations from being generated from incomplete or unreliable data.
We created representative evaluation sets containing:
- βstraightforward questions;
- βambiguous questions;
- βquestions requiring clarification;
- βcomplex metric calculations;
- βmulti-table joins;
- βedge cases;
- βunsupported requests;
- βmachine-learning requests.
We removed agents that did not provide meaningful independent value. Some tasks were converted into deterministic functions. Some tasks were performed in parallel. Others were skipped when the required result was already available in the shared state.
The system did not retry indefinitely. For example, a failed SQL query could receive one or two controlled revisions. After that, the workflow stopped or requested human intervention. This reduced latency and prevented expensive retry loops.
Structured state reduced interpretation drift between agents.
Results
After introducing stronger governance, validation, routing, and evaluation, answer quality improved from approximately 60% to roughly 85% against our internal quality criteria. We also materially reduced hallucinations.
Latency improved because the system made fewer unnecessary model calls, reused structured context, and moved deterministic work out of the LLM layer. The exact architecture was less important than the principle behind it: AI handled interpretation, planning, and explanation. Deterministic software handled access, policy enforcement, validation, execution, and workflow control. Humans remained responsible for evaluating critical outputs and approving high-impact use cases.
Key Trade-Offs
- βspecialization;
- βclearer ownership;
- βbetter traceability;
- βeasier testing;
- βbetter fault isolation.
- βhigher cost;
- βgreater latency;
- βmore state-management complexity;
- βmore failure points;
- βmore conflicting outputs.
We learned not to create an agent for every small task. A component should become an agent only when it requires distinct reasoning, context, tools, or evaluation.
An AI supervisor can support flexible routing. However, fully autonomous routing is harder to test and govern. We chose a hybrid design. AI interpreted the userβs request. Deterministic code enforced the permitted workflow.
- βDoes this SQL answer the userβs question?
- βDoes the query align with the approved metric definition?
- βIs the explanation supported by the result?
- βIs the query read-only?
- βDoes it reference an approved table?
- βIs a date filter present?
- βDoes the query exceed the scan limit?
- βIs a restricted column included?
The strongest system used both.
Additional validation improved reliability but added processing time. We reduced the impact by:
- βrunning independent checks in parallel;
- βcaching metric definitions and schemas;
- βusing smaller models for classification;
- βlimiting query revisions;
- βavoiding repeated context;
- βmoving calculations into BigQuery and Python.
The system automated a significant portion of analytics work. It did not eliminate human responsibility. Human review remained important for:
- βmetric-definition changes;
- βhigh-impact business decisions;
- βsensitive data use;
- βmodel-deployment approval;
- βcausal interpretation;
- βnew analytical workflows;
- βevaluation of unexpected outputs.
The Broader Lesson
A multi-agent system is not simply several prompts connected together.
A production system requires:
- βclear responsibilities;
- βgoverned context;
- βtyped state;
- βdeterministic orchestration;
- βrestricted tools;
- βindependent validation;
- βdata-quality gates;
- βevaluation datasets;
- βobservability;
- βhuman oversight.
The most important architecture decision was not how many agents we used. It was deciding which responsibilities belonged to AI and which belonged to traditional software.
- βunderstanding intent;
- βresolving language;
- βplanning analysis;
- βinterpreting results;
- βexplaining findings.
- βauthentication;
- βauthorization;
- βSQL policy enforcement;
- βquery execution;
- βdata validation;
- βcost controls;
- βstate transitions;
- βaudit logging.
That separation helped move the system from an impressive prototype to a more reliable analytics product.
And that remains one of my biggest lessons from building multi-agent systems:
The intelligence does not come only from the model. It comes from the architecture surrounding the model.
About the Author. Tobe Awosanya is a Technical Founder and AI Product & Governance Leader working across AI engineering, agentic systems, AI evaluation, and technical AI governance. Her work focuses on translating AI product and governance requirements into practical system, control, and implementation decisions for teams building and adopting AI systems.
Considering Building a Multi-Agent System?
Multi-agent systems can look impressive in a demo and still fail in production because of weak orchestration, poor validation, unnecessary agent complexity, rising model costs, latency, and hallucinated outputs.
Through Data Techcon AI Advisory, I help founders and teams design practical multi-agent architectures that are easier to govern, evaluate, and scale.
- βdetermine whether your use case actually needs multiple agents;
- βdefine the right agent responsibilities and workflow;
- βseparate AI reasoning from deterministic application logic;
- βdesign validation, guardrails, evaluation, and human-review controls;
- βchoose the appropriate models, tools, data architecture, and orchestration framework;
- βidentify cost, latency, security, and reliability risks before development begins.
Whether you are validating an early idea, reviewing an existing architecture, or preparing to move a prototype into production, you can book an advisory session to get expert guidance tailored to your product and use case.
Book an Advisory Session