⚡ DemandLoop

An autonomous growth engine for ecommerce brands that plans, creates, launches, measures, and improves paid acquisition on Google — continuously.

A founder gives DemandLoop a business goal such as:

Acquire as many profitable new customers as possible while keeping CPA at or below $18, staying inside the daily budget, and never scaling a product that is low on inventory.

DemandLoop turns that goal into a continuous operating loop:

observe → plan → create → validate → launch → measure → scale → learn → repeat

It connects Gemini, Google Agent Development Kit (ADK), Google Ads API, Merchant Center, Shopify, Google Cloud, and Google image-generation capabilities into one agentic growth system.

DemandLoop is not a dashboard that tells a founder what happened, and it is not a chatbot that recommends what the founder should do next. The core idea is that the agents perform the repetitive operational work themselves: constructing campaigns, generating creative briefs and assets, creating Google Ads resources, reading performance, reallocating budget inside policy, recording experiment outcomes, and launching the next controlled test.

Molten Coffee is the live ecommerce brand used to demonstrate DemandLoop. Molten Coffee is the demo environment, not the submitted product.


🎯 1. The Goal: What Is DemandLoop Actually Optimizing?

An autonomous growth system needs an explicit objective function. Otherwise “optimization” becomes a collection of arbitrary model decisions.

For the Molten Coffee demo, the founder defines:

PRIMARY OBJECTIVE
Maximize profitable new-customer acquisition

PRIMARY KPI
Cost per new-customer purchase <= $18

HARD CONSTRAINTS
Daily account spend <= founder-defined ceiling
Campaign spend <= campaign ceiling
Never scale inventory-constrained products
Respect minimum product margin
Use only approved brand claims
Require approval for material spend changes
Require sufficient conversion evidence before scaling

The founder controls the goal and policy. Agents control the tactics.

That means DemandLoop may decide:

  • which product to promote,
  • which audience hypothesis to test,
  • which creative angle to generate,
  • which Demand Gen surfaces to target,
  • which bidding strategy to configure,
  • which losing asset to reduce,
  • which winning campaign deserves more budget,
  • and what experiment should run next.

But it cannot silently change the $18 target, raise the account-wide spending ceiling, ignore inventory, or remove approval requirements.

DemandLoop is autonomous inside a bounded strategy space.


🧩 2. Why This Needs Agents Instead of Normal Automation

Normal ecommerce automation is excellent for deterministic workflows:

Shopify order paid
        ↓
Send order to fulfillment provider

That should remain deterministic. There is no reason to insert an LLM.

Growth decisions are different:

Sales slowed this week.

Is traffic down?
Is conversion down?
Which product has enough margin and inventory to scale?
Which campaign is responsible?
Is a creative fatigued?
Should budget move or should we wait for more evidence?
What new hypothesis would teach us the most?

Those decisions require context from several systems, trade-offs, interpretation, planning, and follow-up action.

DemandLoop therefore uses agents for reasoning and typed software services for deterministic execution.

DETERMINISTIC SYSTEMS
Shopify • Merchant Center • Google Ads • APIs • Firestore
                   │
                   ▼
             FRESH BUSINESS STATE
                   │
                   ▼
              AGENT REASONING
       plan • compare • choose • coordinate
                   │
                   ▼
             PERMISSIONED TOOLS
   query • create • mutate • pause • scale • record

☕ 3. End-to-End Demo: Molten Coffee

The demo is intentionally built around one complete growth cycle rather than a collection of disconnected AI features.

Step 1 — DemandLoop reads the business before buying more traffic

Suppose the business goal is:

Target CPA:          <= $18
Total ad budget:     $100/day
Market:              United States
Objective:           new-customer purchases

Fresh Shopify / product data shows:

COORG RESERVE
Inventory: 82 units
Current advertising spend: $35/day

COORG SUNRISE
Inventory: 716 units
Current advertising spend: $8/day

The Demand & Merchandising Agent produces a machine-readable eligibility decision:

coorg_reserve:
  status: DO_NOT_SCALE
  reason: inventory_constraint

coorg_sunrise:
  status: ELIGIBLE_TO_SCALE
  max_growth_budget: 40

The system therefore does not blindly optimize the campaign with the highest short-term conversion rate. Product reality affects media buying.

Step 2 — Growth Strategist creates the experiment

The Growth Strategist receives the founder goal, live product state, prior experiments, brand constraints, and current Google Ads performance.

It emits a typed CampaignPlan:

campaign_plan_id: plan_042
objective: acquire_new_customers
product: coorg_sunrise
market: US
channel: DEMAND_GEN
primary_metric: cost_per_purchase
target_cpa_usd: 18
initial_budget_usd: 20
bidding_strategy: MAXIMIZE_CONVERSIONS
creative_hypothesis: "Coorg provenance will outperform generic premium-coffee messaging"
audience_hypotheses:
  - premium_coffee_enthusiasts
  - provenance_oriented_food_shoppers
approval_required_for_activation: true

That object — not free-form conversation — becomes the contract for downstream agents.

Step 3 — Creative Director turns the hypothesis into assets

The Creative Director receives:

  • real Molten product packshots,
  • logo and brand assets,
  • typography/colors,
  • approved product claims,
  • winning/losing historical creatives,
  • placement requirements,
  • audience hypothesis,
  • and the campaign goal.

It can output several CreativeSpec objects:

creative_id: provenance_v2_portrait
format: 4:5
angle: origin_story
visual_direction: "lush Coorg hillside, editorial morning light"
headline: "Coffee with a sense of place."
supporting_copy: "Single-origin Arabica from Coorg."
cta: "Discover Molten"
asset_roles:
  - portrait_marketing_image
  - square_marketing_image
  - landscape_marketing_image
  - logo

Google image-generation capabilities can create new backgrounds / scenes / visual variants. Real Molten packshots and logo assets remain fixed inputs so the system does not hallucinate a new package design every time.

Step 4 — Media Buyer constructs real Google Ads resources

The campaign plan is converted into a MutationPlan containing concrete Google Ads operations.

For Demand Gen the dependency graph is:

CampaignBudget
      │
      ▼
Campaign (DEMAND_GEN)
      │
      ▼
AdGroup
      │
      ├────────► Audience
      │               │
      │               ▼
      │        AdGroupCriterion
      │
      ├────────► Assets
      │           ├─ TextAsset
      │           ├─ ImageAsset
      │           ├─ VideoAsset
      │           └─ Carousel Card Asset
      │
      ▼
AdGroupAd

The campaign is created PAUSED. Activation is a separate permissioned operation.

Step 5 — DemandLoop waits for evidence and measures the result

After the configured evaluation window, the Growth Analyst queries Google Ads again.

Suppose it observes:

Creative A
CPA: $27
Purchases: 18
Result: UNDERPERFORMING

Creative B
CPA: $14
Purchases: 31
Result: WINNER

Creative C
CPA: $16
Purchases: 4
Result: INSUFFICIENT_EVIDENCE

DemandLoop does not treat Creative C as a winner just because its current CPA is below target. The sample size is too small under the configured evidence rule.

Step 6 — Exploit the winner

Creative B is below the target CPA, has enough conversions, and the product has healthy inventory.

The Media Buyer can progressively increase spend inside policy:

$20/day
   ↓ +20%
$24/day
   ↓ measure again
$29/day
   ↓ measure again
$35/day

At every step DemandLoop checks:

  • CPA versus target,
  • conversion volume,
  • conversion value / ROAS when used,
  • inventory,
  • account budget,
  • campaign budget ceiling,
  • creative fatigue,
  • and approval policy.

The first failed guardrail stops further scaling.

Step 7 — Explore something better

At the same time, the Creative Director receives the experiment outcome:

Repeated signal:
Origin/provenance creative > generic product creative

It generates controlled variants around the winning hypothesis instead of random new ads.

For a $100/day acquisition budget, policy might reserve:

$75 → proven campaigns / creatives
$25 → controlled experiments

That gives DemandLoop two simultaneous modes:

EXPLOIT: scale what is already proving profitable.

EXPLORE: spend a bounded portion of budget learning what might be better.


🤖 4. Five Specialized Agents, Not One Giant Prompt

DemandLoop is implemented as a supervisor-and-specialist system. The agents do not share one giant prompt containing every API, credential, historical experiment, and brand asset.

Each agent has a narrow responsibility and communicates using typed artifacts.

🧠 Growth Strategist

Owns: campaign hypothesis and allocation strategy.

Reads:

  • founder goal,
  • Shopify revenue / conversion state,
  • margins,
  • eligible products,
  • existing campaigns,
  • experiment history,
  • strategic memory.

Outputs: CampaignPlan, ExperimentHypothesis, AllocationProposal.

Key question: What should we test or scale next, and why?

📦 Demand & Merchandising Agent

Owns: whether a product should receive additional demand.

Reads:

  • inventory,
  • price,
  • margin,
  • catalog state,
  • Merchant Center feed status,
  • product-level ad performance.

Outputs: ProductEligibility and product-level spend constraints.

Key question: Should the growth system create more demand for this product right now?

🎨 Creative Director

Owns: translating a hypothesis into platform-ready creative.

Reads:

  • brand kit,
  • real product assets,
  • placement requirements,
  • historical asset performance,
  • creative learnings.

Outputs: CreativeSpec, image-generation requests, text assets, creative family IDs.

Key question: What creative expression tests this specific hypothesis?

💰 Media Buyer

Owns: Google Ads execution.

Reads: CampaignPlan, ProductEligibility, CreativeSpec, spend policy.

Outputs: MutationPlan, BudgetDecision, campaign/resource IDs.

Key question: How do I safely turn the strategy into real Google Ads resources and changes?

📊 Growth Analyst

Owns: evaluation.

Reads: fresh Google Ads metrics + experiment definition.

Outputs: ExperimentResult, ScaleDecision, LearningCandidate.

Key question: Did the experiment actually move the business objective, and what should change next?


🔗 5. How Agents Interact: Structured Contracts

Agents do not send each other arbitrary paragraphs. Their hand-offs are validated structured objects.

BusinessGoal
    │
    ▼
Growth Strategist
    │
    ├── CampaignPlan ───────────────┐
    │                               │
    ▼                               ▼
Demand Agent                  Creative Director
    │                               │
    └── ProductEligibility          └── CreativeSpec
             │                             │
             └──────────────┬──────────────┘
                            ▼
                       Media Buyer
                            │
                       MutationPlan
                            │
                            ▼
                     Google Ads API
                            │
                     resource IDs
                            │
                            ▼
                      Growth Analyst
                            │
              ExperimentResult / ScaleDecision
                            │
               ┌────────────┴────────────┐
               ▼                         ▼
         Media Buyer               Strategic Memory
       scale / reduce                    │
               │                         ▼
               └──────────────► next Strategist run

Representative Pydantic-style contracts:

class ProductEligibility:
    product_id: str
    state: Literal["ELIGIBLE_TO_SCALE", "HOLD", "DO_NOT_SCALE"]
    max_incremental_daily_spend: Decimal
    reasons: list[str]

class ExperimentResult:
    experiment_id: str
    primary_metric: str
    observed_value: Decimal
    purchase_count: int
    evidence_sufficient: bool
    outcome: Literal["WINNER", "HOLD", "LOSER"]
    recommended_budget_delta_pct: int

The model proposes values; deterministic validation verifies types, bounds, and policy before any external side effect.


⚙️ 6. Workflow Runtime: How One Growth Cycle Executes

Each growth cycle is treated as a durable workflow rather than a single LLM call.

CREATED
  ↓
SNAPSHOT_BUSINESS_STATE
  ↓
BUILD_STRATEGY
  ↓
CHECK_PRODUCT_ELIGIBILITY
  ↓
GENERATE_CREATIVE_SPEC
  ↓
BUILD_MUTATION_PLAN
  ↓
VALIDATE
  ↓
WAITING_FOR_APPROVAL (when required)
  ↓
EXECUTE
  ↓
VERIFY_GOOGLE_ADS_STATE
  ↓
MEASUREMENT_WINDOW
  ↓
ANALYZE
  ↓
LEARN
  ↓
CLOSED / NEXT_EXPERIMENT

Firestore stores the durable state:

run_id: run_20260821_0042
status: MEASUREMENT_WINDOW
campaign_plan_id: plan_042
experiment_id: exp_042
google_ads_resources:
  campaign: customers/.../campaigns/...
  ad_group: customers/.../adGroups/...
  ads:
    - customers/.../adGroupAds/...
approval_status: approved
last_completed_step: verify_google_ads_state
next_evaluation_at: 2026-08-23T10:00:00Z
retry_count: 0

Because state is stored outside the model runtime, a Cloud Run instance can disappear and the workflow can resume without reconstructing business state from chat history.


📣 7. Google Ads API: The Real Execution Surface

Google Ads is not represented as a generic manage_ads() tool. DemandLoop exposes focused tools around actual Google Ads resources and services.

Authentication and capability boundary

The integration layer manages:

  • OAuth 2.0 credentials,
  • Google Ads developer token,
  • customer ID,
  • manager-account / login customer context when required.

The Gemini agents never receive raw refresh tokens or developer-token values.

Instead they receive bounded tools such as:

ads.query_campaign_performance(...)
ads.query_asset_performance(...)
ads.create_demand_gen_draft(...)
ads.update_campaign_budget(...)
ads.pause_campaign(...)
ads.enable_campaign(...)
ads.query_change_events(...)

🔎 8. Google Ads Read Path: GAQL + SearchStream

GoogleAdsService.Search / SearchStream and Google Ads Query Language (GAQL) provide the read layer.

DemandLoop uses different reporting views instead of asking Gemini to reason over one enormous unstructured API response.

Campaign-level query

SELECT
  campaign.id,
  campaign.name,
  campaign.status,
  campaign.advertising_channel_type,
  campaign_budget.amount_micros,
  metrics.impressions,
  metrics.clicks,
  metrics.ctr,
  metrics.average_cpc,
  metrics.cost_micros,
  metrics.conversions,
  metrics.cost_per_conversion,
  metrics.conversions_value,
  metrics.conversions_value_per_cost
FROM campaign
WHERE segments.date DURING LAST_7_DAYS

Asset-level learning

For Demand Gen, ad_group_ad_asset_view links an asset to the ad in which it served. DemandLoop can use it to evaluate the actual asset/ad pairing instead of assigning performance to an entire creative family blindly.

Conceptually:

SELECT
  campaign.id,
  ad_group.id,
  ad_group_ad.ad.id,
  asset.id,
  ad_group_ad_asset_view.field_type,
  ad_group_ad_asset_view.performance_label,
  metrics.impressions,
  metrics.clicks,
  metrics.conversions,
  metrics.cost_micros
FROM ad_group_ad_asset_view
WHERE segments.date DURING LAST_14_DAYS

This enables learning at multiple levels:

Campaign level  → Is the strategy working?
Audience level  → Who is responding?
Ad level        → Which assembled ad wins?
Asset level     → Which image/headline/video contributes?
Product level   → What should receive more demand?

API output is normalized into internal metric objects before being passed to Gemini.


🏗️ 9. Google Ads Write Path: Atomic Demand Gen Construction

Demand Gen campaigns are a graph of dependent resources. DemandLoop builds the entire graph before sending the mutation.

CampaignBudget
      ↓
Campaign
      ↓
AdGroup
      ├── Audience / criteria
      ├── Assets
      └── AdGroupAd

The Campaign is configured with:

advertising_channel_type = DEMAND_GEN
status                   = PAUSED
campaign_budget          = newly created non-shared budget
bidding                  = strategy selected from policy-compatible options

Demand Gen supports bidding approaches including Maximize Clicks, Maximize Conversions, Target CPA, and Target ROAS. DemandLoop chooses among these based on the business objective and available conversion evidence rather than allowing the model to invent a bidding algorithm.

Temporary resource IDs

Dependent resources can be assembled in one mutation using temporary negative IDs.

budget temp id:   -1
campaign temp id: -2  → references budget -1
ad group temp id: -3  → references campaign -2
assets:           -4, -5, -6 ...
ad:               -9  → references ad group -3 + assets

The plan is then sent through GoogleAdsService.Mutate so closely related resources can be created together rather than leaving a half-created campaign if a required entity fails.

The Media Buyer persists the returned permanent Google resource names after mutation.


✅ 10. Validation and Human Approval Before Spend

DemandLoop separates reasoning from authority.

Gemini creates strategy
        ↓
Typed MutationPlan
        ↓
Schema validation
        ↓
Policy engine
        ↓
Google Ads validate_only
        ↓
Human approval if required
        ↓
Real mutation
        ↓
Read-after-write verification

Example policy:

Create campaign <= $25/day       → may create PAUSED draft
Enable brand-new campaign        → requires approval
Increase existing budget <= 20%  → autonomous if all guardrails pass
Increase budget > 20%            → requires approval
Daily account ceiling exceeded   → blocked
Inventory constrained            → blocked
Evidence insufficient            → blocked from scaling

This is enforced in deterministic code outside the prompt.


📺 11. Demand Gen Channel Controls

DemandLoop can coordinate media placement and creative format using Demand Gen ad-group channel controls.

A hypothesis might explicitly select:

  • YouTube In-Feed,
  • YouTube In-Stream,
  • YouTube Shorts,
  • Discover,
  • Gmail,
  • Maps,
  • or Display where appropriate.

Example:

experiment_id: shorts_origin_video_01
channel_configuration:
  youtube_shorts: true
  youtube_in_feed: false
  youtube_in_stream: false
  discover: false
  gmail: false
  maps: false
primary_metric: cost_per_purchase
creative_format: vertical_video

That means “test vertical video” is not merely a creative instruction. The media placement, asset type, experiment record, and measurement window are all tied together.


🎨 12. Demand Gen Ad and Asset Construction

The Media Buyer can assemble supported Demand Gen formats including:

  • multi-asset ads,
  • carousel ads,
  • video-responsive ads,
  • and product-oriented Demand Gen ads when a Merchant Center feed is attached.

Carousel tests can be represented as a sequence of product / storytelling cards. Multi-asset tests can isolate portrait, square, landscape, headline, and description combinations. Video-responsive tests can use vertical creative for Shorts-focused experiments.

Every generated asset receives internal metadata before upload:

asset_id: creative_provenance_v2_portrait
creative_family: provenance_v2
hypothesis_id: exp_042
model_generation_id: img_...
source_product_asset: molten_coorg_sunrise_packshot_v3
role: PORTRAIT_MARKETING_IMAGE

When Google returns the permanent Asset resource name, DemandLoop links it back to the internal experiment record. This makes later GAQL asset-level reporting interpretable.


🛍️ 13. Merchant Center + Shopify: Product-Aware Advertising

DemandLoop is specifically built for ecommerce, so paid media cannot be separated from the product catalog.

For product-feed Demand Gen campaigns, DemandLoop can associate a linked Merchant Center account using the campaign's shopping configuration and use ListingGroup criteria to decide which products are included or excluded.

Shopify
  ├─ inventory
  ├─ price
  ├─ margin
  └─ orders
        │
        ▼
Merchant Center
  ├─ product feed
  ├─ approval / feed state
  └─ Google-facing product identity
        │
        ▼
Demand Agent
        │
        ├─ include eligible products
        └─ exclude constrained products
        │
        ▼
ListingGroup criteria
        │
        ▼
Demand Gen product ads

This is why the Demand Agent exists separately from the Media Buyer: the advertising account may say a product is performing well while the business says it cannot absorb more demand.


🎯 14. Conversion Measurement: Optimize Purchases, Not Clicks

DemandLoop treats CTR and CPC as diagnostic metrics. The business objective is a purchase outcome.

The measurement layer focuses on:

new-customer purchases
conversions
conversion value
cost per conversion / CPA
conversion value per cost
ROAS when relevant

Where the ecommerce measurement flow requires uploaded first-party conversion events, the architecture can use Google Ads conversion upload capabilities with transaction identifiers / deduplication logic.

The Growth Analyst receives normalized conversion metrics together with the experiment's primary KPI. This prevents a visually appealing ad with a high CTR but poor purchase performance from becoming a “winner.”


🧠 15. Memory Architecture: Four Different Kinds of Memory

DemandLoop deliberately does not use a giant conversation transcript as memory.

Layer 1 — Live source-of-truth state

These facts are always re-read from the authoritative system:

Shopify inventory
Shopify orders
current product price
current Google Ads spend
campaign status
live performance metrics
Merchant Center product status

A remembered statement can never override a fresher API fact.

Layer 2 — Workflow / session state

ADK session state handles short-lived context needed during the current agent interaction. Durable run state lives externally in Firestore so the system survives process restarts and multiple Cloud Run instances.

Examples:

current experiment
selected product
pending campaign plan
approval decision
current workflow step

Layer 3 — Experiment memory

Every growth test is stored structurally:

experiment_id: exp_042
hypothesis: provenance creative reduces CPA
product: coorg_sunrise
audience: premium_coffee
creative_family: provenance_v2
channel: demand_gen
budget_before: 20
budget_after: 24
primary_metric: CPA
observed_cpa: 14.00
purchases: 31
outcome: WINNER
started_at: ...
evaluated_at: ...

This is the empirical history of what DemandLoop actually tried.

Layer 4 — Strategic memory

Repeated outcomes become compact reusable learnings for future planning.

Examples:

For new-customer acquisition, provenance-led creative repeatedly outperformed generic premium positioning.

Creative family provenance_v2 showed fatigue after approximately 18 days.

Premium-coffee audience A performed well for Coorg Sunrise but poorly for Reserve.

Budget increases above 20% tended to degrade CPA faster than staged 15–20% increases.

These learnings are retrieved selectively. The Creative Director needs visual/creative learnings. The Media Buyer needs budget / audience / campaign learnings. The Demand Agent needs product-level demand learnings.


🧬 16. How DemandLoop Self-Improves

“Self-improving” does not mean DemandLoop rewrites its source code, changes the founder's safety policy, or trains a new model after every campaign.

It improves through closed-loop empirical learning:

1. OBSERVE
   fresh business + advertising state

2. HYPOTHESIZE
   choose one useful thing to test

3. EXECUTE
   create the actual campaign / creative / allocation

4. MEASURE
   wait for configured evidence window

5. EVALUATE
   compare primary metric against target and control/history

6. LEARN
   write ExperimentResult + LearningCandidate

7. ADAPT
   scale, reduce, hold, or design the next experiment

8. REPEAT

A learning only becomes strategic memory after it passes consolidation rules. One lucky result should not become a permanent truth.

For example:

Experiment 1: provenance creative wins
Experiment 2: provenance creative wins
Experiment 3: no clear difference
Experiment 4: provenance creative wins

→ promote "provenance works for this product/audience" into strategic memory

The next strategy cycle retrieves that prior but still validates it against fresh data.


📈 17. Budget Scaling Engine: Winner Does Not Mean “Triple Spend”

Suppose:

Target CPA = $18
Creative B CPA = $14
Purchases = 31

The Growth Analyst emits:

outcome: WINNER
evidence_sufficient: true
recommended_budget_delta_pct: 20

The Media Buyer then checks deterministic constraints:

Is product inventory healthy?        YES
Is CPA below target?                 YES
Minimum purchase count reached?      YES
Account daily cap available?         YES
Campaign ceiling available?          YES
Increase <= autonomous limit?        YES

Only then is the budget mutation allowed.

After scaling, the experiment is not closed forever. A new observation window asks whether performance survived the increased spend.

$20/day @ $14.00 CPA
        ↓
$24/day @ $14.80 CPA
        ↓
$29/day @ $17.10 CPA
        ↓
$35/day @ $20.40 CPA
        ↓
STOP / ROLLBACK OR HOLD

This gives DemandLoop a controlled feedback system rather than a one-time optimization rule.


⚖️ 18. Explore vs. Exploit

The budget allocator maintains a policy-controlled split between known winners and learning.

$100 daily acquisition budget

$75 exploitation pool
  └─ campaigns already meeting business target

$25 exploration pool
  └─ new audiences / creative / placements / product hypotheses

Experiments can graduate:

EXPERIMENT
   ↓
WAIT FOR EVIDENCE
   ↓
WINNER ─────────► exploitation pool
HOLD   ─────────► continue measuring
LOSER  ─────────► reduce / pause

The split is configuration, not a number invented by Gemini. A founder can use 90/10, 75/25, or another policy.


🔄 19. Reconciling Manual Human Changes

The founder may still open Google Ads and change a campaign manually. DemandLoop must not assume its stored copy of the account is always correct.

Before material changes, the Media Buyer performs a fresh read. The architecture can also query Google Ads ChangeEvent data to understand recent account changes, including whether a resource was changed through the API or another client.

Example:

DemandLoop planned:
Budget = $29/day

Founder manually changed Google Ads:
Budget = $40/day

Next DemandLoop cycle:
read fresh state
  ↓
detect mismatch / change
  ↓
do NOT blindly write $29
  ↓
re-plan from $40 current truth

This makes human intervention compatible with autonomy rather than creating a fight between the founder and the agent.


🛡️ 20. Security and Permission Model

The LLM is not the security boundary.

Controls are enforced in software:

  • secrets stored server-side / Secret Manager,
  • least-privilege service identity,
  • read tools separated from write tools,
  • strict Pydantic / JSON schemas,
  • spend limits checked outside the model,
  • campaign activation gated separately from campaign drafting,
  • no raw OAuth or developer credentials inside prompts,
  • external text treated as untrusted data,
  • tool results validated before being stored as authoritative state.

The agent can request an operation. The tool layer determines whether that operation is legal.


🔁 21. Reliability: Idempotency, Retries, and Partial Failure

Agent systems become dangerous if a retry can duplicate a paid action.

DemandLoop assigns stable identifiers:

run_id
experiment_id
mutation_plan_id
action_id

Side-effecting operations store the intended action and the resulting Google resource ID.

Before retrying, the executor checks whether the action already succeeded.

network timeout after mutation
        ↓
DO NOT automatically create another campaign
        ↓
query expected resource / stored response state
        ↓
confirm whether first action succeeded
        ↓
retry only if safe

Transient failures use bounded exponential backoff. Permanently invalid operations move the workflow to FAILED_VALIDATION or REQUIRES_REVIEW rather than looping.

For larger asynchronous mutation sets, Google Ads BatchJobService provides an additional batch-oriented execution path with mixed operations and transient-error retry behavior, while synchronous atomic mutates remain preferable for a tightly coupled small campaign graph.


👀 22. Observability and Audit Trail

Every run records operational metadata instead of exposing private model chain-of-thought.

run_id: run_042
trigger: scheduled_growth_cycle
agents_called:
  - strategist
  - demand
  - creative
  - media_buyer
  - analyst
tools_called:
  - shopify.get_products
  - ads.search_stream
  - ads.validate_mutation
  - ads.mutate
policy_decisions:
  - budget_within_limit
  - inventory_eligible
approval_events:
  - campaign_activation_approved
final_state: MEASUREMENT_WINDOW
latency_ms: ...

Cloud Logging / tracing can correlate events using run_id and experiment_id across Cloud Run, Pub/Sub, ADK, and external integrations.

The UI can therefore answer:

What did DemandLoop change, which evidence caused the decision, which policy allowed it, and what happened afterward?


☁️ 23. Google Cloud Architecture

                 ┌──────────────────────────────┐
                 │      ECOMMERCE SYSTEMS       │
                 │ Shopify • Merchant Center    │
                 └──────────────┬───────────────┘
                                │
                                ▼
                       Cloud Run adapters
                                │
                                ▼
                             Pub/Sub
                                │
                                ▼
                 ┌──────────────────────────────┐
                 │      ADK ORCHESTRATOR        │
                 │       Gemini 3.5+            │
                 └──────────────┬───────────────┘
                                │
         ┌──────────────────────┼─────────────────────┐
         ▼                      ▼                     ▼
 Growth Strategist       Creative Director       Media Buyer
         │                      │                     │
 Demand Agent       Google image generation      Google Ads API
         │                      │                     │
         └──────────────────────┼─────────────────────┘
                                ▼
                         Growth Analyst
                                │
                ┌───────────────┼────────────────┐
                ▼               ▼                ▼
            Firestore       Agent memory     Cloud Logging
        workflow/experiments  learnings        + tracing
                │
                ▼
                     next growth cycle

Core Google stack

  • Gemini 3.5+ — planning, multimodal creative reasoning, analysis, structured decisions
  • Google ADK — supervisor / specialist agent orchestration and session context
  • Google Ads API — campaign resource construction, GAQL reporting, budget mutations, asset reporting, Demand Gen controls
  • Merchant Center / Merchant APIs — product and catalog context
  • Google image-generation capabilities — creative scene and variant generation
  • Cloud Run — agent services and integration endpoints
  • Pub/Sub — asynchronous workflow events
  • Firestore — durable workflow state and experiment registry
  • Secret Manager — external credentials
  • Cloud Logging / tracing — run-level observability
  • Python + Pydantic — typed contracts, validation, policy enforcement

🧪 24. Testing and Evaluation

DemandLoop is evaluated as a workflow system, not by asking whether generated prose “sounds good.”

Tool tests

  • invalid Google resource input rejected,
  • budget above policy rejected,
  • product with low inventory rejected,
  • API timeout handled,
  • malformed Shopify response handled.

Agent contract tests

Given a fixture business snapshot, validate that agents return schema-valid:

  • CampaignPlan,
  • ProductEligibility,
  • CreativeSpec,
  • MutationPlan,
  • ExperimentResult.

Policy tests

Budget +15%, healthy inventory, enough purchases → allowed
Budget +40%                              → approval required
Low inventory                            → blocked
Only 3 purchases                         → hold, do not scale

Workflow recovery tests

Simulate:

  • duplicated Pub/Sub event,
  • agent restart,
  • mutation timeout,
  • expired approval,
  • user manually changing Google Ads,
  • partial external API outage.

End-to-end test

A complete test starts with a founder goal and business snapshot and ends with:

  1. structured strategy,
  2. generated creative specification,
  3. valid Google Ads mutation graph,
  4. campaign created paused,
  5. approval event,
  6. campaign activation,
  7. GAQL performance read,
  8. winner/loser decision,
  9. bounded budget mutation,
  10. experiment memory update.

🎬 25. What the Hackathon Demo Will Prove

The demo is designed to make autonomous action visible rather than hide everything behind a chat UI.

The judge will see:

1. Founder goal
   "Acquire customers below $18 CPA"

2. Live/fixture Shopify + product state
   DemandLoop chooses Coorg Sunrise, not low-stock Reserve

3. Agent plan
   CampaignPlan + audience + creative hypothesis

4. Creative generation
   New Molten creative family generated from real brand assets

5. Google Ads construction
   CampaignBudget + Campaign + AdGroup + Audience + Assets + Ad

6. Safety
   validate_only + PAUSED creation + approval boundary

7. Execution
   real Google Ads mutation / deployed Google Cloud backend

8. Measurement
   GAQL campaign + asset metrics

9. Autonomous optimization
   $14 CPA winner receives bounded budget increase
   $27 CPA loser is reduced / paused

10. Self-improvement
    experiment stored, strategic learning updated,
    next controlled creative test generated

The important part is the loop: DemandLoop does not stop after creating an ad. It uses the result of that ad to decide and execute what happens next.


🌍 Why It Matters

Large ecommerce companies can employ a growth strategist, creative strategist, media buyer, merchandising analyst, and performance analyst.

A small Shopify brand often has one founder opening five dashboards and manually performing all five jobs.

DemandLoop explores a different operating model:

The founder defines the business objective and boundaries. A coordinated team of agents handles the repetitive planning, execution, measurement, and iteration required to pursue it.

Molten Coffee is the proof environment. The underlying architecture is designed to generalize to ecommerce brands whose growth decisions depend on the same loop of catalog → creative → media → conversion → learning → allocation.


🛠️ Current Build Status

DemandLoop is being built for the All Things Agentic Hackathon with a deliberately bounded MVP: one end-to-end Demand Gen growth loop that is deep enough to prove real autonomy, memory, Google Ads execution, safety controls, and Google Cloud deployment.

The project page describes the target architecture and demo contract. Final implementation evidence — repository, architecture image, deployed Cloud Run proof, screenshots, Google Ads resource proof, test results, and demo video — will be attached as the build is completed.

Built With

  • firestore
  • gaql
  • gemini
  • google-adk
  • google-ads-api
  • google-cloud-logging
  • google-cloud-run
  • google-pub/sub
  • google-secret-manager
  • memory-bank
  • merchant-center-api
  • pydantic
  • python
  • shopify-api
  • vertex-ai
Share this project:

Updates