The execution layer for advertising.
The execution layer is the missing last mile, where a decision becomes money spent on Meta, Google, and TikTok. We build it.
The execution layer that makes ad agents accurate, optimised and secure.
The missing layer of advertising that other industries have.
Stripe built it for payments. Twilio for communications. Unity for gaming. Salesforce for customer data. LangChain for agents. Zyou builds it for advertising, in the agentic era.
Why agents fail when pointed at raw platform endpoints.
It drowns in data.
A raw connector dumps ~90–100K tokens into the agent's context. It runs out of room and starts making mistakes within a couple of prompts.
It guesses, fails, retries until blocked.
An agent half-remembers hundreds of fields and parameters. There is no ads library the model was trained on. So it guesses, gets rejected, and retries until the account is rate-limited or flagged.
It silently works with half the data.
A timeout caused 200/500 rows being pulled. But the agent finishes confidently and reports a clean answer. No one can tell which rows went missing.
Message: Call was not successfulMethod: GETPath: https://graph.facebook.com/v23.0/me/Params: {'fields': 'id,name'} Status: 400Response: { "error": { "message": "Got unexpected null", "type": "OAuthException", "code": 190, "fbtrace_id": "AAiPVXeNypq48ztGa30906U" } }
zyou_facebook.core.exceptions.AuthenticationError: Your Facebook access token is invalid or has expired. → Fix: Generate a new token at https://developers.facebook.com/tools/explorer/ Required permissions: ads_management, ads_read, pages_read_engagement → FB Error Code: 190→ Trace ID: ArOuKnJhD4dKNpZJa88HCgL
Same expired token, two outcomes. Zyou's core engine turns every platform error into a typed, human-readable failure with the fix attached, so the agent recovers instead of guessing.
Not a connector. A stack.
Existing connectors are the raw platform with a wrapper. Zyou is the five layers that make an agent safe and useful on live spend. Your team sees "connectors." What sits underneath is an invisible execution layer. And that layer is your moat.
What we connect.
L1 is more than the places you spend, it's every source that tells you whether the spend worked.
A new source is a connector, not a rebuild.
Everything in is optimised. Everything out is validated.
The agent asks an exact question; Zyou returns the exact answer: queried, completeness-checked, processed locally. Answers, not data dumps.
vs a raw pull that quietly returns 200 / 500 (see "why it fails")
Zyou makes the platform call, never the agent. Claude supplies the arguments; Zyou validates them against the real schema and executes. Nothing reaches a platform unchecked.
Clean data in. Validated actions out. Nothing the agent isn't supposed to do.
Your team sets the limits. The system enforces them.
Governance lives in the runtime, not in a policy document.
Every agent acts within its user's permission. A planner can plan; it can't launch.
Actions above a threshold (budget increases, launches, audience changes) stop and route to a human. One click to proceed.
Every action logged: what changed, who authorized it, when.
The agent cannot self-authorize anything above its scope. That isn't a promise. It's the design.
What Zyou actually buys you.
from facebook_business.api import FacebookAdsApi
from facebook_business.adobjects.adaccount import AdAccount
from facebook_business.adobjects.adset import AdSet
from facebook_business.adobjects.targeting import Targeting
import time
APP_ID = "your_app_id"
APP_SECRET = "your_app_secret"
ACCESS_TOKEN = "your_access_token"
AD_ACCOUNT_ID = "act_your_account_id"
CAMPAIGN_ID = "your_campaign_id"
FacebookAdsApi.init(APP_ID, APP_SECRET, ACCESS_TOKEN)
targeting = {
Targeting.Field.geo_locations: {
"countries": ["US"],
"regions": [{"key": "4081"}],
},
Targeting.Field.age_min: 25,
Targeting.Field.age_max: 55,
Targeting.Field.genders: [1, 2],
Targeting.Field.publisher_platforms: ["facebook", "instagram"],
Targeting.Field.facebook_positions: ["feed", "story"],
Targeting.Field.instagram_positions: ["stream"],
Targeting.Field.device_platforms: ["mobile", "desktop"],
Targeting.Field.flexible_spec: [
{"interests": [
{"id": "6003139266461", "name": "Technology"},
{"id": "6003020834693", "name": "E-commerce"},
]},
],
}
start_time = int(time.time()) + 3600
end_time = start_time + (7 * 24 * 3600)
account = AdAccount(AD_ACCOUNT_ID)
params = {
AdSet.Field.name: "My Python Ad Set",
AdSet.Field.campaign_id: CAMPAIGN_ID,
AdSet.Field.status: AdSet.Status.paused,
AdSet.Field.daily_budget: 5000,
AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
AdSet.Field.start_time: start_time,
AdSet.Field.end_time: end_time,
AdSet.Field.targeting: targeting,
AdSet.Field.attribution_spec: [
{"event_type": "CLICK_THROUGH", "window_days": 7},
{"event_type": "VIEW_THROUGH", "window_days": 1},
],
}
try:
adset = account.create_ad_set(
fields=[AdSet.Field.id, AdSet.Field.name],
params=params,
)
print("Ad Set created:", adset[AdSet.Field.id])
except Exception as e:
print("Error creating Ad Set:", e)from zyou_facebook import AdsetModel, TargetingModel, ConversionLocation, BidStrategy, init, create_adset init(ACCESS_TOKEN, AD_ACCOUNT_ID) targeting = TargetingModel({...}) adset_params = AdsetModel({ "campaign_id": campaign["campaign_id"], "adset_name": "TRMNL Adset", "targeting": targeting, "conversion_location": ConversionLocation.ON_AD, "bid_strategy": BidStrategy.HIGHEST_VOLUME, "is_dynamic_creative": True, }) adset = create_adset(params=adset_params)
A single campaign change is hundreds of fields against the raw API, every key and enum typed by hand, in the dark. The agent supplies a handful of named arguments; Zyou builds the full payload, validates it against the platform's real schema, and ships it.