Metadata MCP Connector
Server Details
Connect Metadata to AI assistants for B2B advertising performance reports, audience planning, brand-aware creative, and campaign launch-readiness checks. Uses secure OAuth with an existing Metadata account and appropriate connected-channel permissions. Hosted Streamable HTTP endpoint maintained by Metadata Inc.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
TDQS
Scored across 171 tools
The tool set has many overlapping and near-duplicate tools. There are two campaign creation tools (create_campaign vs create_native_structure_campaign), two campaign edit tools (add_and_edit_campaign_elements vs add_and_edit_native_campaign_elements), and a huge family of audience creation tools (create_firmographic_audience, create_bombora_audience, create_technographic_audience, create_g2_intent_dynamic_audience, create_g2_intent_linkedin_native_dynamic_audience, create_g2_intent_static_audience, create_linkedin_native_criteria_audience, create_facebook_native_criteria_audience, create_retargeting_audience, create_linkedin_engagement_retargeting_audience, etc.) that are distinguished only by subtle type differences. The descriptions are extremely detailed and do try to disambiguate, but the sheer number of similar tools makes misselection likely.
Most tools follow a verb_noun pattern (create_*, get_*, list_*, remove_*, update_*), but there are notable inconsistencies: create_update_* mixes create and update into one verb, some tools use different naming for the same concept (create_audience_from_segment vs create_firmographic_audience vs upload_account_list_csv_audience), and there are oddities like 'account_funnel_reports' (noun_noun) vs 'account_level_stats'. The naming is mostly predictable but not consistent enough for a 4.
171 tools is an extreme count for any MCP server. Even for a comprehensive advertising platform, this is far beyond what an agent can effectively navigate. The tool count alone makes the server unwieldy, and many tools could be consolidated (e.g., the ~20 create_*_extension tools, the ~10 audience creation tools, the ~6 stats tools).
The server covers an impressively complete lifecycle for the advertising domain: campaign creation/editing/launching/pausing/duplicating, ad creation/archiving, audience creation/archiving, offer creation, budget groups, performance stats, UTM management, negative keywords, extensions, and integrations. Minor gaps exist (e.g., no tool to edit account-level UTM defaults, no hard-delete for ads, some channel settings are draft-only), but the surface is remarkably complete for its scope.
Available Tools
171 toolsaccount_funnel_reportsGet Account Funnel Stage ReportsARead-onlyInspect
Account-level funnel performance across stages.
USE FOR: Account progression through funnel stages, account engagement/conversion analysis, social media account reach, account-level pipeline/revenue tracking.
REQUIRED: startDate, endDate, reportTab
REPORT TABS:
REACHED: Accounts reached by campaigns
ENGAGED: Accounts that engaged with content
CONVERTED: Accounts that converted (leads)
MQL: Marketing qualified accounts
OPPS: Accounts with opportunities
WON: Accounts with closed-won deals
Include company name AND domain when available in results.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based) | |
| size | No | Number of results per page. Default: 15, Max: 10000 — raise it to pull the full funnel set in one call. | |
| sort | No | Sort criteria. Examples: 'impressions,desc' (default), 'engagement,desc', 'conversions,desc' | impressions,desc |
| type | No | Report type. Currently only SOCIAL is supported | SOCIAL |
| endDate | Yes | End date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: '2025-12-31T23:59:59.999Z' | |
| reportTab | Yes | Funnel stage to analyze. Options: REACHED (default), ENGAGED, CONVERTED, MQL, OPPS, WON | REACHED |
| startDate | Yes | Start date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: '2025-01-01T00:00:00.000Z' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, covering the safety profile. The description adds valuable behavioral context by defining what each funnel stage means and specifying that results include company name and domain when available, setting output expectations beyond the annotations. No contradiction detected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured with clear labeled sections: core purpose, USE FOR, REQUIRED, REPORT TABS. Every section earns its place; there is no filler or repetition. The most important scoping decision (report tab meanings) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only report tool with fully documented parametersща, the description covers the essential invocation context: what the tool returns (funnel stage metrics) and which parameters are mandatory. The absence of an output schema is partly mitigated by the report tab definitions and the note about company name/domain, though a fuller return structure would be stronger.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description enhances this by explaining the semantics of each reportTab enum value (REACHED, ENGAGED, etc.), which the schema merely lists. It also highlights the three required parameters, making the call contract clearer.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement of the resource ('Account-level funnel performance') and the tool's action (retrieve reports across stages). The title reinforces it as 'Get Account Funnel Stage Reports'. The list of REPORT TABS concretely defines the resource and distinguishes it from generic account stats or list tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section explicitly enumerates four concrete use cases (progression, engagement/conversion analysis, social reach, pipeline/revenue tracking), giving the agent clear applicability. It does not name alternatives or exclusion conditions, but the directive list is sufficient for selection among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_level_statsGet Account-Level StatisticsARead-onlyInspect
Account-level statistics and channel breakdown for a timeframe.
USE FOR: General account stats by period, channel breakdown, high-level metrics (ROI, spending, leads, opportunities), custom date ranges. NOT FOR: Campaign-level info (use experiment_performance_stats), specific experiments (use get_experiments).
CHANNELS: FACEBOOK, LINKEDIN, GOOGLE ADS, ALL
TIMEFRAME LOGIC:
'quarter'/'Q1-Q4' → timeframe='QUARTER'
'week'/'weekly' → timeframe='WEEK'
≤3 months → timeframe='MONTH'
3 months → timeframe='QUARTER'
Default: timeframe='MONTH'
CUSTOM DATE RANGE: Provide ONLY startDate + endDate (NO timeframe). Format: ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ)
METRICS: impressions, clicks, spent, leads, mqls | opens, sends, actionClicks (CONVO/MESSAGE ads) | triggeredOpps, triggeredOppsAmount, influencedOpps, influencedOppsAmount | triggeredClosedWonOpps, triggeredClosedWonOppsAmount | roiInfluencedOpp, roiTriggeredOpp | cpc, cpl, cpm, ctr, conversionRate | costPerOpen, costPerSend (CONVO/MESSAGE ads) | customFields array
CONVO/MESSAGE AD CAVEAT: opens, sends, actionClicks (and their per-cost derivatives) are the success metrics for CONVO and MESSAGE (LinkedIn message) ad types. clicks/ctr/cpc are typically 0 for these ads — do not treat that as "no performance". If account-level data shows high spend with 0 clicks, drill into experiment_performance_stats or get_ad_details to confirm ad type before drawing conclusions.
| Name | Required | Description | Default |
|---|---|---|---|
| endDate | No | End date for custom date range in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Must be used together with startDate. Do NOT provide timeframe when using this. Example: 2025-09-30T00:00:00.000Z | |
| startDate | No | Start date for custom date range in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Must be used together with endDate. Do NOT provide timeframe when using this. Example: 2025-07-01T00:00:00.000Z | |
| timeframe | No | Timeframe for data aggregation. MONTH=monthly breakdown, QUARTER=quarterly breakdown, WEEK=weekly breakdown, YEAR=yearly breakdown. DO NOT use this parameter when providing startDate and endDate. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, destructiveHint=false, so the tool is safe to call. The description adds useful context like the CONVO/MESSAGE ad caveat, warning that clicks/ctr/cpc are typically 0 for those ad types. However, it contains a significant behavioral inconsistency: it states timeframe can be 'MONTH' but the schema enum only allows QUARTER, WEEK, YEAR. This misleads the agent about accepted values and default behavior, undermining transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (USE FOR, NOT FOR, CHANNELS, TIMEFRAME LOGIC, CUSTOM DATE RANGE, METRICS, CONVO/MESSAGE AD CAVEAT). It is front-loaded with the core purpose and usage guidance. It is somewhat long, but the length is justified by the detailed caveat and metric listing. Every section serves a purpose, though the flawed timeframe logic could be considered unnecessary or misleading.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must explain what is returned. It lists available metrics and the CONVO/MESSAGE caveat, which helps. However, it does not specify the response structure or how to select a channel (despite listing CHANNELS), and the timeframe discrepancy leaves the agent uncertain about valid inputs. Given the tool's complexity and absence of output schema, these gaps make the description incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides detailed descriptions for startDate, endDate, and timeframe (100% coverage). The description adds timeframe logic and custom date range rules, but the timeframe mapping includes 'MONTH' which is not in the enum, so the added semantics are incorrect. It also mentions CHANNELS (FACEBOOK, LINKEDIN, GOOGLE ADS, ALL) but does not explain how to specify a channel given the schema has no channel parameter, leaving a semantic gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Account-level statistics and channel breakdown for a timeframe.' It also explicitly differentiates from sibling tools by stating 'NOT FOR: Campaign-level info (use experiment_performance_stats), specific experiments (use get_experiments).' This gives a specific verb, resource, and scope, and distinguishes it from alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit USE FOR and NOT FOR sections, naming alternative tools for other scopes. It also gives detailed timeframe logic and custom date range instructions. However, the timeframe logic includes a mapping to 'MONTH' which is not present in the schema's enum (which only has QUARTER, WEEK, YEAR), creating potential confusion about when and how to use the timeframe parameter. This inconsistency reduces the clarity of usage instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_list_performanceGet Account List PerformanceARead-onlyInspect
Account list information with engagement metrics and statistics.
USE FOR: Account list performance/engagement, ABM list effectiveness, account journey metrics (reached, engaged, converted, qualified), account list pipeline/opportunities, comparing account lists, conversion funnel analysis. NOT FOR: Campaign-level details (use experiment_performance_stats), individual experiment performance (use performance_metrics), budget group analysis (use budget_group_performance).
CHANNELS: FACEBOOK, LINKEDIN, GOOGLE_ADS, INSTAGRAM (comma-separated)
METRICS: accounts, reachedAccounts, engagedAccounts, convertedAccounts | qualifiedAccounts, influencedOppsAccounts, triggeredOppsAccounts, wonAccounts | impressions, clicks, leads, mqls | influencedOpps, influencedAmount, triggeredOpps, triggeredAmount | id, name, lastUpdatedDate
Returns paginated response with totalElements, totalPages, and data array.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Example: page=0 for the first page. | |
| size | No | Number of results per page. Default: 25; raise it (up to 10000) to pull every account list in one call. | |
| sort | No | Sorting criteria. Examples: 'triggeredAmount,desc', 'engagedAccounts,desc', 'influencedAmount,desc'. Format: field,direction where direction is 'asc' or 'desc'. | |
| endDate | No | End date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: 2025-01-31T23:59:59.999Z. Optional for custom date ranges. | |
| channels | No | Comma-separated channel names (e.g., 'LINKEDIN,FACEBOOK,INSTAGRAM,GOOGLE_ADS'). Leave empty for all channels. | |
| startDate | No | Start date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: 2025-01-01T00:00:00.000Z. Optional for custom date ranges. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: it lists the exact metrics returned, states that the response is paginated with totalElements/totalPages/data array, and clarifies channel filtering. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than typical but well-structured with clear labels (USE FOR, NOT FOR, CHANNELS, METRICS, pagination note). It is front-loaded with purpose and uses a scannable format. Every section provides distinct value; while slightly verbose, no sentence is wasteful. Score 4 rather than 5 due to the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given six optional parameters and no output schema, the description compensates by detailing the metrics available, channel options, pagination behavior, and usage boundaries. It fully equips an agent to call the tool correctly without needing additional documentation. The absence of prerequisites or rate limits is acceptable for a read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage for all six parameters, each with detailed examples (e.g., page, size, sort, date formats). The tool description adds no additional parameter-level semantics beyond what the schema already provides. Per the rubric, when schema coverage is high, baseline is 3, and the description does not elevate it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('get'/'list') and resource ('account list performance'), then lists the exact metrics and scope ('account list information with engagement metrics and statistics'). It distinguishes itself from siblings by naming alternatives in the NOT FOR section (e.g., 'use experiment_performance_stats'), so an agent can select it correctly without opening other tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly provides USE FOR and NOT FOR sections, naming specific sibling tools for excluded cases (e.g., 'Campaign-level details (use experiment_performance_stats)'). This gives direct guidance on when to use this tool versus alternatives, with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_and_edit_campaign_elementsAdd & Edit Campaign ElementsADestructiveInspect
Add new elements and edit existing properties of a Precision Optimization (1×1×1 / METADATA) marketing campaign. This tool serves two purposes: 1. ADD new audiences, ads, offers, and keywords to campaigns across LinkedIn, Facebook, Instagram, Google Ads, and Reddit. 2. EDIT existing campaign level properties: name, budget group, schedule dates, and offers per channel.
CRITICAL: PRECISION / METADATA CAMPAIGNS ONLY — NATIVE CAMPAIGNS USE A DIFFERENT TOOL.
This tool edits **Precision Optimization (1×1×1 / METADATA)** campaigns. For a **Channel-First / Native / Platform-First (N×N×N)** campaign, use `add_and_edit_native_campaign_elements` instead (it takes container-shaped input). If you call this tool on a Native campaign it returns an error telling you to use the native tool (and vice-versa), so a wrong guess self-corrects — no silent mis-write. Pick by the campaign's structure, not by user phrasing.
CRITICAL: REMEMBER — CAMPAIGN STRUCTURE IS FIXED AT CREATION AND CANNOT BE CHANGED HERE.
A campaign's structure (Precision 1×1×1 vs Native N×N×N) is chosen at creation and this tool does NOT switch it. Changing structure means building a NEW campaign with create_campaign (Precision) or create_native_structure_campaign (Native).
WARNING: THIS IS THE TOOL TO USE WHEN THE USER WANTS TO:
- EDIT/UPDATE a campaign's name, budget group, start date, or end date
- CHANGE or REPLACE the offers assigned to a channel in a campaign
- ENABLE a channel on an existing campaign
- ADD new audiences, ads, ad groups, or keywords to a campaign
- Expand campaign reach without recreating the entire campaign
CRITICAL OFFER-CHANNEL PAIRING RULE (silent failure if violated)
Lead Gen offers are CHANNEL-LOCKED at creation time (the channel was set on create_update_offer via data.channel). When you populate any channel's "offers" array here, you MUST only pass offer_ids whose data.channel matches that slot — the API DOES NOT validate the pairing and will SILENTLY return a "successful" update on a campaign that cannot serve.
• linkedin.offers → only Lead Gen offer_ids with data.channel='LINKEDIN' (or Landing Page offer_ids).
• facebook.offers → only Lead Gen offer_ids with data.channel='FACEBOOK' (or Landing Page offer_ids).
• instagram.offers → only Lead Gen offer_ids with data.channel='INSTAGRAM' or 'FACEBOOK' (or Landing Page offer_ids).
• google.offers → ONLY Landing Page offer_ids (Google Ads does not support Lead Gen forms).
• reddit.offers → ONLY Landing Page offer_ids (Reddit does not support Lead Gen forms).
Because this tool's "offers" arrays are FULL REPLACEMENTS (not appends), a wrong id here will overwrite the channel's correct offers with broken ones. If you cannot remember an offer_id's channel, call get_offer(name=<offer_name>) BEFORE submitting and inspect the channel field.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
EDIT CAPABILITIES (overwrites/replaces previous values):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- name → Renames the campaign (smart: only executes if new name differs from current)
- budgetGroup → Reassigns campaign to a different budget group (smart: only if different from current)
- startDate → Replaces the campaign start date (can be updated independently)
- endDate → Replaces the campaign end date (can be updated independently)
- offers → WARNING: FULL REPLACEMENT per channel. Sending offers OVERWRITES the entire offer list for that channel.
- Channel state → Enables any channel included in the payload (idempotent if already enabled)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ADD CAPABILITIES (appends alongside existing, non-destructive):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- audiences → Appended to existing audiences (POST)
- exclude_audiences → Appended as channel-level EXCLUDE (negative-targeting) audience groups (POST). This is the consolidated home for exclusion audiences (the standalone add_exclusion_audiences_to_campaign tool was retired).
- target_groups → Appended to existing target groups (POST)
- ads → Appended to existing ads/ad groups (POST)
- keywords (Google only) → Create keyword groups (free-text and/or existing keyword IDs); optionally LINK a group to a native ad container (NATIVE structure), or change an existing group's match type in place (set_match_type)
- negative_keyword_lists (Google only) → Assigned to Google Ads channel after processing
REQUIRED PARAMETERS:
- campaignId: Campaign ID (numeric identifier for the campaign)
- campaignType: "Lead Gen" or "Brand Awareness" (must match existing campaign)
- name: Campaign name
- startDate: Campaign start date in YYYY-MM-DD format
- endDate: Campaign end date in YYYY-MM-DD format
- budgetGroup: Budget group name
CHANNEL ELEMENTS:
WARNING: ADS — SEPARATE (default) vs BUNDLED INTO ONE GROUP (opt-in):
- "ads.list": ad IDs sent one per request. DEFAULT — use this unless the user
explicitly asks to group ads. A list of N ids produces N separate ads, not one bundle.
- "ads.groups" ([{name, ads:[ids]}]): bundles ads into named ad groups. ONLY when grouping is requested.
(LinkedIn has no ad groups — always use list.)
LinkedIn:
- audiences: Array of audience names (APPENDED)
- target_groups: Array of Targeting Group names (APPENDED)
- ads: Object with "groups" (ad group objects) and/or "list" (individual ad IDs) (APPENDED)
- offers: Array of offer IDs (WARNING: REPLACES all existing offers on this channel)
Facebook:
- audiences: Array of audience names (APPENDED)
- target_groups: Array of Targeting Group names (APPENDED)
- ads: Object with "groups" and/or "list" (APPENDED)
- offers: Array of offer IDs (WARNING: REPLACES all existing offers on this channel)
Instagram:
- audiences: Array of audience names (APPENDED)
- target_groups: Array of Targeting Group names (APPENDED)
- ads: Object with "groups" and/or "list" (APPENDED)
- offers: Array of offer IDs (WARNING: REPLACES all existing offers on this channel)
Google Ads:
- keywords: Object with "groups" and/or "set_match_type".
- groups: [{name, keywords?: [str], keyword_ids?: [int], match_type?: PHRASE|BROAD|EXACT, container?/container_id?}]
Creates keyword groups. A group naming a container/container_id is LINKED to that native ad container (NATIVE structure: keywordGroupId set by re-POSTing the channel's container list). A group with no container is appended unlinked.
- set_match_type: [{keyword_group_id? | container?/container_id?, match_type}] — change an existing group's match type in place (PATCH; non-destructive).
- audiences: Array of audience names (APPENDED)
- ads: Object with "groups" and/or "list" (APPENDED)
- offers: Array of offer IDs (WARNING: REPLACES all existing offers on this channel)
- negative_keyword_lists: Array of negative keyword list names (optional)
Example: ["Competitor Brands", "Low Intent Keywords"]
Assigned to the Google Ads channel after processing.
Names must match existing negative keyword lists (use list_negative_keywords_list to find them).
Reddit:
- audiences: Array of audience names (APPENDED)
- target_groups: Array of Targeting Group names (APPENDED; Reddit Target Groups come from create_reddit_target_group)
- ads: Object with "list" only — Reddit ads attach one per request, like LinkedIn (APPENDED)
- offers: Array of offer IDs (WARNING: REPLACES all existing offers on this channel)
- Channel settings (objective, comments, placements, conversion pixel) are NOT edited
here — use update_reddit_channel_settings. When this tool flips a disabled Reddit
channel to enabled, UI-equivalent defaults are applied (Lead Gen → CLICKS + AUTO_BID;
Brand Awareness → IMPRESSIONS + MANUAL_BID).
CHANNEL ACTIVATION LOGIC:
A channel is enabled if ANY of these conditions are met (OR logic):
- audiences array has at least 1 item, OR
- target_groups array has at least 1 item, OR
- ads object exists, OR
- offers array has at least 1 item, OR
- keywords exist (Google Ads only)
WARNING: AUDIENCES vs TARGET GROUPS — CRITICAL DISTINCTION:
- "audiences": standard Metadata audiences (Firmographic, Bombora Intent, Retargeting, LinkedIn/Facebook Native, etc.)
- "target_groups": Targeting Groups (also called Target Groups) created in the platform's Targeting Groups section.
Both are arrays of names (strings). Send each type in its own field — do NOT mix them.
If the user mentions a "Targeting Group" or "Target Group", it goes in "target_groups", NOT in "audiences".
EXAMPLES:
Edit campaign name and dates (no channel elements needed):
add_and_edit_campaign_elements({
"campaignId": 12345,
"campaignType": "Lead Gen",
"name": "NEW_CAMPAIGN_NAME_2025",
"startDate": "2025-09-01",
"endDate": "2025-12-31",
"budgetGroup": "BoFu"
})
Replace offers on LinkedIn:
add_and_edit_campaign_elements({
"campaignId": 12345,
"campaignType": "Lead Gen",
"name": "MD_LG_20252107161406",
"startDate": "2025-08-01",
"endDate": "2025-09-30",
"budgetGroup": "BoFu",
"linkedin": {
"offers": [57538, 57504]
}
})
Add audiences and ads to LinkedIn:
add_and_edit_campaign_elements({
"campaignId": 12345,
"campaignType": "Lead Gen",
"name": "MD_LG_20252107161406",
"startDate": "2025-08-01",
"endDate": "2025-09-30",
"budgetGroup": "BoFu",
"linkedin": {
"audiences": ["Test Native Audience", "EU Countries"],
"ads": {
"groups": [{"name": "1GOAT", "ads": [173669, 171805]}],
"list": [156502, 156485]
},
"offers": [57538, 57504]
}
})
Add Google keywords:
add_and_edit_campaign_elements({
"campaignId": 12345,
"campaignType": "Lead Gen",
"name": "MD_LG_20252107161406",
"startDate": "2025-08-01",
"endDate": "2025-09-30",
"budgetGroup": "BoFu",
"google": {
"keywords": {
"groups": [{"name": "CRM Keywords", "keywords": ["crm software", "lead gen tools"]}]
},
"audiences": ["SUP_SF_All-Customers-Contacts_ALL_3"],
"ads": {"list": [175258]},
"offers": [61054]
}
})
Mixed: edit budget group + add across multiple channels:
add_and_edit_campaign_elements({
"campaignId": 12345,
"campaignType": "Lead Gen",
"name": "MD_LG_20252107161406",
"startDate": "2025-08-01",
"endDate": "2025-09-30",
"budgetGroup": "ToFu",
"linkedin": {"audiences": ["New Audience"], "offers": [57538]},
"facebook": {"audiences": ["FB Audience"], "ads": {"list": [171806]}},
"google": {"keywords": {"groups": [{"name": "Keywords", "keywords": ["keyword"]}]}, "offers": [61054]}
})
VALIDATION:
- campaignId must match existing campaign
- All asset IDs (ads, offers) must exist
- Audience names must match existing audiences
- Budget group and name use smart filters: only updated if different from current values
- Dates support partial updates: you can change only startDate, only endDate, or both
RESPONSE: Returns
- success, campaign_id, campaign_name, campaign_type, status, status_label
- channels_updated: list of channel keys that had any edits
- elements_added: true if anything changed at the campaign or channel level
- added_summary: per-channel counts of what was ACTUALLY attached (audiences,
target_groups, ad_groups, individual_ads, offers, keyword_groups,
negative_keyword_lists) — not just what was requested
- changes: { renamed, budget_group_reassigned, schedule_updated }
reporting which campaign-level edits actually fired
- optimization_group: { id, tag_name } after the edit
- start_date, end_date, campaign_url, full_response (complete wizard state)
- errors[]: populated on partial failures; success=false if present
BID STRATEGY FOR NEWLY-ENABLED CHANNELS:
When a channel transitions from disabled → enabled as part of this edit, the
tool automatically applies the same auto-bid default used on create_campaign
(AUTO_BID on LI/FB/IG, TARGET_SPEND on Google, objective-driven on Reddit:
Lead Gen → CLICKS + AUTO_BID, Brand Awareness → IMPRESSIONS + MANUAL_BID)
so the channel is launch-ready.
Already-enabled channels keep their existing bid strategy untouched.
SMART-UPDATE BEHAVIOUR:
- name and budgetGroup are only pushed to the platform when different from
current values (prevents the UniqueWizardName validator from rejecting a
no-op rename, and avoids pointless tag churn).
- startDate / endDate are partial: supply either or both.
ERROR HANDLING: Validates campaign exists, verifies all asset IDs and audience
names. Failures on individual operations are collected into errors[] and the
rest of the edit proceeds — the campaign is not rolled back on partial errors.| Name | Required | Description | Default |
|---|---|---|---|
| campaign_data | Yes | Campaign data with fields to edit and/or elements to add |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (readOnlyHint=false, destructiveHint=true) are reinforced and far exceeded. The description discloses the silent-failure offer-channel pairing rule, full-replacement (overwrite) semantics for offers vs append semantics for audiences, channel-activation OR logic, smart-update no-op filters, bid-strategy defaults for newly-enabled channels, and the no-rollback partial-error behavior. Nothing contradicts the annotations — destructiveHint=true aligns with the repeated overwrite warnings.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The critical Precision-vs-Native distinction is correctly front-loaded and the section headers (EDIT/ADD/CHANNEL ELEMENTS/EXAMPLES) impose structure. However, the description is extremely verbose with clear redundancy: the channel-lock/offer-replacement warning is repeated in prose, in each channel block, and again in schema; the bid-strategy default is stated twice; and five near-identical examples inflate length. Much is warranted by the tool's complexity, but it would benefit from trimming.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the extreme complexity (nested per-channel objects, add-vs-edit semantics, silent-failure modes, 5 channels with differing rules) and the absence of an output schema, the description is complete. It covers response fields (channels_updated, added_summary, changes), validation rules, error handling, smart-update behavior, and bid strategy — nothing an agent needs to invoke this safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema itself is rich, so baseline is 3. The description adds substantial value beyond the schema: the channel-lock offer pairing rules per channel, the audiences-vs-target_groups distinction, the ads list-vs-groups default/opt-in semantics, and the negative_keyword_lists assignment behavior. This meaningfully surpasses what the schema alone conveys, though some of it (e.g., offers warnings) duplicates schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope: 'Add new elements and edit existing properties of a Precision Optimization (1x1x1 / METADATA) marketing campaign.' It explicitly enumerates the two purposes (ADD audiences/ads/offers/keywords; EDIT name/budget group/schedule/offers) and names the sibling it is not (add_and_edit_native_campaign_elements). An agent can distinguish it from all 200+ siblings immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Exceptionally explicit. 'PRECISION / METADATA CAMPAIGNS ONLY — NATIVE CAMPAIGNS USE A DIFFERENT TOOL' names the alternative and the condition that selects it, notes the self-correcting wrong-guess behavior, and instructs picking by campaign structure not phrasing. A 'WARNING: THIS IS THE TOOL TO USE WHEN' list enumerates concrete use cases, and structure changes are explicitly routed away to create_campaign/create_native_structure_campaign. Reddit settings are routed to update_reddit_channel_settings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_and_edit_native_campaign_elementsAdd & Edit Campaign Elements — Native / Channel-First (N×N×N)ADestructiveInspect
Add elements to, and edit campaign-level fields of, an existing Channel-First / Native (N×N×N) campaign — the one built with create_native_structure_campaign (channel.structureType=NATIVE, WizNativeAdContainer). This is the NATIVE counterpart of add_and_edit_campaign_elements: that tool edits Precision (1×1×1 / METADATA) campaigns; THIS tool edits Native (N×N×N) campaigns.
CRITICAL: PICK THE TOOL BY THE CAMPAIGN'S STRUCTURE (not by user phrasing):
• Native / Channel-First / Platform-First / N×N×N campaign → THIS tool (`add_and_edit_native_campaign_elements`).
• Precision Optimization / 1×1×1 / METADATA campaign → `add_and_edit_campaign_elements`.
Both tools guard: call THIS tool on a Precision/METADATA campaign and it returns an error telling you to use `add_and_edit_campaign_elements`, and vice-versa. So if you guess wrong, the error tells you the right one — no silent mis-write. If you don't know the structure, check the campaign first (its channels' structureType) or just try and follow the redirect.
WHAT THIS TOOL DOES:
- EDIT campaign-level fields: name, budgetGroup, startDate, endDate (same smart/partial semantics as the flat tool — only pushed when different / supplied).
- ADD new containers: each channel's `containers[]` APPENDS new WizNativeAdContainers (one audience × an `ad_offers` list of {ad, offer} pairs each, same shape as `create_native_structure_campaign`). Existing containers are PRESERVED — the channel's current container list is re-POSTed with the new ones appended.
- ADD bare target groups: each channel's optional `target_groups[]` (names) attaches targeting groups to the native channel without a full container (places targetingGroupId on a reused/appended ad-less container).
- ATTACH negative keyword lists (Google Ads / Microsoft Ads only): the search channel block's optional `negative_keyword_lists[]` (names of EXISTING lists) attaches them channel-wide — valid with or without new containers. Names inside `containers[].negative_keyword_lists` are unioned in and applied at the same channel level. A name that doesn't resolve on the channel is reported in `errors[]`, never silently skipped.
- EDIT existing containers (PER CONTAINER): each channel's optional `modify_containers[]` targets an existing container by `name` and, within it, deletes specific Ad—Offer rows (`remove_ads`), clears an offer from one ad while keeping it on the OTHER ads (`clear_offers_on_ads`), removes this container's audience / targeting group / keywords / exclusion (`remove_audience` / `remove_target_group` / `remove_keywords` / `remove_exclude_audience`), or deletes the whole container (`delete_container`). This is the surgical counterpart to the channel-wide remove_* tools — use it when an audience/offer/ad is shared across containers and you only want to touch one. Removing a group clears it on that one container; a group reused by other containers stays alive for them.
WHAT THIS TOOL DOES NOT DO:
- It does not switch a campaign's structure (that's fixed at creation).
- For a change that spans ALL ads (remove an offer/ad everywhere it appears on the channel), use the channel-wide removal tools (remove_offers_from_campaign / remove_ad_from_campaign / remove_audiences_from_campaign / remove_target_groups_from_campaign / remove_keywords_from_campaign); `modify_containers` is only for a specific container/row.
CONTAINER RULES (same as create_native_structure_campaign):
- Each container is one audience × a LIST of (ad, offer) pairs (`ad_offers`, 1+). Group several ads/offers under one audience by adding pairs — e.g. 3 ads on the same offer = 3 pairs that repeat the same `offer` id. Send two containers only to run the audience as two separate ad-sets.
- `audience` / `exclude_audience` / `target_group` are NAMES (resolved server-side); the `ad` / `offer` inside each `ad_offers` pair are integer IDs.
- Audience names are resolved BEFORE anything is created: a container whose `audience` cannot be resolved is dropped with an error in `errors[]` that states whether retrying can help ("may still be matching") or not ("not available on this channel"); no keyword group or other element is left behind for a dropped container.
- `audience` is REQUIRED for LinkedIn/Facebook/Instagram/Reddit; OPTIONAL for Google/Microsoft search containers (keyword-only is valid — provide `keywords`/`keyword_ids` instead).
- Offer–channel lock still applies: a Lead Gen offer must be locked to the container's channel (LinkedIn→LINKEDIN, etc.); Google takes Landing Page offers only; Landing Page offers are universal.
RESPONSE: same top-level shape as `add_and_edit_campaign_elements` (success, campaign_id, changes {renamed, budget_group_reassigned, schedule_updated}, added_summary per channel {containers, target_groups, negative_keyword_lists, and — when modify_containers is used — ads_removed, offers_cleared, containers_deleted, audiences_removed, target_groups_removed, keywords_removed, excludes_removed}, optimization_group, campaign_url, full_response). On partial failures, success=false plus `errors[]`; the rest of the edit still proceeds.
EXAMPLE (append a LinkedIn container + rename):
add_and_edit_native_campaign_elements(campaign_data={
"campaignId": 159490,
"name": "Q3_ABM_Native_v2",
"linkedin": {"containers": [
{"name": "VPs > Demo > Form", "audience": "VPs - NA", "ad_offers": [{"ad": 156502, "offer": 57538}]}
]}
})
EXAMPLE (append a Google keyword-only container + bare target group):
add_and_edit_native_campaign_elements(campaign_data={
"campaignId": 159490,
"google": {
"containers": [
{"name": "Incident Response", "ad_offers": [{"ad": 210804, "offer": 67269}],
"keywords": ["incident response platform"], "negative_keyword_lists": ["Competitor Brands"]}
],
"target_groups": ["Tech Decision Makers"]
}
})
EXAMPLE (ROW-LEVEL: drop the offer from ONE ad in a container, keep it on the other ads):
add_and_edit_native_campaign_elements(campaign_data={
"campaignId": 159490,
"facebook": {"modify_containers": [
{"container": "ICP > 3 creatives > TOF offer",
"clear_offers_on_ads": ["Ungated-AI-in-Finance-v2-vert_FB"]}
]}
})
EXAMPLE (PER-CONTAINER: delete one Ad—Offer row in one container; delete a whole other container):
add_and_edit_native_campaign_elements(campaign_data={
"campaignId": 159490,
"linkedin": {"modify_containers": [
{"container": "VPs > Demo > Form", "remove_ads": ["Old Creative A"]},
{"container": "Retired ad-set", "delete_container": True}
]}
})
EXAMPLE (PER-CONTAINER: drop a reused audience from ONE container, keep it on the others):
add_and_edit_native_campaign_elements(campaign_data={
"campaignId": 159490,
"facebook": {"modify_containers": [
{"container": "ICP - A2", "remove_audience": True}
]}
})| Name | Required | Description | Default |
|---|---|---|---|
| campaign_data | Yes | Native (N×N×N) campaign edit payload: campaignId + optional campaign-level fields + per-channel `containers[]` (append) and optional `target_groups[]`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say destructiveHint=true and openWorldHint=true; the description carries the full behavioral burden and exceeds it. It discloses the wrong-tool guard (error redirect, no silent mis-write), the append-and-preserve semantics (existing containers re-POSTed), audience-resolution-before-creation ordering, per-container vs channel-wide scope, and partial-failure behavior (success=false with errors[] but rest proceeds). All genuinely useful, beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long, but every section earns its place given the complexity: purpose, routing, what-it-does/doesn't-do, container rules, response shape, and five worked examples. Front-loaded with purpose and critical routing. Slight verbosity in repeating modify_containers semantics, but justified for a multi-channel surgical tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Exceptionally complete: covers the operation scope, explicit exclusions (no structure switch), container rules (audience required per channel, keyword-only valid for search), offer-channel lock, response shape (no output schema, so description must cover it), and error semantics. For a tool with nested multi-channel structures, nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with detailed per-field descriptions, so baseline is 3. The description adds value by explaining smart/partial semantics (name only pushed when different, budgetGroup only reassigned when different), the container N×N×N shape, and the ad_offers repetition pattern. It complements the schema without repeating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Add & Edit) and resource (existing Channel-First / Native N×N×N campaign), and explicitly names its sibling counterpart `add_and_edit_campaign_elements` (Precision/1×1×1/METADATA). The distinction is made crisp by structure type, so an agent can route correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated CRITICAL section gives explicit routing rules: pick THIS tool for Native/Channel-First/N×N×N, pick `add_and_edit_campaign_elements` for Precision/METADATA. It also names the channel-wide removal siblings (remove_offers_from_campaign, etc.) and tells when to prefer them over `modify_containers`. No ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_extensions_to_native_campaignAdd Extensions to Native-Structure CampaignAInspect
Attach existing library extensions (sitelinks, callouts, etc.) to a native-structure Google Ads / Microsoft Ads campaign, so they actually serve when the campaign launches.
ALSO KNOWN AS: add extension to campaign, attach sitelink, put sitelink on campaign, link extension to campaign, enable extension for campaign
KEYWORDS: add, attach, link, bind, extension, sitelink, callout, campaign, native, native structure, channel first, google ads, microsoft ads, bing
WHY THIS EXISTS: creating an extension only puts it in the account library — it is NOT attached to any campaign and will not serve. This tool performs the binding.
WHEN TO USE:
- "Add our 'Book a Demo' sitelink to campaign X"
- "Attach these callouts to the native search campaign"
- After create_google_sitelink_extension, when the user wants it live on a specific campaign
WHEN NOT TO USE:
- The campaign uses the Precision / METADATA structure — this tool covers native-structure campaigns only and will tell you so. Precision binds extensions per-creative and has no tool yet; direct the user to the platform UI.
- You do not have the extension's internal id → call list_extensions first
- Removing an attachment → use remove_extensions_from_native_campaign
INPUTS (all required):
- campaign_id: wizard campaign id
- channel: GOOGLE_ADS or MICROSOFT_ADS
- extension_ids: internal ids from list_extensions (the `id` field, NOT `externalId`)
BEHAVIOUR: additive — existing attachments are preserved. Safe to re-run; already-attached ids are reported and left alone.
ORDERING CAVEAT: add_and_edit_native_campaign_elements rebuilds the channel's native containers and CLEARS extension attachments. Attach extensions AFTER any native element edits, or re-attach afterwards.
EXAMPLE:
add_extensions_to_native_campaign(campaign_id=8421, channel="GOOGLE_ADS", extension_ids=[551, 552])| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | Search channel. Ad extensions are a search-channel-only concept. | |
| campaign_id | Yes | The wizard campaign id. | |
| extension_ids | Yes | Internal library extension ids from list_extensions. These are the `id` field, NOT `externalId` (the ad platform's own id). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint: false, destructiveHint: false), the description adds meaningful behavioral context: the operation is additive, existing attachments are preserved, re-running is safe, already-attached ids are reported and left alone, and the tool only handles native-structure campaigns. It also discloses the destructive clearing behavior of add_and_edit_native_campaign_elements relative to extensions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: aliases, keywords, the core conceptual reason the tool exists, usage conditions, exclusions, required inputs, behavior, an ordering caveat, and an example. It is structured with clear headers and front-loads the most important clarification that attaching is different from creating.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with three required parameters and meaningful ecosystem interactions, the description is complete. It explains the prerequisite (list_extensions), the native-vs-Precision distinction, the relationship to sibling tools like remove_extensions_from_native_campaign and add_and_edit_native_campaign_elements, and the additive re-run behavior. No critical calling context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description reiterates that extension_ids must be internal ids from list_extensions and not externalId, but the schema already states this explicitly. The example call adds a small amount of practical clarity but does not substantially extend the schema's parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Attach existing library extensions (sitelinks, callouts, etc.) to a native-structure Google Ads / Microsoft Ads campaign.' It clearly distinguishes this binding action from merely creating an extension, and the 'WHEN NOT TO USE' section further separates it from Precision-structure workflows and from remove_extensions_from_native_campaign.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is an explicit 'WHEN TO USE' section with concrete user phrasings, plus a 'WHEN NOT TO USE' section naming alternatives: call list_extensions first if the id is unknown, use remove_extensions_from_native_campaign for removal, and direct Precision-structure users to the platform UI. The ordering caveat about add_and_edit_native_campaign_elements is also clear operational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_keywords_to_negative_listsAdd Keywords to Negative ListsAInspect
Add keywords to one or more existing Google Ads negative keyword lists.
PURPOSE:
Append keywords (typically search terms surfaced by list_search_terms) to one or
more existing negative keyword lists, so future ads are blocked from matching them.
Use this for the day-to-day "review search terms, exclude the wasteful ones" loop.
WHEN TO USE:
- Block search terms that consumed budget without producing clicks or conversions
- Extend an existing "Keywords we don't wanna spend money on" list with new offenders
- Apply the same keywords to multiple negative lists in a single call
THIS IS NOT FOR CREATING A NEW LIST:
To create a brand-new negative keyword list, use create_negative_keywords_list.
This tool only appends to lists that already exist.
LOOKING UP LIST IDS:
Call list_negative_keywords_list first to find the id(s) of the list(s) you want
to extend. The 'id' field returned there is what you pass here as negativeListIds.
MATCH TYPE:
Two ways to set the match type, pick whichever fits:
(a) Single match type for the whole batch: pass keywords as plain strings
and set the top-level match_type. Defaults to PHRASE (the same default
the UI uses when adding from the search-terms page).
(b) Mixed match types in a single call (preferred when recommending negatives
after reviewing search terms, since it keeps the whole batch in one call):
pass keywords as objects {text, match_type}. The per-item match_type wins
over the top-level default. Items without a match_type fall back to the
top-level default.
Only PHRASE, BROAD, and EXACT are valid for negative keywords.
COMMON USE CASES:
1. Add a single wasteful search term to one list (all-PHRASE):
add_keywords_to_negative_lists(
negativeListIds=[43256533],
keywords=["free download"],
)
2. Add several terms to multiple lists, all exact-match:
add_keywords_to_negative_lists(
negativeListIds=[43256533, 43258891],
keywords=["competitor a", "competitor b"],
match_type="EXACT",
)
3. Mixed match types in ONE call (recommended after a search-terms review):
add_keywords_to_negative_lists(
negativeListIds=[43256533],
keywords=[
{"text": "free download", "match_type": "PHRASE"},
{"text": "competitor a", "match_type": "EXACT"},
{"text": "how to", "match_type": "BROAD"},
],
)
4. Mostly PHRASE with one EXACT override (mix strings + objects):
add_keywords_to_negative_lists(
negativeListIds=[43256533],
keywords=[
"free download",
"tutorial",
{"text": "competitor a", "match_type": "EXACT"},
],
match_type="PHRASE",
)
PARAMETERS:
- negativeListIds (array of integers, required): IDs of the existing negative
keyword lists to extend, as returned by list_negative_keywords_list.
- keywords (array, required): each item is either a plain string (keyword text,
uses the top-level match_type) or an object {text, match_type} where
match_type overrides the top-level default. Min 1.
- match_type (string, optional): EXACT, PHRASE, or BROAD. Default PHRASE.
Used as the default for plain-string items and for object items that omit
match_type.
RESPONSE FORMAT:
Returns the platform response describing the updated list(s).
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
lists, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
| keywords | Yes | Keywords to add to every list in negativeListIds. Each item is either a plain string or {text, match_type}. | |
| match_type | No | Default match type, used when an item is a plain string or an object that omits match_type. Default PHRASE. | PHRASE |
| negativeListIds | Yes | IDs of the existing negative keyword lists to extend (from list_negative_keywords_list). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only mark readOnlyHint=false, openWorldHint=false, destructiveHint=false, so the description carries the behavioral burden. It clearly states this appends to existing lists, blocks future ads, that channels hold separate lists, and how match_type override rules work. Minor gaps like deduplication and error behavior remain, but the core behavioral traits are well disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections: PURPOSE, WHEN TO USE, NOT FOR, LOOKING UP, MATCH TYPE, USE CASES, PARAMETERS, RESPONSE, and CHANNEL SCOPE. It is front-loaded with a one-line summary. Some example repetition could be trimmed, but given the tool's mixed match-type complexity, the length is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given four parameters, no output schema, and intricate match-type behavior, the description is essentially complete. It covers list ID sourcing, match type override semantics, both channels, default values, and four illustrative use cases. The response format statement is vague, but with no output schema, that is not a critical gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, giving a baseline of 3, but the description substantially adds meaning beyond schema descriptions. It explains that negativeListIds come from list_negative_keywords_list, demonstrates the keywords array's polymorphic nature with real examples, specifies match_type precedence rules, and clarifies the channel default and separation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb 'Add' and resource 'negative keyword lists' in the first line, immediately making the action and target clear. It explicitly distinguishes itself from create_negative_keywords_list ('This tool only appends to lists that already exist'), preventing confusion with the sibling creation tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a dedicated WHEN TO USE section with concrete conditions such as blocking budget-wasting terms and extending existing lists. It explicitly says NOT for creating a new list and points to create_negative_keywords_list as the alternative, and instructs the agent to call list_negative_keywords_list first for ID lookup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_negative_keyword_lists_to_live_campaignsAdd Negative Keyword Lists to Live CampaignsAInspect
Attach existing Google Ads negative keyword lists to campaigns that are ALREADY LAUNCHED — a live edit that syncs through to Google.
CRITICAL: LIVE EDIT vs DRAFT EDIT — THE DISTINCTION THAT PICKS THIS TOOL:
A campaign is a DRAFT until it is launched; every status after that
(Launched, Launching, Editing, Finished, Error, Failed) is LIVE. Editing a
live campaign is a different code path on the platform, not just a different
status — the change has to be published to the running Google campaign, not
only written to the wizard.
• LIVE campaign (already launched) → THIS tool. It calls the platform's
bulk live-edit endpoint, which publishes an update per running ad group
so Google actually starts excluding the keywords.
• DRAFT campaign (never launched) → the campaign-builder tools
(`create_campaign` / `create_native_structure_campaign` /
`add_and_edit_campaign_elements` / `add_and_edit_native_campaign_elements`,
via their `negative_keyword_lists` field). Those write wizard state that
gets pushed at launch.
Pass a draft campaign here and it is SKIPPED with a reason rather than
written — the draft path has different, destructive semantics, so this tool
refuses to take it. If you are unsure which a campaign is, just call this
tool: the per-campaign report tells you the status and which path applies.
WORKS ON BOTH CAMPAIGN STRUCTURES. Negative keyword lists attach at the
CHANNEL level, not to an ad group / container, so Precision Optimization
(1×1×1) and Channel-First / Native (N×N×N) campaigns are handled identically.
You do NOT need to know the structure, and you must NOT reach for
`add_and_edit_native_campaign_elements` to do this on a live campaign — that
tool rebuilds containers, which the platform forbids once experiments are
launched.
BULK BY DESIGN: pass every campaign the user named in ONE call. The platform
endpoint takes a campaign list, and this tool groups them so campaigns
needing the same final set share a single request.
ADDS, DOES NOT REPLACE (default): the platform applies exactly the set of
lists it is handed, so `mode="add"` first reads what each campaign already
has and submits the union — attaching one list never silently detaches the
others. Use `mode="replace"` ONLY when the user explicitly wants the
campaign's negative lists to become exactly the ones named; the response's
`detached` field reports what that removed.
FINDING LISTS: pass `listNames` (what the user says) and/or `listIds` (from
`list_negative_keywords_list`). Names must match an existing list EXACTLY
(case-insensitive) — a name that matches nothing is reported in `warnings`
and skipped, never swapped for a similar list. To attach a list that does not
exist yet, create it first with `create_negative_keywords_list`.
COMMON USE CASES:
1. Add one list to a running campaign:
add_negative_keyword_lists_to_live_campaigns(campaignIds=[159490], listNames=["Competitor Brands"])
2. Same lists across several live campaigns, one call:
add_negative_keyword_lists_to_live_campaigns(campaignIds=[159490, 159502], listNames=["Job Seekers", "Free Content"])
3. Make a campaign's negatives exactly one list (removes any others):
add_negative_keyword_lists_to_live_campaigns(campaignIds=[159490], listIds=[43256533], mode="replace")
RESPONSE FORMAT:
Per campaign: status, `edit_path` ("live" / "draft"), `attached_before`,
`newly_attached`, `already_attached`, `detached`, `attached_after`, and an
`action` of submitted / no_change / skipped / failed. Top level carries
`submitted_campaign_ids`, `warnings`, `errors`, and `delivery_note`.
WARNING: ASYNC — REPORT IT HONESTLY: the platform accepts this in the background
and answers with no body. `action: "submitted"` means ACCEPTED, not applied.
It also drops campaigns server-side WITHOUT an error when they are locked by
another pending change or when a launched campaign is not currently
active/paused (e.g. completed). Tell the user the change was submitted and
that it lands on Google shortly — do not claim it is live, and if they need
certainty, re-check the campaign a little later.
CHANNEL SCOPE:
GOOGLE_ADS only — the platform endpoint is hardcoded to the Google Ads
channel. It does NOT work for Microsoft Ads (Bing) even though Microsoft has
the same negative-list concept; if the user asks for Microsoft, say this is
not supported yet rather than calling with channel=GOOGLE_ADS.| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | 'add' (default) merges with the lists already on the campaign. 'replace' makes the campaign's negative lists exactly the ones requested, detaching the rest — only for an explicit user request. | add |
| channel | No | Ad channel scope. Only GOOGLE_ADS is supported — the platform's live-edit endpoint is Google-only. | GOOGLE_ADS |
| listIds | No | IDs of existing negative keyword lists to attach, as returned by list_negative_keywords_list. Can be combined with listNames. | |
| listNames | No | Names of existing negative keyword lists to attach. Matched exactly (case-insensitive) against the account library; an unmatched name is reported, never substituted. | |
| campaignIds | Yes | Wizard campaign ids of the LIVE (already launched) campaigns to update. Pass every campaign the user named in one call. Draft campaigns are skipped with a reason. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only saying readOnlyHint=false and destructiveHint=false, the description carries the behavioral burden and does so thoroughly: it discloses that mode='add' merges rather than replaces, mode='replace' detaches lists, the operation is async ('submitted' means accepted, not applied), campaigns can be dropped server-side without error, and draft campaigns are skipped rather than written. This far exceeds what the annotations alone convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the length is earned: it uses clear headers, bullets, and examples for a genuinely complex tool with live-vs-draft, add-vs-replace, and async behaviors. It is well front-loaded with the critical distinction, though some points are restated across sections, keeping it from a perfect conciseness score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must explain the response shape, which it does per-campaign and top-level, including warnings/errors and delivery_note. It also covers failure modes, channel scope, exact matching rules, and even common-use-case call signatures, making the tool fully callable without external docs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds substantial meaning: listNames are matched exactly and case-insensitively, unmatched names are warned and skipped never substituted, listIds come from list_negative_keywords_list, and campaignIds should include every campaign the user named in one call. The worked examples further clarify how to combine parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb+resource: 'Attach existing Google Ads negative keyword lists to campaigns that are ALREADY LAUNCHED' via a bulk live-edit endpoint. It also explicitly differentiates itself from draft-path tools like create_campaign and add_and_edit_native_campaign_elements, so an agent can distinguish it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says use this tool for LIVE campaigns and names the exact draft-path alternatives for DRAFT campaigns, even listing which sibling tools to use instead. It also states when not to use it (Microsoft Ads) and tells the agent to call this tool if unsure, making the selection criteria unmistakable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
archive_adArchive AdADestructiveInspect
Archive (soft-delete) one or more ads on the Metadata platform.
ARCHIVE IS HOW YOU DELETE AN AD. The platform has NO hard-delete
endpoint for ads — archive is the soft-delete and the only way to
remove an ad from the active library. When the user says
"delete this ad", "remove this ad", "discard this ad", "trash this
ad", or "get rid of this ad" → call archive_ad. Do NOT hallucinate
a delete_ad or remove_ad tool; it does not exist.
The archived ad is preserved on the platform (it still has its id,
creative_json, and history) and can be restored with unarchive_ad.
USE THIS TOOL WHEN:
- User asks to delete, remove, discard, trash, drop, retire, or
archive one or more ads.
- User wants to clean up draft ads they no longer need.
- User asks "make this ad go away" or similar.
HOW TO GET THE id(s):
- search_ads_by_names(ad_names=[...]) → returns active ad ids.
- get_ad_details(ids=...) → confirms an ad exists if the id is
already known (works for active ads).
ALSO KNOWN AS: archive ad, delete ad, remove ad, discard ad,
trash ad, drop ad, retire ad, soft-delete ad, get rid of ad.
KEYWORDS: archive, delete, remove, discard, trash, drop, retire,
soft-delete, hide, get rid of, clean up, ad cleanup.
PARAMETERS:
- ids: Array of integer ad ids (at least one). Bulk-friendly —
pass several ids to archive multiple ads in a single call.
RETURNS:
{ "success": true, "archived_ids": [123, 456], "count": 2 }
To bring an archived ad back, call unarchive_ad with the same id(s).
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Ad id(s) to archive. At least one integer required; pass multiple to archive in bulk. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations provide destructiveHint: true and readOnlyHint: false, but the description goes beyond by explaining the soft-delete nature: 'The archived ad is preserved on the platform (it still has its id, creative_json, and history) and can be restored with unarchive_ad.' This clarifies the destructive semantics and adds context on reversibility and data preservation, which is essential for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-structured with sections for purpose, usage, id retrieval, parameters, and returns. Every section adds value, especially the explicit routing away from delete_ad and the 'ALSO KNOWN AS' and 'KEYWORDS' lists. It is not overly verbose given the tool's central role as the only delete mechanism, though a slightly tighter version could be more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers everything an agent needs: what it does, when to use it, how to obtain ids, the return format, and restoration via unarchive_ad. It also includes explicit exclusion of a non-existent delete_ad tool. The output format is shown, and given the tool's simplicity (one parameter) and presence of siblings, it is fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100% with a single parameter 'ids', the description adds meaningful detail: 'Bulk-friendly — pass several ids to archive multiple ads in a single call' and 'Array of integer ad ids (at least one).' It explains the minimum requirement and encourages bulk usage, which is not explicit in the schema beyond minItems=1.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Archive (soft-delete) one or more ads on the Metadata platform.' It differentiates from a non-existent delete_ad, emphasizing it is the only way to remove an ad, and references the restoration sibling unarchive_ad. The verb 'archive' plus the resource 'ads' and the soft-delete clarification make it unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly lists when to use the tool with bullet points: user asks to delete/remove/discard/trash/drop/retire/archive, wants to clean up drafts, or says 'make this ad go away.' It also warns not to hallucinate a delete_ad tool and provides steps to get ids via search_ads_by_names or get_ad_details, and mentions the alternative unarchive_ad for restoration.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
archive_audienceArchive AudienceADestructiveInspect
Archive (delete) a custom audience from the Metadata platform. Use this tool when the user wants to archiveo or delete a custom audience from the entire System.
You can identify the audience either by its numeric custom_audience_id or by its name.
If only the audience name is provided, the tool will search existing audiences to resolve the correct ID before archiving.
PARAMETERS:
• custom_audience_id (optional): The numeric ID of the custom audience to archive.
• audience_name (optional): The name of the custom audience to archive. Used to look up the ID if custom_audience_id is not provided.
At least one of custom_audience_id or audience_name must be provided.
RESPONSE:
• actionStatus: "SUCCEEDED" if the audience was archived successfully.
| Name | Required | Description | Default |
|---|---|---|---|
| audience_name | No | The name of the custom audience to archive. If provided without custom_audience_id, the tool will search for the audience by name to resolve the ID. | |
| custom_audience_id | No | The numeric ID of the custom audience to archive. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already set destructiveHint=true and readOnlyHint=false, and the description consistently reflects this by saying 'Archive (delete).' It adds useful behavioral context beyond the annotations: the tool will resolve audience_name by searching existing audiences before archiving, and it documents the actionStatus response field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into clear PARAMETERS and RESPONSE sections and is mostly front-loaded, but it repeats schema content nearly verbatim and contains a typo ('archiveo'). The extra whitespace and redundant listing of parameters reduce economy without adding much new information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter destructive tool with full schema coverage, the description covers the essential information: how to identify the audience, the at-least-one-parameter requirement, and the response format. It does not detail failure behavior or irreversibility, but the destructive annotation and 'delete' wording make the core behavior clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully describes both parameters, so the baseline is 3. The description adds extra value by clarifying the 'at least one of custom_audience_id or audience_name must be provided' constraint and reinforcing the ID-resolution behavior for audience_name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Archive (delete)') and resource ('custom audience from the Metadata platform'), making the tool's purpose unambiguous. It clearly distinguishes itself from related sibling tools like unarchive_audience and archive_ad by targeting custom audiences specifically.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'when the user wants to archive or delete a custom audience.' It also explains the two identification modes (by ID or by name), but does not enumerate alternatives or explicitly state situations where this tool should not be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
budget_group_performanceGet Budget Group PerformanceARead-onlyInspect
Performance statistics for a specific budget group by name. IMPORTANT: Accepts budget group NAME directly - no need to look up ID first. Do NOT call get_budget_group before this tool.
USE FOR: Budget group CPL/ROI/Pipeline/MQL analysis, spending and conversion metrics, experiment performance within budget group, efficiency analysis. NOT FOR: Comparing ALL budget groups (use list_budget_groups), individual experiments without budget group context (use experiment_performance_stats), account-level aggregates (use account_level_stats), budget group config WITHOUT performance (use get_budget_group).
HOW IT WORKS: Takes name → looks up ID → fetches experiments tagged with budget group → returns detailed performance.
METRICS RETURNED: spent, impressions, clicks | leads, mqls, conversions | ctr, cpl, cpc, cpm, conversionRate, mqlRate | oppsAmount, triggeredAmount, totalOpps, totalTriggered | name, status, channel, dates
DATE HANDLING: No dates = all-time data. Supports ISO 8601 date ranges.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Use for paginating through large result sets. | |
| size | No | Number of experiments per page. Default is 10. Use larger values (up to 10000) for comprehensive analysis — pull the whole set rather than a sample. | |
| sort | No | Sort criteria for experiments. Format: field,field,direction. Examples: 'experimentId,name,asc', 'spent,desc', 'cpl,asc' | experimentId,name,asc |
| endDate | No | End date for analysis in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.SSSZ, e.g., '2025-12-15T23:59:59.999Z'). Optional - if not provided, no end date filter is applied. | |
| startDate | No | Start date for analysis in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.SSSZ, e.g., '2025-01-01T00:00:00.000Z'). Optional - if not provided, no start date filter is applied. | |
| budget_group_name | Yes | Name of the budget group to analyze (required). The tool will automatically look up the budget group ID. Example: 'Brand Awareness', 'ToFu', 'Lead Gen Q4' | |
| excludeExperimentName | No | Experiment name to exclude from results. Useful for filtering out specific experiments from the analysis. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds meaningful behavior beyond that: the internal flow 'Takes name → looks up ID → fetches experiments tagged with budget group', the date semantics ('No dates = all-time data'), and the full list of returned metrics. It does not discuss error cases like unknown group names, but the added context is substantial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but highly structured with clear sections: purpose, IMPORTANT, USE FOR, NOT FOR, HOW IT WORKS, METRICS RETURNED, and DATE HANDLING. It front-loads the core purpose and routing guidance. There is minor redundancy in repeating the 'name directly / no ID lookup' point, but overall each section earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 7 parameters and no output schema, the description compensates well by listing the exact metrics returned, explaining the internal lookup flow, and covering date behavior. It does not define every metric name or explain pagination, but the schema handles those details. The definition is sufficiently complete for confident invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds some helpful emphasis around budget_group_name (accepts name directly, no ID lookup required) and date handling, but most of that is already present in the schema property descriptions, which also cover pagination, sorting, and exclusion semantics. The description reinforces rather than meaningfully extends the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise specification: 'Performance statistics for a specific budget group by name.' It then enumerates the exact metric categories returned and explicitly distinguishes itself from get_budget_group, list_budget_groups, experiment_performance_stats, and account_level_stats, so an agent can tell it apart from its nearest siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit USE FOR and NOT FOR sections, names the exact alternatives for excluded cases, and adds a direct workflow instruction: 'Do NOT call get_budget_group before this tool.' This leaves no ambiguity about when to select this tool versus its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_campaign_launch_readinessCheck Campaign Launch ReadinessARead-onlyInspect
Check whether a draft campaign is ready to launch, per channel. Reads the campaign's real configuration from the platform and reports, for each ENABLED channel, whether it has the ads, audience, offer, budget AND a live channel connection it needs to go live - plus a specific list of blockers for anything missing.
KEYWORDS: campaign, launch, readiness, ready, preflight, can launch, blockers, missing, go live, validate, checklist
WHEN TO USE:
- Before launching a campaign, to confirm it is actually ready
- After assembling or editing a draft, as the go/no-go check
- When the user asks "is my campaign ready to launch?" or "what's missing?"
RETURNS:
A per-channel readiness report:
- is_launchable: whether EVERY enabled channel is ready
- verified: whether the platform's pre-launch check actually answered. When false,
is_launchable is an assumption, NOT a verdict - say the check could not be run
instead of telling the user the campaign is ready.
- channels: [{channel, launchable, blockers[], ads, audiences, offers, budget}]
- summary: a one-line human verdict
This is a READ-ONLY check - it does NOT launch anything. Use launch_campaign to actually launch.
CHANNEL CONNECTION: a channel with no live integration is reported as a blocker here, and the
platform will refuse the launch itself. This is the ONLY point in a build where a missing
connection matters - audiences, targeting, offers, creative and the draft campaign are all
built without one on purpose. So do NOT ask the user to connect anything earlier; raise it
here, name the channels, and offer to connect them.
PARAMETERS:
- campaign_id: The wizard campaign ID (integer, required)
CAMPAIGN ID SOURCES:
- search_campaigns_by_names tool (returns campaign IDs)
- create_campaign tool response (returns campaign_id)| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The wizard campaign ID to check launch readiness for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description reinforces this while adding important behavioral nuance: the 'verified' field distinguishes a real platform verdict from an assumption, and the per-channel blocker logic is explained. It also discloses that a missing live channel connection is reported as a blocker and that the platform will refuse the launch itself, which goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear section headers, front-loaded purpose, and useful return details. Some content, such as the keyword list, is somewhat redundant for an agent that already has the title and schema, but it does not obscure the essential guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Because there is no output schema, the description correctly explains the return structure including is_launchable, verified, channels, and summary. It also covers when to use the tool, the read-only nature, channel-connection handling, and where to find campaign IDs. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents campaign_id as a required integer, so the baseline is 3. The description adds value by explaining this is specifically 'The wizard campaign ID' and by listing concrete ID sources through search_campaigns_by_names and create_campaign. This helps an agent obtain the parameter correctly, though it does not need to compensate for missing schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Check whether a draft campaign is ready to launch, per channel.' It also explicitly disambiguates from sibling launch_campaign by saying 'This is a READ-ONLY check - it does NOT launch anything. Use launch_campaign to actually launch.' An agent can tell what it does and what it is not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'WHEN TO USE' bullets covering pre-launch confirmation, go/no-go after draft edits, and direct user questions. It also gives exclusion guidance: do not ask the user to connect channels earlier in the build because this is the only point where a missing connection matters, and names launch_campaign as the alternative for actually launching.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connect_channelConnect ChannelAInspect
Get the OAuth redirect URL to connect a specific advertising channel to the Metadata platform.
USAGE INSTRUCTIONS FOR LLM:
Use this tool to obtain the authorization URL that users need to visit to connect their advertising channel accounts.
This tool returns a redirect URL that initiates the OAuth flow for the selected channel.
WHEN TO USE THIS TOOL:
- User asks to "connect [channel name]"
- User wants to "add [channel] integration"
- User needs to "link [channel] account"
- User wants to "authorize [channel] access"
- User asks "how do I connect my Facebook/LinkedIn/Twitter/Reddit/Google account?"
- User needs to "set up [channel] connection"
- After disconnecting a channel and wanting to reconnect
- User asks "give me the link to connect [channel]"
SUPPORTED CHANNELS:
- linkedin: Connect LinkedIn advertising account
- meta: Connect Facebook/Instagram advertising accounts (Meta Business Suite)
- google: Connect Google Ads account
- reddit: Connect Reddit advertising account
- x: Connect X (Twitter) advertising account
IMPORTANT WORKFLOW - MUST FOLLOW THESE STEPS:
1. Call this tool to get the OAuth redirect URL
2. Display the URL to the user clearly and instruct them to open it in their browser
3. Explain that they need to complete the authorization process on the channel's website
4. IMPORTANT: Ask the user to return to the chat and confirm when they have completed the connection
5. WAIT for the user's confirmation before proceeding with any other tasks
6. Once the user confirms the connection is complete, acknowledge it and continue
REQUIRED USER INTERACTION:
- The user MUST visit the returned URL in their browser to complete OAuth authorization
- The URL will redirect to the channel's authorization page
- After authorization, the user will be redirected back to Metadata platform
- The connection will be active once the OAuth flow is completed successfully
- YOU MUST WAIT for user confirmation before proceeding
COMMON SCENARIOS:
Scenario 1 - Connect new channel: "I want to connect my LinkedIn account"
→ Call connect_channel with channel="linkedin"
→ Show URL to user: "Please open this URL to connect your LinkedIn account: [URL]"
→ "After completing the authorization, please return here and let me know it's done so we can proceed."
→ WAIT for user confirmation
Scenario 2 - Reconnect after disconnect: "Get me the link to reconnect Facebook"
→ Call connect_channel with channel="meta"
→ Show URL to user with instructions
→ WAIT for user confirmation
Scenario 3 - Setup new integration: "How do I add Google Ads?"
→ Call connect_channel with channel="google"
→ Explain OAuth process and provide URL
→ Ask user to confirm when complete
→ WAIT for user confirmation
Scenario 4 - Add Twitter/X: "Connect my X account"
→ Call connect_channel with channel="x"
→ Provide the URL to user
→ WAIT for user confirmation
RESPONSE FORMAT:
Returns an object containing the redirect URL for OAuth authorization.
Example: {"redirectUrl": "https://oauth.channel.com/authorize?client_id=..."}
EXAMPLE: "Connect LinkedIn" → connect_channel(channel="linkedin")
| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | The channel to connect. Must be one of: linkedin, meta (for Facebook/Instagram), google, reddit, x (for Twitter) | |
| acknowledge_data_access | No | Set true to confirm the person you are acting for asked to connect this channel. The response is an OAuth authorization URL that starts a credential grant into their Metadata account. Without this the call is refused. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the minimal annotations by explaining that the tool only returns a redirect URL, that the user must complete OAuth in a browser, and that the connection is active only after the OAuth flow finishes. It also stresses the agent must wait for user confirmation, which is a critical behavioral constraint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear summary and is well-organized with headers. However, the four 'COMMON SCENARIOS' repeat nearly identical instructions, and the workflow/user-interaction sections overlap, making it longer than necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is thorough for a two-parameter tool: it explains the return format with an example, required user interaction, and the step-by-step workflow. The main gap is that the example omits the acknowledge_data_access parameter even though the schema says the call is refused without it, but this is covered in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers both parameters with 100% descriptions and an enum for channel, so the baseline applies. The description adds a 'SUPPORTED CHANNELS' list and examples, but these largely mirror the schema's enum and don't introduce new semantics for either parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb ('Get'), resource ('OAuth redirect URL'), and scope ('connect a specific advertising channel to the Metadata platform'). The description also clarifies it is the authorization-URL step, which distinguishes it from broader operations like connect_crm or disconnect_channel.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated 'WHEN TO USE THIS TOOL' section lists concrete user intents ('connect [channel]', 'link [channel] account', etc.) and even covers reconnection after disconnect. However, it does not explicitly state when not to use the tool or mention alternative sibling tools, so it falls short of fully explicit routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connect_crmConnect CRMAInspect
Get the OAuth redirect URL to connect a specific CRM system to the Metadata platform.
USAGE INSTRUCTIONS FOR LLM:
Use this tool to obtain the authorization URL that users need to visit to connect their CRM accounts.
This tool returns a redirect URL that initiates the OAuth flow for the selected CRM system.
WHEN TO USE THIS TOOL:
- User asks to "connect [CRM name]"
- User wants to "add [CRM] integration"
- User needs to "link [CRM] account"
- User wants to "authorize [CRM] access"
- User asks "how do I connect my Salesforce/HubSpot CRM?"
- User needs to "set up [CRM] connection"
- After disconnecting a CRM and wanting to reconnect
- User asks "give me the link to connect [CRM]"
SUPPORTED CRM SYSTEMS:
- salesforce: Connect Salesforce CRM
- hubspot: Connect HubSpot CRM
IMPORTANT WORKFLOW - MUST FOLLOW THESE STEPS:
1. Call this tool to get the OAuth redirect URL
2. Display the URL to the user clearly and instruct them to open it in their browser
3. Explain that they need to complete the authorization process on the CRM's website
4. IMPORTANT: Ask the user to return to the chat and confirm when they have completed the connection
5. WAIT for the user's confirmation before proceeding with any other tasks
6. Once the user confirms the connection is complete, acknowledge it and continue
REQUIRED USER INTERACTION:
- The user MUST visit the returned URL in their browser to complete OAuth authorization
- The URL will redirect to the CRM's authorization page
- After authorization, the user will be redirected back to Metadata platform
- The connection will be active once the OAuth flow is completed successfully
- YOU MUST WAIT for user confirmation before proceeding
COMMON SCENARIOS:
Scenario 1 - Connect Salesforce: "I want to connect my Salesforce CRM"
→ Call connect_crm with crm="salesforce"
→ Show URL to user: "Please open this URL to connect your Salesforce CRM: [URL]"
→ "After completing the authorization, please return here and let me know it's done so we can proceed."
→ WAIT for user confirmation
Scenario 2 - Connect HubSpot: "Connect HubSpot CRM"
→ Call connect_crm with crm="hubspot"
→ Show URL to user with instructions
→ WAIT for user confirmation
Scenario 3 - Reconnect workflow: "I want to reconnect my Salesforce with different credentials"
→ First disconnect existing connection if needed
→ Call connect_crm with crm="salesforce"
→ Provide the URL to user
→ WAIT for user confirmation
RESPONSE FORMAT:
Returns an object containing the redirect URL for OAuth authorization.
Example: {"redirectUrl": "https://login.salesforce.com/services/oauth2/authorize?..."}
EXAMPLE: "Connect Salesforce" → connect_crm(crm="salesforce")
| Name | Required | Description | Default |
|---|---|---|---|
| crm | Yes | The CRM system to connect. Must be one of: salesforce, hubspot | |
| acknowledge_data_access | No | Set true to confirm the person you are acting for asked to connect this CRM. The response is an OAuth authorization URL that starts a credential grant into their Metadata account. Without this the call is refused. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate non-read-only, open-world, non-destructive behavior. The description adds valuable behavioral context: it initiates an OAuth flow requiring user interaction, mandates waiting for user confirmation, and notes that the call is refused without acknowledge_data_access=true. It explains the redirect flow and eventual activation of the connection. However, it does not cover failure modes or what happens if the user does not confirm, leaving some gaps beyond the annotation profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long and detailed, with sections for usage, workflow, scenarios, and response format. It is well-organized and front-loaded with purpose, but it is verbose and includes repetitive instructions (e.g., repeated 'WAIT for user confirmation' across sections). Some content, such as the example response format, is redundant given the schema. It could be trimmed without losing essential guidance, so it does not earn a top score for conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and a multi-step OAuth flow, the description is exceptionally complete. It explains the return value (object with redirectUrl), the required user interaction, the full workflow, and common scenarios. It covers all the information an agent needs to correctly invoke the tool and guide the user, fulfilling the description's burden given the lack of an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both parameters, with clear enum values for crm and a thorough explanation of acknowledge_data_access in the schema itself. The description's examples (crm='salesforce') and scenario mentions reinforce the schema but do not add new semantic meaning. Since the schema already carries the parameter documentation, the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: 'Get the OAuth redirect URL to connect a specific CRM system'. It enumerates supported CRM systems (salesforce, hubspot) and explicitly distinguishes from generic channel connections (e.g., connect_channel) by focusing on CRM OAuth. The purpose is unambiguous and easily differentiates from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a dedicated 'WHEN TO USE THIS TOOL' section with concrete user intents (e.g., 'connect [CRM name]', 'add [CRM] integration') and a detailed workflow with numbered steps. It also provides common scenarios (Salesforce, HubSpot, reconnect) that illustrate exact invocation patterns. This gives the agent explicit guidance on when to call this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_audience_from_segmentCreate Audience from SegmentAInspect
Create a dynamic Insights Retargeting audience from a saved Insights (Spotlight) segment: the companies matching the segment inside a lookback window, refreshed automatically as the journey data changes.
TWO VARIANTS (audience_type):
"contacts" (default): Insights Retargeting Contacts, platform type WEBSITE_RETARGETING. Contacts at the matching accounts, matched through the Metadata contact graph; usable on LinkedIn, Facebook, Instagram, X and Reddit.
"accounts": Insights Retargeting Accounts, platform type WEBSITE_ACCOUNT_RETARGETING. The matching COMPANIES pushed to LinkedIn as a matched company audience; LinkedIn only. The shape for account-level INCLUSION or EXCLUSION on LinkedIn, e.g. suppressing accounts that already received 200+ impressions from a sequenced program.
WHEN: behaviour- or CRM-state-based retargeting and suppression ("retarget accounts that visited pricing", "exclude accounts we already saturated", "high engagement score not in the CRM"). NOT for firmographic / technographic / intent asks (use those audience tools), and NOT for LinkedIn ad-engagement retargeting (create_linkedin_engagement_retargeting_audience works off LinkedIn's own engagement signals; this one works off the Spotlight journey: website visits, impressions, clicks, scores, CRM state).
WORKFLOW (each step is checked and a failure is refused with the reason):
list_segments, then get_segment_criteria(segment_id, lookback_window): the segment must exist, be READY, and match at least one account in the window. A segment matching 0 accounts is refused (widen the window, or create_segment with looser criteria).
lookback_window in days (1 to 365): the window the segment's metrics are evaluated over ("in the last 90 days" = 90).
Call this tool with a descriptive name. The audience appears in the library as "Insights Retargeting Contacts (Dynamic)" or "Insights Retargeting Accounts (Dynamic)".
RETURNS: {success, id, audience_id, audience_name, status, audience_type, platform_audience_type, segment_id, segment_name, lookback_window, accounts_in_window, channels, expectedNumberOfCompanies, expectedNumberOfContacts, criteria}. Member matching is asynchronous: -1 or 0 right after creation means "not matched yet"; check again later with get_deep_audience_details.
USED AS AN EXCLUSION: Ann attaches it through add_and_edit_campaign_elements (exclude_audiences) on the campaign that must not reach those accounts.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name for the new audience. Unique and descriptive, e.g. 'Exclude: 200+ LinkedIn impressions, 90d'. | |
| segment_id | Yes | The id of a READY segment from list_segments / create_segment. | |
| audience_type | No | contacts (default): people at the matching accounts, multi-channel. accounts: the matching companies as a LinkedIn matched audience, LinkedIn only; use it for account-level LinkedIn exclusions. | |
| lookback_window | Yes | Days the segment is evaluated over. Range 1 to 365. 30 for the last month, 90 for the last quarter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it as a non-read, non-destructive operation; the description adds useful behavioral detail by describing a checked workflow that fails with a reason and a RETURNS section. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Organized into sections, but substantially overlong and repetitive; a shorter description would serve an agent better.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers variants, when to use, workflow/failure behavior, returns, and exclusion usage. With no output schema, the RETURNS section helps fill the gap. Slightly too noisy to merit a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all parameters with descriptions (100% coverage), so the description adds little beyond what the schema provides; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create an Audience from a Segment') and explains the two audience_type variants. It does not explicitly contrast with sibling create_*_audience tools, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a dedicated WHEN section and a USED AS AN EXCLUSION note, giving an agent explicit context for when to invoke it. It does not name an alternative sibling tool, so not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_bombora_audienceCreate Bombora AudienceAInspect
Create Bombora buyer intent audiences on the Metadata platform. Creates B2B audiences based on buyer intent topics, company firmographics, contact attributes, and geographic targeting.
IMPORTANT PREREQUISITE:
Before using this tool, call get_intent_topics first to verify that Bombora topics are available.
If get_intent_topics returns NO topics (empty list), Bombora is NOT available for this account —
do NOT suggest or use this tool. Instead, recommend creating a firmographic audience
(create_firmographic_audience) as the preferred alternative.
Firmographic audiences are the default and most commonly used audience type.
WHEN TO USE:
- ONLY after get_intent_topics confirms that Bombora topics are available
- Create targeted B2B audiences based on buyer intent signals using Bombora data
- Target companies by industry, size, and employee count
- Target contacts by seniority level and job function
- Target specific buyer intent topics (e.g., Pardot, Salesforce)
- Set geographic targeting and contact limits per company
BUYER INTENT TOPICS:
Use the get_intent_topics tool to retrieve available intent topics before creating the audience.
Intent topics represent buyer interest areas such as:
- CRM solutions (e.g., Pardot, Salesforce)
- Marketing automation platforms
- Analytics and BI tools
- And many others based on available topics
TARGETING OPTIONS:
- Intent Topics: Use topic values from get_intent_topics (required for Bombora audience)
- Industries: Use industry IDs. Examples:
1=Defense & Space, 4=Computer Software, 6=Internet, 7=Semiconductors, 8=Telecommunications,
11=Management Consulting, 12=Biotechnology, 41=Banking, 42=Insurance, 43=Financial Services,
80=Marketing & Advertising, 96=Information Technology & Services
- Employees: "FROM_1_TO_10", "FROM_10_TO_50", "FROM_50_TO_200", "FROM_200_TO_500", "FROM_500_TO_1000", "FROM_1000_TO_5000", "FROM_5000_TO_10000", "OVER_10000"
- Job Function / Seniority / Job Title / Location: identical shape to the Firmographic + G2 tools (PRD-29704 — the old Bombora-specific names `function_ids` / `seniority_ids` / `countries` / `cities` were renamed to the canonical contact-criteria fields below so Max can transfer the same criteria across audience types).
CONTACTS CRITERIA:
Use the following parameters to filter and target specific contacts within accounts:
GEOGRAPHIC TARGETING:
location_country_ids: Array of country IDs (e.g., [29] for Brazil, [229] for United States)
location_state_ids: Array of state IDs (e.g., [5] for California, [32] for New York)
JOB TITLES:
job_title_includes: Array of free text strings to include (e.g., ["Software Engineer", "Manager"])
job_title_excludes: Array of free text strings to exclude (e.g., ["Senior", "Lead"])
JOB FUNCTIONS: Valid job function IDs and their labels:
1: Marketing, 2: Sales, 3: Customer Service, 4: Finance, 5: Human Resources, 6: Public Relations
7: Media, 8: Design, 9: Engineering, 10: Operations, 11: Legal, 12: Education
13: Health, 14: Real Estate, 15: Accounting, 16: Administrative, 17: Business Development
18: Community and Social Services, 19: Consulting, 20: Entrepreneurship, 21: Information Technology
22: Military and Protective Services, 23: Product Management, 24: Program and Project Management
25: Purchasing, 26: Quality Assurance, 27: Research, 28: Trades
job_function_include_ids: Array of job function IDs to include (e.g., [9] for Engineering)
job_function_exclude_ids: Array of job function IDs to exclude
SENIORITY LEVELS: Valid seniority IDs and their labels:
2: Manager, 3: Director, 4: VP, 5: CXO, 6: Unpaid, 7: Training
8: Senior, 9: Owner, 10: Entry, 11: Partner
seniority_include_ids: Array of seniority level IDs to include (e.g., [10, 7] for Entry and Training)
seniority_exclude_ids: Array of seniority level IDs to exclude
CONTACT LIMITS:
contacts_per_company_limit: Maximum number of contacts to target per company (optional). Example: 20
USAGE NOTES:
All ID fields (countries, states, job functions, seniorities) use numeric IDs from the platform
Job titles are free text strings, not IDs
Use include parameters to specify which criteria to target
Use exclude parameters to filter out contacts matching specific criteria
Combine multiple criteria for precise targeting (e.g., Senior Engineers in California)
Criteria are combined with AND logic, so all conditions must be met
CONTACTS CRITERIA PARAMETERS(Usually after other initial audience parameters to be described next):
location_country_ids: Array of country IDs (optional)
location_state_ids: Array of state IDs (optional)
job_title_includes: Array of job title keywords to include (optional)
job_title_excludes: Array of job title keywords to exclude (optional)
job_function_include_ids: Array of job function IDs (optional)
job_function_exclude_ids: Array of job function IDs (optional)
seniority_include_ids: Array of seniority level IDs (optional)
seniority_exclude_ids: Array of seniority level IDs (optional)
contacts_per_company_limit: Maximum contacts per company (optional)
Returns audience details with ID, size estimation, and creation status.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required) | |
| topics | Yes | Array of buyer intent topics (required). Use get_intent_topics to retrieve available topics. Example: ['Pardot', 'Salesforce'] | |
| employees | No | Employee count ranges for company targeting (optional). Valid values: 'FROM_1_TO_10', 'FROM_10_TO_50', 'FROM_50_TO_200', 'FROM_200_TO_500', 'FROM_500_TO_1000', 'FROM_1000_TO_5000', 'FROM_5000_TO_10000', 'OVER_10000' | |
| industries | No | Industry IDs for company targeting (optional). Valid range: 1-148. Example: [4, 96] | |
| job_title_excludes | No | Free text keywords for job titles to exclude (optional). Example: ['Senior', 'Lead'] | |
| job_title_includes | No | Free text keywords for job titles to include (optional). Example: ['Software Engineer', 'Manager'] | |
| location_state_ids | No | State IDs for geographic targeting (optional). Valid US State IDs: 1 (Alabama), 2 (Alaska), 3 (Arizona), 4 (Arkansas), 5 (California), 6 (Colorado), 7 (Connecticut), 8 (Delaware), 9 (Florida), 10 (Georgia), 11 (Hawaii), 12 (Idaho), 13 (Illinois), 14 (Indiana), 15 (Iowa), 16 (Kansas), 17 (Kentucky), 18 (Louisiana), 19 (Maine), 20 (Maryland), 21 (Massachusetts), 22 (Michigan), 23 (Minnesota), 24 (Mississippi), 25 (Missouri), 26 (Montana), 27 (Nebraska), 28 (Nevada), 29 (New Hampshire), 30 (New Jersey), 31 (New Mexico), 32 (New York), 33 (North Carolina), 34 (North Dakota), 35 (Ohio), 36 (Oklahoma), 37 (Oregon), 38 (Pennsylvania), 39 (Rhode Island), 40 (South Carolina), 41 (South Dakota), 42 (Tennessee), 43 (Texas), 44 (Utah), 45 (Vermont), 46 (Virginia), 47 (Washington), 48 (West Virginia), 49 (Wisconsin), 50 (Wyoming), 52 (District of Columbia). Example: [5] for California, [32] for New York | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| seniority_exclude_ids | No | Seniority level IDs to exclude (optional). Valid IDs: 2-11 as listed above | |
| seniority_include_ids | No | Seniority level IDs to include (optional). Valid IDs: 2 (Manager), 3 (Director), 4 (VP), 5 (CXO), 6 (Unpaid), 7 (Training), 8 (Senior), 9 (Owner), 10 (Entry), 11 (Partner). Example: [10, 7] for Entry and Training | |
| job_function_exclude_ids | No | Job function IDs to exclude (optional). Valid IDs: 1-28 as listed above | |
| job_function_include_ids | No | Job function IDs to include (optional). Valid IDs: 1 (Marketing), 2 (Sales), 3 (Customer Service), 4 (Finance), 5 (HR), 6 (PR), 7 (Media), 8 (Design), 9 (Engineering), 10 (Operations), 11 (Legal), 12 (Education), 13 (Health), 14 (Real Estate), 15 (Accounting), 16 (Administrative), 17 (Business Development), 18 (Community Services), 19 (Consulting), 20 (Entrepreneurship), 21 (IT), 22 (Military Services), 23 (Product Management), 24 (Program/Project Management), 25 (Purchasing), 26 (QA), 27 (Research), 28 (Trades). Example: [9] for Engineering | |
| contacts_per_company_limit | No | Maximum number of contacts to target per company (optional). Example: 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnlyHint=false and destructiveHint=false, so the description carries the burden of explaining behavior. It adds valuable context: the dependency on get_intent_topics, AND logic across criteria, examples of include/exclude semantics, and the expected return content (ID, size estimation, creation status). It falls slightly short only because it does not discuss side effects or operational limits, though the annotations already establish this is a write but non-destructive operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is not appropriately sized. It is very long and repetitive: the CONTACTS CRITERIA section appears twice with almost identical parameter lists, and several ID labels and examples are duplicated from the input schema. While the most important prerequisite is front-loaded, the redundant sections make the definition harder to scan than it should be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter tool with no output schema, the description is remarkably complete: it covers prerequisites, when to use, when not to use, alternative tools, full valid value sets, examples, AND logic, and return information. An agent has enough context to decide whether to invoke it and how to fill its parameters correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema description coverage is 100%, the description adds substantial meaning beyond the schema: human-readable labels for industry, job function, and seniority IDs; concrete examples; include/exclude semantics; AND-combination logic; and the instruction to source topic values from get_intent_topics. This goes well beyond what the structured schema alone provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as creating Bombora buyer intent audiences on the Metadata platform, and further specifies that it targets B2B audiences by buyer intent topics, firmographics, contact attributes, and geography. This is a specific verb-resource pair that distinguishes it from sibling audience creation tools like create_firmographic_audience or create_g2_intent_*.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance, including a mandatory prerequisite: call get_intent_topics first, and if no topics are returned, do NOT use this tool. It also names the preferred alternative, create_firmographic_audience, making the decision boundary entirely clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_budget_groupCreate or Update Budget GroupADestructiveInspect
Create or update advertising budget and spending allocation. Set up budget groups to control how much money campaigns can spend. ALSO KNOWN AS: set budget, allocate spend, create spending plan, budget allocation, ad budget, campaign budget
KEYWORDS: budget, spend, spending, money, dollars, $, quarter, monthly, allocation, cost, funds, cap, limit
SUPPORTED TYPES:
- Lead Generation (default): goal=CPL, groupMetric=CPL, optimizerFormula=CPL_2 (or CPC_2), autoPauseConfigurationId=14, enableBooster=true. Requires benchmark and groupMetric. Dates follow budgetType, not the goal (see DATE RULES): FIXED_BUDGET sends startDate AND endDate, MONTHLY_RESET sends neither.
- Brand Awareness: goal=CTR, autoPauseConfigurationId=9, enableBooster=false, budgetType=MONTHLY_RESET. Two formula variants:
• CPC variant: groupMetric=CPC, optimizerFormula=CPC_2 (benchmark is a CPC target, e.g. 10)
• CTR variant: groupMetric=CTR, optimizerFormula=CTR (benchmark is a CTR target in basis-points style, e.g. 10000)
budgetRedistributionStrategy may be PERFORMANCE or PACING_ONLY. MONTHLY_RESET: omit BOTH startDate and endDate.
WARNING: BUDGET-GROUP TYPE MUST FOLLOW THE CAMPAIGN GOAL (do not mix):
- A CPL / Lead Generation campaign (campaignType "Lead Gen") REQUIRES a Lead Generation (CPL) budget group: goal=CPL, groupMetric=CPL, optimizerFormula=CPL_2, enableBooster=true, autoPauseConfigurationId=14.
- A Brand Awareness campaign (campaignType "Brand Awareness") REQUIRES a Brand Awareness budget group: goal=CTR, enableBooster=false, budgetType=MONTHLY_RESET, autoPauseConfigurationId=9 (CPC or CTR formula variant per SUPPORTED TYPES above).
- NEVER attach a Brand-Awareness (CTR) budget group to a CPL campaign, or a Lead-Generation (CPL) budget group to a Brand Awareness campaign — the optimizer goal must match the campaign's objective. If the campaign goal is unknown, confirm it before creating the budget group.
To UPDATE: include 'id' field with the budget group ID.
To CREATE: omit the 'id' field.
Pass all fields inside the `data` object. Dates must be ISO 8601 UTC with exactly 3 ms digits, e.g. 2026-01-15T12:00:00.000Z (format example only — compute the real values).
CRITICAL DATE RULES:
- startDate and endDate travel TOGETHER: send both or neither. The platform rejects one without the other with 400 VALIDATION_DATE ("End Date can not be empty" / "Start Date can not be empty"). budgetType decides which: FIXED_BUDGET = both required; MONTHLY_RESET = omit both. This holds for EVERY goal, CPL included: a Lead Gen group with a monthly budget is MONTHLY_RESET with no dates at all, never MONTHLY_RESET plus a startDate.
- You do NOT inherently know today's date. If you are not already certain of it, call get_current_date FIRST and anchor every rule below to that real value — never guess.
- The endDate MUST ALWAYS be in the future (strictly after today's real date).
- NEVER set an endDate that is today or in the past — this will cause the budget group to be immediately expired.
- "this month" → endDate = the last day of the current month. "this quarter" → endDate = the last day of the current quarter. "next month" / "next quarter" → compute relative to today's real date.
- If the user provides a specific end date that is in the past, WARN THEM and ask for a valid future date. Do NOT submit a past endDate.
- startDate can be today or in the future, but never in the past for new budget groups.
REMARKS:
- If the user doesn't EXPLICITLY states that their budget is by month or MONTHLY, then use FIXED_BUDGET as budgetType.
- In other words, the default value is FIXED_BUDGET unless the user explicitly says MONTHLY or BY MONTH.
- IF the user says "this month" then also use FIXED_BUDGET and start date should be today, end date should be the last day of the month.
- When you use FIXED_BUDGET (fixed-date) but the user's timing expectations/goals are NOT clear, ASK for an explicit start-date and end-date before creating — do not silently invent a date range. Only skip the question when the dates are already unambiguous (e.g. the user gave a range, or said "this month"/"this quarter").
- monthlyCap is the user's money: when the user has NOT explicitly stated a budget / monthly cap (or confirmed a figure you proposed), ASK for it before creating — do not silently invent a cap. This applies to campaign-creation flows too: a budget group needed by a new campaign still requires a user-chosen cap. Same when an update would change monthlyCap.
- If the user says "set a monthly budget of $X" or equivalent then use MONTHLY_RESET as budgetType (MONTHLY is NOT a valid value, the platform rejects it)
- Before an update, refresh the information by using get_budget_group to avoid overwriting fields unintentionally.
- The campaign doesn't need to be in a launched state for its budget group to be updated.
WHEN TO USE:
- User wants to create a new budget group with specific settings
- We're creating a campaign and need to set up its budget group.
- User requests to update an existing budget group with new parameters
- User requests to update the budget of a campaign
INTEGRATION WITH OTHER TOOLS:
- If the ID for a budget group update is unknown there are a few options:
- if you have the campaign name, use search_campaigns_by_name. In its response, `$.optimizationGroup.id` is the budget group ID.
- From search_campaigns_by_names's response, you get the property `$.optimizationGroup.id`. That's the budget group ID.
- You can also use get_budget_group if you have the budget group name to retrieve its ID.
Anchor every date calculation to the REAL current date — if you are not certain what today is, call get_current_date before computing start/end dates.| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | Budget group configuration |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and readOnlyHint=false, so the agent already knows this is a mutating operation. The description adds substantial behavioral context beyond that: it warns that the platform rejects mismatched date pairs with 400 VALIDATION_DATE errors, that past endDates cause immediate expiration, that MONTHLY is not a valid budgetType value, and that the tool requires user-confirmed caps rather than silently inventing them. It also discloses that the campaign doesn't need to be launched for updates. The only minor gap is that it doesn't describe the success/error response shape, but with no output schema and rich behavioral warnings already present, this is a strong disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense and well-organized with clear section headers (SUPPORTED TYPES, WARNING, CRITICAL DATE RULES, REMARKS, WHEN TO USE, INTEGRATION WITH OTHER TOOLS). However, it is quite long and contains some redundancy: the date rules are repeated across CRITICAL DATE RULES and REMARKS (e.g., 'this month' handling appears in both), and the CPL/Lead Gen configuration is stated in both SUPPORTED TYPES and the WARNING section. The 'ALSO KNOWN AS' and 'KEYWORDS' sections, while useful for search, add bulk. Every section earns its place, but tighter editing would improve it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex create/update tool with nested objects, no output schema, and destructive annotations, the description is remarkably complete. It covers the create-vs-update distinction, all supported type configurations, date-format requirements, date-pairing rules, the need to call get_current_date, the need to confirm user budget figures, and how to resolve unknown IDs via sibling tools. The only thing missing is the response format, but the description's job is to guide invocation, and it does that thoroughly. The integration with get_current_date and search_campaigns_by_name closes the main contextual gaps an agent would face.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter. The description adds significant meaning beyond the schema: it explains which parameter combinations are valid per budget-group type (e.g., FIXED_BUDGET requires both startDate and endDate; MONTHLY_RESET requires neither), which optimizerFormula values pair with which groupMetric values, and which autoPauseConfigurationId to use for each goal. It also clarifies that 'MONTHLY' is not a valid enum value and that monthlyCap must be user-confirmed. This goes well beyond the schema's terse field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Create or update advertising budget and spending allocation') and immediately states the core purpose: 'Set up budget groups to control how much money campaigns can spend.' It also includes a comprehensive 'ALSO KNOWN AS' and 'KEYWORDS' section that helps an agent recognize the tool across many phrasings. The title 'Create or Update Budget Group' is expanded with clear create-vs-update semantics (include 'id' to update, omit to create). This clearly distinguishes it from siblings like get_budget_group, list_budget_groups, and budget_group_performance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has an explicit 'WHEN TO USE' section listing four concrete scenarios: creating a new budget group, setting up a budget group during campaign creation, updating an existing budget group, and updating a campaign's budget. It also provides 'INTEGRATION WITH OTHER TOOLS' guidance for resolving unknown IDs via search_campaigns_by_name or get_budget_group. The extensive WARNING section tells the agent when NOT to use certain configurations (e.g., never mix budget-group type with campaign goal), which is strong exclusionary guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_campaignCreate Campaign — Precision Optimization (1×1×1)AInspect
Create multi-channel advertising campaigns for LinkedIn, Facebook, Instagram, Google Ads, Reddit, and Microsoft Ads using the platform's "Precision Optimization" (1×1×1) model — Metadata's signature approach. Every audience×ad×offer combination is tested as its OWN isolated experiment (each experiment = exactly 1 audience × 1 ad × 1 offer); you pass per-channel lists of audiences, ads, and offers and the backend creates one experiment per combination. Platform product copy: "Metadata's signature approach with maximum budget control and fastest learning through separate testing of each combination." This is the DEFAULT structure when the user hasn't chosen one. Sets channel.structureType=METADATA (no WizNativeAdContainer).
KEYWORDS (for tool discovery — many users ask by the math, not the product name): 1x1x1, 1×1×1, "1x1x1 campaign", "one by one by one", Precision Optimization, separate testing of each combination, isolated per-combination experiments, maximum budget control, fastest learning.
NAMING CONVENTION (from the platform UI's "Campaign Structure" selector — match these exact labels):
• "Precision Optimization (1x1x1)" = THIS tool (`create_campaign`). Each experiment isolates one audience×ad×offer cell; the platform builds one per combination. Metadata's signature approach; the DEFAULT.
• "Channel First Structure (NxNxN)" = the OTHER tool, `create_native_structure_campaign` (the UI also shows it as "Native Structure" / "Platform-First Structure"). Audiences/ads/offers are grouped in the ad platform's NATIVE structure (WizNativeAdContainer) and optimized together by the platform (~1 experiment per channel).
Routing anchor: "precision" / "1x1x1" → this tool; "native" / "channel first" / "platform first" / "NxNxN" → create_native_structure_campaign. (structureType=METADATA here, NATIVE there — and that lines up, because "native" means the native-platform structure.)
════════════════════════════════════════════════════════════════════════════════
WARNING: TWO CAMPAIGN-CREATION TOOLS EXIST — READ BEFORE PICKING ONE
════════════════════════════════════════════════════════════════════════════════
CRITICAL: REMEMBER — HOW TO CHOOSE THE STRUCTURE (the user's decision always wins):
1. If the user explicitly names one, RESPECT IT — "precision" / "Precision Optimization" / "1x1x1" → create_campaign (this tool); "native" / "Native Structure" / "Channel First" / "Platform-First" / "NxNxN" → create_native_structure_campaign.
2. ELSE, if the request involves MANY ads AND audiences (Precision Optimization makes one experiment per combination — a large experiment count), ASK the user which structure they want before creating — do not guess.
3. OTHERWISE, DEFAULT to Precision Optimization (1×1×1) → this tool (create_campaign).
The two build structurally different, non-swappable campaigns — so once the user decides, respect that decision for the rest of the campaign.
USE THIS TOOL (`create_campaign`) — "Precision Optimization" (1×1×1) — WHEN:
• The user says "Precision Optimization", "precision", "1x1x1", "1×1×1", "separate testing of each combination", or wants each combination tested in its own isolated experiment.
• The user gives per-channel lists of audiences/ads/offers and wants the platform to test every combination separately (one experiment per audience×ad×offer).
• The user wants maximum budget control / fastest per-combination learning.
• No structure was specified — this is the DEFAULT.
USE `create_native_structure_campaign` ("Channel First" / "Native Structure", N×N×N) INSTEAD — DO NOT USE THIS TOOL — WHEN:
• The user says "native", "Native Structure", "Channel First Structure", "channel-first", "Platform-First Structure", "platform-first", "NxNxN", "N×N×N", "WizNativeAdContainer", or asks for the traditional / hierarchical / native-platform structure.
• The user wants the ad platform's native structure to group and optimize audiences/ads/offers together (~1 experiment per channel, unified reporting) rather than one isolated experiment per combination.
• The user is migrating a campaign FROM "Precision Optimization" (1×1×1) TO the native "Channel First" structure.
Do not silently call this tool when the user has signalled Channel-First / native intent — the schemas and resulting platform state are different and not swappable after creation.
Apply the structure-selection rule above: respect an explicit "precision"/"native" choice; if the user didn't choose, ASK only when there are MANY ads AND audiences; otherwise default to Precision Optimization (1×1×1, this tool).
════════════════════════════════════════════════════════════════════════════════
WHEN TO USE:
- Create multi-channel marketing campaigns with unified configuration
- Set up campaigns with specific start/end dates and budget groups
- Configure Lead Generation or Brand Awareness campaigns
- Organize ads into groups with specific targeting and offers
- Set up Google Ads campaigns with keyword targeting
CAMPAIGN TYPES:
1. "Lead Gen" - Lead generation campaigns
2. "Brand Awareness" - Brand awareness campaigns
CRITICAL OFFER TYPE RULE:
- "Lead Gen" campaigns: ONLY Lead Gen (LG) form offers allowed. Landing Page (LP) offers are FORBIDDEN.
- "Brand Awareness" campaigns: Both LG and LP offers allowed. No restriction.
CRITICAL OFFER-CHANNEL PAIRING RULE (silent failure if violated)
Lead Gen offers are CHANNEL-LOCKED at creation time (the channel was set on create_update_offer via data.channel). An offer_id created with channel="LINKEDIN" CANNOT be assigned to facebook.offers / instagram.offers / google.offers — and vice versa. This server DOES NOT validate the pairing and will RETURN SUCCESS on a mis-wired campaign that cannot actually serve. The only way the user finds out is when the campaign produces zero impressions in the platform.
HARD RULES (verify each offer_id BEFORE submitting):
1. linkedin.offers MUST contain ONLY offer_ids whose creating call set data.channel="LINKEDIN" (or Landing Page offer_ids, which have no channel and are universal).
2. facebook.offers MUST contain ONLY offer_ids with data.channel="FACEBOOK" (or Landing Page offer_ids).
3. instagram.offers MUST contain ONLY offer_ids with data.channel="INSTAGRAM" or "FACEBOOK" (or Landing Page offer_ids).
4. google.offers MUST contain ONLY Landing Page offer_ids — Google Ads does NOT support Lead Gen forms. Putting any Lead Gen offer_id in google.offers is a HARD FAILURE.
5. reddit.offers MUST contain ONLY Landing Page offer_ids — Reddit does NOT support Lead Gen forms (create_update_offer rejects channel="REDDIT"). Putting any Lead Gen offer_id in reddit.offers is a HARD FAILURE.
6. microsoft.offers MUST contain ONLY offer_ids with data.channel="MICROSOFT_ADS" (or Landing Page offer_ids). Unlike Google, Microsoft Ads DOES accept Lead Gen offers, but only when channel-locked to MICROSOFT_ADS.
7. If the user's campaign requires Lead Gen on multiple channels, you MUST have called create_update_offer SEPARATELY for each channel (one call per channel per concept). Cross-channel reuse of a Lead Gen offer_id WILL break the campaign even though this API returns success.
8. If you cannot remember which channel an offer_id was created for, call get_offer(name=<offer_name>) first and read the channel field — DO NOT GUESS.
REQUIRED FIELDS:
- campaignType: "Lead Gen" or "Brand Awareness"
- name: Unique campaign name
- startDate / endDate: YYYY-MM-DD format
- budgetGroup: Budget group name (e.g., "BoFu", "ToFu", "Brand")
- Per-channel dailyBudget (optional, min $10): the channel's daily spend in USD. Set it whenever a budget split was approved (monthly channel budget / 30); a channel without it keeps the platform default of $50/day.
- At least one channel must be configured
CHANNEL-SPECIFIC CONFIGURATION:
WARNING: AUDIENCES vs TARGET GROUPS — CRITICAL DISTINCTION:
- "audiences": standard Metadata audiences (Firmographic, Bombora Intent, Retargeting, LinkedIn/Facebook Native, etc.)
- "target_groups": Targeting Groups (also called Target Groups) created in the platform's Targeting Groups section.
Both are arrays of names (strings). Send each type in its own field — do NOT mix them.
If the user mentions a "Targeting Group" or "Target Group", it goes in "target_groups", NOT in "audiences".
WARNING: ADS — SEPARATE (default) vs BUNDLED INTO ONE GROUP (opt-in):
The "ads" object has two slots and they map to two different platform structures:
- "ads.list": a flat array of ad IDs. Each id is sent as its own request, so a list of N ids
produces N separately managed ads, NOT one bundle. THIS IS THE DEFAULT — put ads here
unless the user explicitly asks for ad groups.
- "ads.groups": an array of {name, ads:[ids]} objects. Each object bundles its ad IDs into ONE named
ad group. Use this ONLY when the user explicitly wants ads grouped together
(e.g. "put these in an ad group", "group these ads"). LinkedIn has no ad-group concept — use list only.
You may send both: ads in "list" stay separate, ads in "groups" get bundled.
(Note: the platform wraps every ad in an ad-group record server-side, single ads included. That is
outside this tool's control and does not change the two shapes above.)
LINKEDIN (optional):
- audiences: Array of audience names (required if linkedin included)
Example: ["Test Native Audience", "EU Countries"]
- target_groups: Array of Targeting Group names
Example: ["My Target Group 1"]
- ads: Object with ad organization (required if linkedin included)
- list: Array of ad IDs, each sent as its own request (default). Example: [156502, 156485]
(LinkedIn has no ad groups — always use list.)
- offers: Array of offer IDs (required if linkedin included)
Example: [57538, 57504]
FACEBOOK (optional):
- audiences: Array of Facebook audience names (required if facebook included)
Example: ["fb-test", "automation-fb-retargeting-event-stage-blue"]
- target_groups: Array of Targeting Group names
- ads: Object with ad organization (required if facebook included)
- list: Array of ad IDs, each sent as its own request (DEFAULT — use this)
- groups: Array of ad group objects [{"name": str, "ads": [ids]}] — bundles ads into
a named ad group. ONLY when the user explicitly asks for grouped ads.
- offers: Array of offer IDs (required if facebook included)
INSTAGRAM (optional):
- audiences: Array of Instagram audience names (required if instagram included)
- target_groups: Array of Targeting Group names
- ads: Object with ad organization (required if instagram included)
- list: Array of ad IDs, each sent as its own request (DEFAULT — use this)
- groups: Array of ad group objects [{"name": str, "ads": [ids]}] — bundles ads into
a named ad group. ONLY when the user explicitly asks for grouped ads.
- offers: Array of offer IDs (required if instagram included)
- Often shares same audiences and offers as Facebook
GOOGLE ADS (optional):
- keywords: Object with keyword organization (required if google included)
- groups: [{"name": "CRM Keywords", "keywords": ["crm software", "lead gen tools"], "match_type": "PHRASE"}]
Each group also accepts "keyword_ids": [<existing library keyword IDs from list_keywords>] and "match_type": PHRASE|BROAD|EXACT (default PHRASE).
- audiences: Array of Google audience names (required if google included)
Example: ["SUP_SF_All-Customers-Contacts_ALL_3"]
- target_groups: Array of Targeting Group names
- ads: Object with ad organization (required if google included)
- list: [175258] — ad IDs each sent as their own request (DEFAULT — use this)
- groups: [{"name": "GOAT", "ads": [175260, 175259]}] — bundles ads into a named
ad group. ONLY when the user explicitly asks for grouped ads.
- offers: Array of offer IDs (required if google included)
- negative_keyword_lists: Array of negative keyword list names (optional)
Example: ["Competitor Brands", "Low Intent Keywords"]
These are assigned to the Google Ads channel AFTER campaign creation.
List names must match existing negative keyword lists (use list_negative_keywords_list to find them).
REDDIT (optional):
- audiences: Array of Reddit audience names (required if reddit included)
- target_groups: Array of Targeting Group names (Reddit Target Groups are created via create_reddit_target_group)
- ads: Object with ad organization (required if reddit included)
- list: Array of ad IDs, each sent as its own request. Reddit ads
are created via create_update_image_ad / create_update_video_ad with channels=["REDDIT"].
(Like LinkedIn, always use list — no ad groups.)
- offers: Array of offer IDs (required if reddit included). Landing Page
offers ONLY — Reddit does not support Lead Gen forms.
- Channel settings (objective, allow comments, placements, conversion pixel)
get UI-equivalent defaults on creation — adjust them afterwards with
update_reddit_channel_settings.
MICROSOFT ADS (optional):
- Search channel — mirrors Google Ads structurally. The platform pairs
MICROSOFT_ADS with GOOGLE_ADS for the TARGET_SPEND bid default.
- keywords: Object with keyword organization (required if microsoft included)
- groups: [{"name": "CRM Keywords", "keywords": ["crm software", "lead gen tools"], "match_type": "PHRASE"}]
Each group also accepts "keyword_ids": [<existing library keyword IDs from list_keywords>] and "match_type": PHRASE|BROAD|EXACT (default PHRASE).
- audiences: Array of Microsoft Ads audience names (required if microsoft included)
- target_groups: Array of Targeting Group names
- ads: Object with ad organization (required if microsoft included)
- list: Array of ad IDs, each sent as its own request (DEFAULT)
- groups: [{"name": "MS Group A", "ads": [ids]}] — bundles ads into a named
ad group. ONLY when the user explicitly asks for grouped ads.
- offers: Array of offer IDs (required if microsoft included). Lead Gen offers
must be MICROSOFT_ADS-locked (created with data.channel="MICROSOFT_ADS");
Landing Page offers are universal.
- negative_keyword_lists: Array of negative keyword list names (optional)
Example: ["Competitor Brands", "Low Intent Keywords"]
Assigned to the Microsoft Ads channel after creation. Names must match
existing lists (use list_negative_keywords_list to find them).
VALIDATION:
- Campaign name must be unique
- Start date must be before end date
- All referenced ad IDs, offer IDs, and audience names must exist
- If a channel is included, its required fields (audiences, ads, offers) must be provided
- WARNING: Lead Gen campaigns with Landing Page offers MUST be rejected
OFFER VERIFICATION (Lead Gen only):
1. Call get_offer to check offer types before campaign creation
2. If any offer is Landing Page → reject and suggest switching to Brand Awareness or replacing with LG offers
RESPONSE: Returns campaign_id, campaign_url, status, configured_channels, per-channel
details, optimization_group (id + tag_name), and a `full_response` payload with the
complete wizard state. On partial failures, returns success=false plus an `errors[]`
list — the campaign shell is still created and partial work is preserved.
Campaign URL: https://platform.metadata.io/hub/advertise/campaigns/{campaign_id}
BID STRATEGY (automatic — no user input needed):
Every enabled channel is set to a safe "auto" default immediately after creation so
the campaign is launch-ready:
- LinkedIn / Facebook / Instagram → AUTO_BID
- Google Ads / Microsoft Ads → TARGET_SPEND (device modifiers reset to 0)
- Reddit → follows the objective, mirroring the platform UI:
Lead Gen campaigns force the CLICKS (Traffic) objective + AUTO_BID; Brand
Awareness keeps the platform default IMPRESSIONS objective + MANUAL_BID.
Change objective/bid afterwards with update_reddit_channel_settings.
This happens regardless of account type and regardless of
campaign goal (CPL / CTR). The user can still override bid strategy later via the
platform UI or a dedicated tool.
EXAMPLE (Lead Gen, multi-channel):
create_campaign(campaign_data={
"campaignType": "Lead Gen",
"name": "Q1_Multi_Channel_2025",
"startDate": "2025-08-01",
"endDate": "2025-09-30",
"budgetGroup": "BoFu",
"linkedin": {
"audiences": ["Test Native Audience", "EU Countries"],
"ads": {"list": [156502, 156485]},
"offers": [57538, 57504]
}
})
EXAMPLE (Brand Awareness, single-channel):
create_campaign(campaign_data={
"campaignType": "Brand Awareness",
"name": "LinkedIn_Brand_Jan2025",
"startDate": "2025-01-15",
"endDate": "2025-02-15",
"budgetGroup": "Brand",
"linkedin": {
"audiences": ["Professional Audience"],
"ads": {"list": [173669, 171805]},
"offers": [57538]
}
CAMPAIGN URL FORMAT:
- All successful campaign creations return a direct URL to the campaign
- URL format: https://platform.metadata.io/hub/advertise/campaigns/{campaign_id}
- Use this URL to navigate directly to the campaign in the platform
- Campaign URL is always included in successful responses
- Provides immediate access to campaign management and monitoring
BEST PRACTICES:
1. Use descriptive, unique campaign names with dates or identifiers
2. Ensure all referenced assets (ads, offers, audiences) exist before campaign creation
3. Plan campaign dates appropriately with buffer time for setup
4. Group related ads together for better organization and reporting
5. Use consistent naming conventions for ad groups across channels
6. Test with single-channel campaigns before creating multi-channel campaigns
7. Verify budget group names match existing budget groups in the system
8. Save the returned campaign URL for quick access to campaign management
ERROR HANDLING:
- Validates all required fields are provided
- Checks that referenced ad IDs, offer IDs, and audience names exist
- Ensures campaign name uniqueness
- Validates date formats and logical date ranges
- Verifies at least one channel is configured
- Provides detailed error messages for troubleshooting
INTEGRATION NOTES:
- Supports both simple single-channel and complex multi-channel campaigns
- Automatically handles channel-specific configuration requirements
- Works in conjunction with ad and offer creation tools for complete campaign setup
- Provides comprehensive campaign status and configuration feedback
- Always returns the platform URL for immediate campaign access| Name | Required | Description | Default |
|---|---|---|---|
| campaign_data | Yes | Complete campaign configuration data |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnlyHint=false and destructiveHint=false, which disclose almost nothing about behavior. The description carries the burden and does it well: it reveals the silent-failure trap where the server returns success on offer-channel mismatches that cannot serve, partial failures still creating a campaign shell, automatic bid-strategy defaults per channel, $50/day platform budget default, and Reddit settings defaults. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely long and repetitive: the campaign URL format, offer-channel warning, and best practices appear multiple times, and the 'CAMPAIGN URL FORMAT' block interrupts the second JSON example with the call left unclosed. Clear headers help navigation, but many sentences do not earn their place, making this more bloated than concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-channel nested-parameter tool with no output schema, the description is essentially complete: required fields, per-channel configuration, validation rules, response shape (campaign_id, status, configured_channels, full_response, errors[]), bid strategy behavior, examples, and cross-tool references (get_offer, list_keywords, update_reddit_channel_settings). Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Though schema coverage is 100%, the description adds meaning far beyond the structured fields: dailyBudget derivation ('monthly channel budget / 30'), the $50/day default, the ads.list-vs-ads.groups distinction, the audiences-vs-target_groups distinction, per-channel offer pairing constraints, negative keyword list timing ('assigned AFTER campaign creation'), and two worked examples. This is exactly the semantic layer an agent needs to construct campaign_data correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb + resource: 'Create multi-channel advertising campaigns for LinkedIn, Facebook, Instagram, Google Ads, Reddit, and Microsoft Ads using the platform's Precision Optimization (1×1×1) model.' It explains the 1×1×1 semantics (one isolated experiment per audience×ad×offer combination) and explicitly distinguishes itself from the sibling create_native_structure_campaign, so an agent can tell them apart without reading schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains dedicated 'USE THIS TOOL ... WHEN' and 'USE create_native_structure_campaign INSTEAD' sections with explicit signals (precision/1x1x1 vs native/channel-first/NxNxN), plus a 3-step decision rule: respect explicit choice, ask when many ads and audiences, otherwise default to this tool. This is explicit when-to-use and when-not-to-use guidance naming the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_csv_upload_linkedin_native_audienceCreate CSV Upload - LinkedIn Native AudienceAInspect
Create a CSV Upload - LinkedIn Native audience (platform customAudienceType=NATIVE_TARGETING_CSV).
AUDIENCE TYPE (mirrors the UI's "Audience Type" dropdown):
• UI label: "CSV Upload - LinkedIn Native"
• Platform enum: NATIVE_TARGETING_CSV
• Channel: LinkedIn only.
• Two-step flow handled server-side: the CSV is uploaded as a NATIVE ABM list, then the audience is created from it with the LinkedIn-native firmographics + contact criteria applied.
PREREQUISITE:
• LinkedIn integration MUST be connected.
WHEN TO USE (exact user phrasing this tool should match):
• "CSV Upload - LinkedIn Native"
• "Upload a CSV and target LinkedIn natively"
• "LinkedIn native audience from this CSV"
• The user attached a CSV of companies AND asked for LinkedIn-native targeting (employees / revenues / job titles / skills resolved via LinkedIn).
WHEN NOT TO USE:
• If the user asked for a plain "CSV Upload - Accounts" → use `upload_account_list_csv_audience` (creates FIRMOGRAPHIC_INCLUDE, NOT LinkedIn-native).
• If the user asked for "Native Criteria - LinkedIn" without a CSV → use `create_linkedin_native_criteria_audience`.
TWO WAYS TO SUPPLY THE ACCOUNT LIST — provide EXACTLY ONE of:
• `companies`: inline `{<companyname>: <companywebsite>}` map (short ad-hoc lists).
• `companies_source_csv_url`: URL of a CSV with header `companyname,companywebsite` (case-insensitive). The MCP server downloads, validates, and uploads it as a native ABM list.
CRITERIA (all optional, LinkedIn-native shapes resolved server-side):
• employees — LinkedIn employee ranges (e.g. "201-500", "501-1000").
• revenues — LinkedIn revenue ranges (e.g. "$1M-$10M").
• company_names — free-text company names (resolved to LinkedIn IDs).
• location_country_ids — country IDs (e.g. 229=US).
• job_titles — free-text titles (resolved to LinkedIn IDs).
• skills — free-text skills (resolved to LinkedIn IDs).
RETURNS: id, audience_id, audience_name, audience_type (NATIVE_TARGETING_CSV), status, abmSearchCriteriaId, companies_count, upload_filename, counts.| Name | Required | Description | Default |
|---|---|---|---|
| skills | No | Free-text professional skills (resolved to LinkedIn skill IDs). Example: ['HubSpot', 'Salesforce'] | |
| revenues | No | LinkedIn revenue ranges for audience targeting. Valid values: Under $1M, $1M-$10M, $10M-$100M, $100M-$1B, $1B+. Example: ['$1M-$10M', '$10M-$100M'] | |
| companies | No | Inline map of company names to website URLs (optional). MUTUALLY EXCLUSIVE with `companies_source_csv_url`. Example: {"Acme Corp": "https://acme.com"} | |
| employees | No | LinkedIn employee count ranges for audience targeting. Valid values: 1, 2-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, +10001. Example: ['201-500', '501-1000'] | |
| job_titles | No | Free-text job titles (resolved to LinkedIn job-title IDs). Example: ['Software Engineer', 'Product Manager'] | |
| audience_name | Yes | Name for the new audience (required). | |
| company_names | No | Free-text company names (resolved to LinkedIn company IDs). Example: ['Metadata', 'Google'] | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| companies_source_csv_url | No | Public URL of a CSV with header EXACTLY `companyname,companywebsite` (case-insensitive). Use when the user attached a CSV to the chat — the URL comes via `AudienceBrief.attached_file_urls`. MUTUALLY EXCLUSIVE with `companies`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, openWorldHint=true, and destructiveHint=false, which the description does not contradict. The description adds context beyond annotations by explaining the server-side two-step flow (CSV upload as NATIVE ABM list, then audience creation) and the integration prerequisite. It does not describe side effects like reversibility or data retention, but that is minor given the write operation is clearly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headings and bullet points, making it scannable. Every section contributes necessary information: audience type, prerequisites, usage boundaries, list options, criteria, and return values. It is verbose due to complexity but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 9 parameters with 100% schema coverage, 1 required, and no output schema, the description covers all critical aspects: how to provide the account list, the criteria options, the server-side flow, prerequisites, and return fields. No missing information that an agent would need to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by explicitly stating the two ways to supply the account list (companies vs companies_source_csv_url) and that exactly one must be provided, plus clarifying criteria are optional and resolved server-side. This goes beyond the schema descriptions, warranting a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it creates a CSV Upload - LinkedIn Native audience, specifies the exact platform enum (NATIVE_TARGETING_CSV), and differentiates from siblings like upload_account_list_csv_audience and create_linkedin_native_criteria_audience. The verb 'Create' and resource are explicit and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a dedicated 'WHEN TO USE' section with exact user phrasing examples and a 'WHEN NOT TO USE' section that names alternative tools and conditions. This provides explicit routing guidance that an agent can act on without inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_facebook_native_criteria_audienceCreate Facebook Native Criteria AudienceAInspect
Create a Facebook native criteria audience using Facebook-supported targeting criteria. Build audiences based on Facebook native industries, geographic location, job titles, interests, and age range.
ESTIMATE-ONLY MODE:
Pass estimate_only=true to preview audience size WITHOUT creating the audience. In this mode the tool
returns expectedNumberOfContacts. Default is false.
ALSO KNOWN AS: Facebook audience, FB criteria audience, native Facebook targeting, Facebook lead audience
KEYWORDS: Facebook, native, criteria, audience, industry, location, job title, interest, age, lead, targeting
WHEN TO USE:
- Create targeted Facebook audiences using native Facebook criteria
- Target users by Facebook industry categories (e.g., IT and Technical Services, Sales, Management)
- Target by geographic countries, job titles, interests, and age range
- Build lead generation audiences for Facebook campaigns
INDUSTRIES:
Facebook native industry categories - provide the industry name as a string:
Administrative Services, Architecture and Engineering, Arts Entertainment Sports and Media,
Business and Finance, Business decision maker titles and interests, Cleaning and Maintenance Services,
Community and Social Services, Computation and Mathematics, Construction and Extraction,
Education and Libraries, Farming Fishing and Forestry, Food and Restaurants,
Government Employees (Global), Healthcare and Medical Services, Installation and Repair Services,
IT and Technical Services, Large business-to-business enterprise employees (500+ employees),
Legal Services, Life Physical and Social Sciences, Management,
Medium business-to-business enterprise employees (200 - 500 employees), Production, Sales,
Small business-to-business enterprise employees (10-200 employees), Transportation and Moving
PARAMETERS:
- name: Audience name (required)
- min_age: Minimum age for targeting (required) - must be between 21 and 65
- max_age: Maximum age for targeting (required) - must be between 21 and 65, and >= min_age
- industries: Array of Facebook native industry names (optional)
- countries: List of country names for location targeting (optional) - each must match a country from the platform's supported countries list
- job_titles: Array of free-text job title strings (optional) - e.g., ["Software Engineer", "Product Owner"]
- interests: Array of free-text interest strings (optional) - e.g., ["Java", "Python", "Cloud Computing"]
RETURNS:
Parsed audience criteria with resolved Facebook reference IDs and validated parameters.
IMPORTANT NOTES:
- name, min_age and max_age are required, all other parameters are optional
- Industries must be valid Facebook native industry names from the enum list
- Countries must be valid country names from the platform's supported countries list
- min_age and max_age must both be between 21 and 65, with min_age <= max_age
- Job titles and interests are free-text arrays
- Job titles and interests are validated by the backend API with the regex pattern [A-Za-z0-9 ]+ (only ASCII letters, digits, and spaces are allowed). Non-ASCII characters, hyphens, and special characters will be automatically replaced with spaces before resolving references (e.g., "co-founder" becomes "co founder"). When providing job titles or interests, use only alphanumeric characters and spaces.| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required). | |
| max_age | Yes | Maximum age for audience targeting. Must be between 21 and 65, and greater than or equal to min_age. | |
| min_age | Yes | Minimum age for audience targeting. Must be between 21 and 65, and less than or equal to max_age. | |
| countries | No | List of country names to target. Each must be a valid country name (e.g., ['United States', 'Brazil']). Resolved to platform country IDs before submission. | |
| interests | No | Free-text interest strings for targeting. Example: ['Java', 'Python', 'Cloud Computing', 'Machine Learning'] | |
| industries | No | Facebook native industry categories for audience targeting. Valid values: Administrative Services, Architecture and Engineering, Arts, Entertainment, Sports and Media, Business and Finance, Business decision maker titles and interests, Cleaning and Maintenance Services, Community and Social Services, Computation and Mathematics, Construction and Extraction, Education and Libraries, Farming, Fishing and Forestry, Food and Restaurants, Government Employees (Global), Healthcare and Medical Services, Installation and Repair Services, IT and Technical Services, Large business-to-business enterprise employees (500+ employees), Legal Services, Life, Physical and Social Sciences, Management, Medium business-to-business enterprise employees (200 - 500 employees), Production, Sales, Small business-to-business enterprise employees (10-200 employees), Transportation and Moving. Example: ['IT and Technical Services', 'Sales'] | |
| job_titles | No | Free-text job title strings for targeting. Example: ['Software Engineer', 'Senior Developer', 'Product Owner'] | |
| estimate_only | No | If true, do NOT create the audience — only estimate its size and return the expected contact count. Use this when the user wants to preview Facebook audience size before committing. Defaults to false (audience is created). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate it's a write operation (readOnlyHint=false) and non-destructive (destructiveHint=false). The description adds valuable behavioral context: estimate_only mode that avoids creation, regex-based validation with automatic replacement of special characters in job titles/interests, and return of resolved Facebook reference IDs. This goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized into labeled sections (ESTIMATE-ONLY MODE, WHEN TO USE, PARAMETERS, IMPORTANT NOTES). It front-loads the core purpose and then provides necessary details. While verbose, each section serves a purpose and avoids redundancy with the schema, though the full industry list is repeated in both schema and description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 8 parameters, 3 required, and no output schema, the description covers all necessary context: required vs optional fields, constraints, validation rules, the estimate-only behavior, and what the return value contains. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds substantial meaning: it clarifies age bounds (21–65), lists valid industry names, explains the regex pattern and character replacement for free-text fields, and notes that countries must match the supported list. This is genuine added value beyond the schema's basic descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (create), the resource (Facebook native criteria audience), and the targeting dimensions (industries, location, job titles, interests, age). It distinguishes from sibling tools like create_linkedin_native_criteria_audience by explicitly focusing on Facebook. The 'ALSO KNOWN AS' and 'KEYWORDS' reinforce its identity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a 'WHEN TO USE' section listing specific use cases (target by Facebook industry, country, job title, etc.) and explains the estimate_only mode for previewing without creation. However, it doesn't explicitly contrast with alternative audience creation tools (e.g., create_bombora_audience) or state when NOT to use it, so it falls just short of full differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_firmographic_audienceCreate Firmographic AudienceAInspect
Create B2B company firmographic audiences for targeted advertising campaigns. Build audiences based on company attributes (industry, size, revenue) and contact-level criteria.
ESTIMATE-ONLY MODE:
Pass estimate_only=true to preview audience size (companies + contacts) WITHOUT creating the audience.
In this mode the tool returns expectedNumberOfCompanies,
expectedNumberOfContacts, and cappedContactCount. Default is false (audience is created).
PREFERRED AUDIENCE TYPE:
This is the DEFAULT and most commonly used audience type on the Metadata platform.
When the user asks to create an audience without specifying a type, prefer this tool.
Only suggest Bombora audiences if get_intent_topics returns available topics.
Only suggest G2 audiences if G2 is confirmed as connected via get_integrations_status
and the user specifically requests G2 targeting.
ALSO KNOWN AS: company audience, target companies, B2B audience, business targeting, account-based audience, ABM list, company targeting
KEYWORDS: company, companies, audience, target, targeting, B2B, business, firmographic, industry, size, employees, revenue, ABM, account-based, LinkedIn, Facebook
WHEN TO USE:
- Default choice when the user wants to create a B2B audience
- Create targeted B2B audiences for LinkedIn, Facebook campaigns
- Target companies by industry, size, revenue
- Target contacts by seniority level and job function
- Set geographic targeting and contact limits per company
TARGETING OPTIONS:
- Industries: Use industry IDs. Examples:
1=Defense & Space, 4=Computer Software, 6=Internet, 7=Semiconductors, 8=Telecommunications,
11=Management Consulting, 12=Biotechnology, 41=Banking, 42=Insurance, 43=Financial Services,
80=Marketing & Advertising, 96=Information Technology & Services, more values in detail in the input schema
- Employees: "0 - 9", "10 - 49", "50 - 199", "200 - 499", "500 - 999", "1,000 - 4,999", "5,000 - 9,999", "10,000+"
- Revenue: "$1M - $10M", "$10M - $50M", "$50M - $100M", "$100M - $200M", "$500M - $1B", "$1B+"
CONTACTS CRITERIA:
Use the following parameters to filter and target specific contacts within accounts:
GEOGRAPHIC TARGETING:
location_country_ids: Array of country IDs (e.g., [29] for Brazil, [229] for United States)
location_state_ids: Array of state IDs (e.g., [5] for California, [32] for New York)
JOB TITLES:
job_title_includes: Array of free text strings to include (e.g., ["Software Engineer", "Manager"])
job_title_excludes: Array of free text strings to exclude (e.g., ["Senior", "Lead"])
JOB FUNCTIONS: Valid job function IDs and their labels:
1: Marketing, 2: Sales, 3: Customer Service, 4: Finance, 5: Human Resources, 6: Public Relations
7: Media, 8: Design, 9: Engineering, 10: Operations, 11: Legal, 12: Education
13: Health, 14: Real Estate, 15: Accounting, 16: Administrative, 17: Business Development
18: Community and Social Services, 19: Consulting, 20: Entrepreneurship, 21: Information Technology
22: Military and Protective Services, 23: Product Management, 24: Program and Project Management
25: Purchasing, 26: Quality Assurance, 27: Research, 28: Trades
job_function_include_ids: Array of job function IDs to include (e.g., [9] for Engineering)
job_function_exclude_ids: Array of job function IDs to exclude
SENIORITY LEVELS: Valid seniority IDs and their labels:
2: Manager, 3: Director, 4: VP, 5: CXO, 6: Unpaid, 7: Training
8: Senior, 9: Owner, 10: Entry, 11: Partner
seniority_include_ids: Array of seniority level IDs to include (e.g., [10, 7] for Entry and Training)
seniority_exclude_ids: Array of seniority level IDs to exclude
CONTACT LIMITS:
contacts_per_company_limit: Maximum number of contacts to target per company (optional). Example: 20
USAGE NOTES:
All ID fields (countries, states, job functions, seniorities) use numeric IDs from the platform
Job titles are free text strings, not IDs
Use include parameters to specify which criteria to target
Use exclude parameters to filter out contacts matching specific criteria
Combine multiple criteria for precise targeting (e.g., Senior Engineers in California)
Criteria are combined with AND logic, so all conditions must be met
CONTACTS CRITERIA PARAMETERS(Usually after other initial audience parameters to be described next):
location_country_ids: Array of country IDs (optional)
location_state_ids: Array of state IDs (optional)
job_title_includes: Array of job title keywords to include (optional)
job_title_excludes: Array of job title keywords to exclude (optional)
job_function_include_ids: Array of job function IDs (optional)
job_function_exclude_ids: Array of job function IDs (optional)
seniority_include_ids: Array of seniority level IDs (optional)
seniority_exclude_ids: Array of seniority level IDs (optional)
contacts_per_company_limit: Maximum contacts per company (optional)
PARAMETERS: - name: Audience name (required) - **IMPORTANT: Name MUST NOT exceed 50 characters. This is a mandatory requirement.** - industries: Array of industry IDs (optional) - employees: Array of employee count ranges (optional) - revenue: Array of revenue ranges (optional) RETURNS: Audience details with ID, size estimation, and creation status. COMMON USE CASES: - Target software companies with 50-500 employees - Find companies in specific industries with revenue ranges - Build audiences with contact-level filtering (seniority, job function, location) - Combine firmographic and contact criteria for precise B2B targeting IMPORTANT NOTES: - **CRITICAL: Audience name MUST NOT exceed 50 characters - this is mandatory and will cause creation to fail if exceeded** - name is the only required parameter - All other parameters are optional for flexible audience creation - Contact criteria fields work the same as in G2 metadata dynamic audiences - Audience size depends on firmographic filters and applied contacts criteria
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required) | |
| revenue | No | Revenue ranges. Valid enum values: LESS_THAN_1M ($0-$1M), FROM_1M_TO_10M ($1M-$10M), FROM_10M_TO_50M ($10M-$50M), FROM_50M_TO_100M ($50M-$100M), FROM_100M_TO_200M ($100M-$200M), FROM_200M_TO_500M ($200M-$500M), FROM_500M_TO_1000M ($500M-$1B), OVER_1000M ($1B+) | |
| employees | No | Employee count ranges. Valid enum values: LESS_THAN_10 (0-9), FROM_10_TO_50 (10-49), FROM_50_TO_200 (50-199), FROM_200_TO_500 (200-499), FROM_500_TO_1000 (500-999), FROM_1000_TO_5000 (1,000-4,999), FROM_5000_TO_10000 (5,000-9,999), OVER_10000 (10,000+) | |
| industries | No | Industry IDs for firmographic/technographic filtering (optional). Valid IDs: 1=Defense & Space, 3=Computer Hardware, 4=Computer Software, 5=Computer Networking, 6=Internet, 7=Semiconductors, 8=Telecommunications, 9=Law Practice, 10=Legal Services, 11=Management Consulting, 12=Biotechnology, 13=Medical Practice, 14=Hospital & Health Care, 15=Pharmaceuticals, 16=Veterinary, 17=Medical Device, 18=Cosmetics, 19=Apparel & Fashion, 20=Sporting Goods, 21=Tobacco, 22=Supermarkets, 23=Food Production, 24=Consumer Electronics, 25=Consumer Goods, 26=Furniture, 27=Retail, 28=Entertainment, 29=Gambling & Casinos, 30=Leisure, Travel & Tourism, 31=Hospitality, 32=Restaurants, 33=Sports, 34=Food & Beverages, 35=Motion Pictures & Film, 36=Broadcast Media, 37=Museums & Institutions, 38=Fine Art, 39=Performing Arts, 40=Recreational Facilities & Services, 41=Banking, 42=Insurance, 43=Financial Services, 44=Real Estate, 45=Investment Banking, 46=Investment Management, 47=Accounting, 48=Construction, 49=Building Materials, 50=Architecture & Planning, 51=Civil Engineering, 52=Aviation & Aerospace, 53=Automotive, 54=Chemicals, 55=Machinery, 56=Mining & Metals, 57=Oil & Energy, 58=Shipbuilding, 59=Utilities, 60=Textiles, 61=Paper & Forest Products, 62=Railroad Manufacture, 63=Farming, 64=Ranching, 65=Dairy, 66=Fishery, 67=Primary/Secondary Education, 68=Higher Education, 69=Education Management, 70=Research, 71=Military, 72=Legislative Office, 73=Judiciary, 74=International Affairs, 75=Government Administration, 76=Executive Office, 77=Law Enforcement, 78=Public Safety, 79=Public Policy, 80=Marketing & Advertising, 81=Newspapers, 82=Publishing, 83=Printing, 84=Information Services, 85=Libraries, 86=Environmental Services, 87=Package/Freight Delivery, 88=Individual & Family Services, 89=Religious Institutions, 90=Civic & Social Organization, 91=Consumer Services, 92=Transportation/Trucking/Railroad, 93=Warehousing, 94=Airlines/Aviation, 95=Maritime, 96=Information Technology & Services, 97=Market Research, 98=Public Relations & Communications, 99=Design, 100=Non-profit Organization Management, 101=Fundraising, 102=Program Development, 103=Writing & Editing, 104=Staffing & Recruiting, 105=Professional Training & Coaching, 106=Venture Capital & Private Equity, 107=Political Organization, 108=Translation & Localization, 109=Computer Games, 110=Events Services, 111=Arts & Crafts, 112=Electrical & Electronic Manufacturing, 113=Online Media, 114=Nanotechnology, 115=Music, 116=Logistics & Supply Chain, 117=Plastics, 118=Computer & Network Security, 119=Wireless, 120=Alternative Dispute Resolution, 121=Security & Investigations, 122=Facilities Services, 123=Outsourcing/Offshoring, 124=Health, Wellness & Fitness, 125=Alternative Medicine, 126=Media Production, 127=Animation, 128=Commercial Real Estate, 129=Capital Markets, 130=Think Tanks, 131=Philanthropy, 132=E-learning, 133=Wholesale, 134=Import & Export, 135=Mechanical Or Industrial Engineering, 136=Photography, 137=Human Resources, 138=Business Supplies & Equipment, 139=Mental Health Care, 140=Graphic Design, 141=International Trade & Development, 142=Wine & Spirits, 143=Luxury Goods & Jewelry, 144=Renewables & Environment, 145=Glass, Ceramics & Concrete, 146=Packaging & Containers, 147=Industrial Automation, 148=Government Relations. Example: [4, 96, 11] for Software, IT Services, Consulting | |
| estimate_only | No | If true, do NOT create the audience — only estimate its size and return the counts. Use this when the user wants to preview how many companies/contacts match the criteria before committing. Defaults to false (audience is created). | |
| job_title_excludes | No | Free text keywords for job titles to exclude (optional). Example: ['Senior', 'Lead'] | |
| job_title_includes | No | Free text keywords for job titles to include (optional). Example: ['Software Engineer', 'Manager'] | |
| location_state_ids | No | State IDs for geographic targeting (optional). Valid US State IDs: 1 (Alabama), 2 (Alaska), 3 (Arizona), 4 (Arkansas), 5 (California), 6 (Colorado), 7 (Connecticut), 8 (Delaware), 9 (Florida), 10 (Georgia), 11 (Hawaii), 12 (Idaho), 13 (Illinois), 14 (Indiana), 15 (Iowa), 16 (Kansas), 17 (Kentucky), 18 (Louisiana), 19 (Maine), 20 (Maryland), 21 (Massachusetts), 22 (Michigan), 23 (Minnesota), 24 (Mississippi), 25 (Missouri), 26 (Montana), 27 (Nebraska), 28 (Nevada), 29 (New Hampshire), 30 (New Jersey), 31 (New Mexico), 32 (New York), 33 (North Carolina), 34 (North Dakota), 35 (Ohio), 36 (Oklahoma), 37 (Oregon), 38 (Pennsylvania), 39 (Rhode Island), 40 (South Carolina), 41 (South Dakota), 42 (Tennessee), 43 (Texas), 44 (Utah), 45 (Vermont), 46 (Virginia), 47 (Washington), 48 (West Virginia), 49 (Wisconsin), 50 (Wyoming), 52 (District of Columbia). Example: [5] for California, [32] for New York | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| seniority_exclude_ids | No | Seniority level IDs to exclude (optional). Valid IDs: 2-11 as listed above | |
| seniority_include_ids | No | Seniority level IDs to include (optional). Valid IDs: 2 (Manager), 3 (Director), 4 (VP), 5 (CXO), 6 (Unpaid), 7 (Training), 8 (Senior), 9 (Owner), 10 (Entry), 11 (Partner). Example: [10, 7] for Entry and Training | |
| job_function_exclude_ids | No | Job function IDs to exclude (optional). Valid IDs: 1-28 as listed above | |
| job_function_include_ids | No | Job function IDs to include (optional). Valid IDs: 1 (Marketing), 2 (Sales), 3 (Customer Service), 4 (Finance), 5 (HR), 6 (PR), 7 (Media), 8 (Design), 9 (Engineering), 10 (Operations), 11 (Legal), 12 (Education), 13 (Health), 14 (Real Estate), 15 (Accounting), 16 (Administrative), 17 (Business Development), 18 (Community Services), 19 (Consulting), 20 (Entrepreneurship), 21 (IT), 22 (Military Services), 23 (Product Management), 24 (Program/Project Management), 25 (Purchasing), 26 (QA), 27 (Research), 28 (Trades). Example: [9] for Engineering | |
| contacts_per_company_limit | No | Maximum number of contacts to target per company (optional). Example: 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations indicating openWorldHint=true and destructiveHint=false, the description provides substantial behavioral context: estimate_only mode prevents creation, name length constraint (50 chars) is mandatory, AND logic for combining criteria, and note that contact criteria work like G2 audiences. These go beyond annotations and add critical operational details. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long, but nearly every section serves a purpose: targeting options with enumerations, parameter examples, usage notes, and important caveats. It is logically structured with clear headings (e.g., ESTIMATE-ONLY MODE, PREFERRED AUDIENCE TYPE, CONTACTS CRITERIA). Some redundancy exists (e.g., CONTACTS CRITERIA section is repeated twice, name length mentioned twice), which prevents a perfect score, but it remains well-organized and front-loaded with key differentiators.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's high complexity (14 parameters) and no output schema, the description is exceptionally comprehensive. It covers all parameter domains with examples and valid values, explains special modes (estimate_only), provides routing to alternatives, and anticipates common use cases. An agent has everything needed to correctly invoke the tool. Minor missing information about pagination or error handling is negligible given the exhaustive detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema coverage is 100%, but the description adds immense value by providing human-readable labels for all enums (e.g., '$1M - $10M' for FROM_1M_TO_10M, '0-9' for LESS_THAN_10), industry IDs and their names, job function IDs with labels, seniority IDs with labels, and country/state ID examples. This goes far beyond the schema's descriptions, enhancing understanding and correct usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: creating B2B firmographic audiences for advertising campaigns, with specific attributes (industry, size, revenue) and contact-level criteria. It distinguishes itself from siblings by explicitly noting it is the default and most commonly used audience type, and it provides alternatives (Bombora, G2) with conditions. This goes beyond a generic verb+resource and is specific enough for an agent to differentiate without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a clear WHEN TO USE section and explicitly states when to prefer alternatives: 'Only suggest Bombora audiences if get_intent_topics returns available topics' and 'Only suggest G2 audiences if G2 is confirmed as connected via get_integrations_status'. This is explicit guidance on when not to use this tool and when to use siblings, making it exemplary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_g2_intent_dynamic_audienceCreate G2 Intent (Dynamic) AudienceAInspect
Create a G2 Intent (Dynamic) audience (platform customAudienceType=DYNAMIC_G2_CONTACT).
AUDIENCE TYPE (mirrors the UI's "Audience Type" dropdown):
• UI label: "G2 Intent (Dynamic)"
• Platform enum: DYNAMIC_G2_CONTACT
• Refreshes daily as G2 intent signals update; uses generic contact criteria (not LinkedIn-native).
PREREQUISITE:
• G2 integration MUST be connected. If not, do NOT call this tool — recommend `create_firmographic_audience`.
WHEN TO USE (exact user phrasing this tool should match):
• "G2 Intent (Dynamic)" (without "LinkedIn Native")
• "G2 intent dynamic audience"
• "Dynamic G2 audience"
• The user wants G2 intent that refreshes daily on Facebook/LinkedIn/other channels (not specifically LinkedIn-native).
WHEN NOT TO USE:
• If the user said "LinkedIn Native" → use `create_g2_intent_linkedin_native_dynamic_audience`.
• If the user said "Static" → use `create_g2_intent_static_audience`.
BUYING STAGES — REQUIRED BY THE PLATFORM:
Same as the LinkedIn Native variant: ASK the user if missing. DO NOT default.
CONTACTS CRITERIA:
Use the following parameters to filter and target specific contacts within accounts:
GEOGRAPHIC TARGETING:
location_country_ids: Array of country IDs (e.g., [29] for Brazil, [229] for United States)
location_state_ids: Array of state IDs (e.g., [5] for California, [32] for New York)
JOB TITLES:
job_title_includes: Array of free text strings to include (e.g., ["Software Engineer", "Manager"])
job_title_excludes: Array of free text strings to exclude (e.g., ["Senior", "Lead"])
JOB FUNCTIONS: Valid job function IDs and their labels:
1: Marketing, 2: Sales, 3: Customer Service, 4: Finance, 5: Human Resources, 6: Public Relations
7: Media, 8: Design, 9: Engineering, 10: Operations, 11: Legal, 12: Education
13: Health, 14: Real Estate, 15: Accounting, 16: Administrative, 17: Business Development
18: Community and Social Services, 19: Consulting, 20: Entrepreneurship, 21: Information Technology
22: Military and Protective Services, 23: Product Management, 24: Program and Project Management
25: Purchasing, 26: Quality Assurance, 27: Research, 28: Trades
job_function_include_ids: Array of job function IDs to include (e.g., [9] for Engineering)
job_function_exclude_ids: Array of job function IDs to exclude
SENIORITY LEVELS: Valid seniority IDs and their labels:
2: Manager, 3: Director, 4: VP, 5: CXO, 6: Unpaid, 7: Training
8: Senior, 9: Owner, 10: Entry, 11: Partner
seniority_include_ids: Array of seniority level IDs to include (e.g., [10, 7] for Entry and Training)
seniority_exclude_ids: Array of seniority level IDs to exclude
CONTACT LIMITS:
contacts_per_company_limit: Maximum number of contacts to target per company (optional). Example: 20
USAGE NOTES:
All ID fields (countries, states, job functions, seniorities) use numeric IDs from the platform
Job titles are free text strings, not IDs
Use include parameters to specify which criteria to target
Use exclude parameters to filter out contacts matching specific criteria
Combine multiple criteria for precise targeting (e.g., Senior Engineers in California)
Criteria are combined with AND logic, so all conditions must be met
CONTACTS CRITERIA PARAMETERS(Usually after other initial audience parameters to be described next):
location_country_ids: Array of country IDs (optional)
location_state_ids: Array of state IDs (optional)
job_title_includes: Array of job title keywords to include (optional)
job_title_excludes: Array of job title keywords to exclude (optional)
job_function_include_ids: Array of job function IDs (optional)
job_function_exclude_ids: Array of job function IDs (optional)
seniority_include_ids: Array of seniority level IDs (optional)
seniority_exclude_ids: Array of seniority level IDs (optional)
contacts_per_company_limit: Maximum contacts per company (optional)
PARAMETERS: • name (required, ≤ 50 chars) • intent_days (required, 1-365) • buying_stages (REQUIRED by platform — ask if missing) • Contact criteria as in CONTACTS CRITERIA above. RETURNS: id, audience_id, audience_name, audience_type (DYNAMIC_G2_CONTACT), status, buying_stages, intent_days, counts.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required, max 50 characters). | |
| intent_days | Yes | Days to look back for G2 intent signals (required, 1-365). | |
| buying_stages | No | Buying stages to target. The platform REQUIRES at least one; if the user did not specify, ASK them before calling — do NOT default. | |
| job_title_excludes | No | Free text keywords for job titles to exclude (optional). Example: ['Senior', 'Lead'] | |
| job_title_includes | No | Free text keywords for job titles to include (optional). Example: ['Software Engineer', 'Manager'] | |
| location_state_ids | No | State IDs for geographic targeting (optional). Valid US State IDs: 1 (Alabama), 2 (Alaska), 3 (Arizona), 4 (Arkansas), 5 (California), 6 (Colorado), 7 (Connecticut), 8 (Delaware), 9 (Florida), 10 (Georgia), 11 (Hawaii), 12 (Idaho), 13 (Illinois), 14 (Indiana), 15 (Iowa), 16 (Kansas), 17 (Kentucky), 18 (Louisiana), 19 (Maine), 20 (Maryland), 21 (Massachusetts), 22 (Michigan), 23 (Minnesota), 24 (Mississippi), 25 (Missouri), 26 (Montana), 27 (Nebraska), 28 (Nevada), 29 (New Hampshire), 30 (New Jersey), 31 (New Mexico), 32 (New York), 33 (North Carolina), 34 (North Dakota), 35 (Ohio), 36 (Oklahoma), 37 (Oregon), 38 (Pennsylvania), 39 (Rhode Island), 40 (South Carolina), 41 (South Dakota), 42 (Tennessee), 43 (Texas), 44 (Utah), 45 (Vermont), 46 (Virginia), 47 (Washington), 48 (West Virginia), 49 (Wisconsin), 50 (Wyoming), 52 (District of Columbia). Example: [5] for California, [32] for New York | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| seniority_exclude_ids | No | Seniority level IDs to exclude (optional). Valid IDs: 2-11 as listed above | |
| seniority_include_ids | No | Seniority level IDs to include (optional). Valid IDs: 2 (Manager), 3 (Director), 4 (VP), 5 (CXO), 6 (Unpaid), 7 (Training), 8 (Senior), 9 (Owner), 10 (Entry), 11 (Partner). Example: [10, 7] for Entry and Training | |
| job_function_exclude_ids | No | Job function IDs to exclude (optional). Valid IDs: 1-28 as listed above | |
| job_function_include_ids | No | Job function IDs to include (optional). Valid IDs: 1 (Marketing), 2 (Sales), 3 (Customer Service), 4 (Finance), 5 (HR), 6 (PR), 7 (Media), 8 (Design), 9 (Engineering), 10 (Operations), 11 (Legal), 12 (Education), 13 (Health), 14 (Real Estate), 15 (Accounting), 16 (Administrative), 17 (Business Development), 18 (Community Services), 19 (Consulting), 20 (Entrepreneurship), 21 (IT), 22 (Military Services), 23 (Product Management), 24 (Program/Project Management), 25 (Purchasing), 26 (QA), 27 (Research), 28 (Trades). Example: [9] for Engineering | |
| contacts_per_company_limit | No | Maximum number of contacts to target per company (optional). Example: 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a non-read-only, non-destructive operation, and the description adds important behavioral context: it requires the G2 integration to be connected, warns not to call if missing, and specifies that buying_stages is mandatory by the platform and must be asked if missing (do not default). It also discloses the daily refresh behavior and return fields, going beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (PURPOSE, PREREQUISITE, WHEN TO USE, WHEN NOT TO USE, CONTACTS CRITERIA, PARAMETERS, RETURNS) but it is overly verbose. There is redundancy: the 'CONTACTS CRITERIA PARAMETERS' section repeats the parameter list that already appears in the earlier CONTACTS CRITERIA section and in the schema. This duplication could be trimmed without loss of information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description explicitly lists the return fields (id, audience_id, audience_name, audience_type, status, buying_stages, intent_days, counts). It covers all 12 parameters, explains prerequisites, platform requirements, and usage notes, making it fully complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds significant value by enumerating all valid job function IDs, seniority IDs, country IDs, and state IDs in a readable format, and by explaining usage notes (AND logic, free text vs IDs, include/exclude semantics). This goes beyond the schema's bare descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Create a G2 Intent (Dynamic) audience') with the exact platform enum (DYNAMIC_G2_CONTACT) and distinguishes it from the LinkedIn Native and Static sibling tools by name. The purpose is unmistakable and clearly differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'WHEN TO USE' and 'WHEN NOT TO USE' sections provide exact user phrasings and name the alternative tools (create_g2_intent_linkedin_native_dynamic_audience, create_g2_intent_static_audience). It also states a prerequisite (G2 integration must be connected) and instructs to recommend create_firmographic_audience if not, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_g2_intent_linkedin_native_dynamic_audienceCreate G2 Intent - LinkedIn Native (Dynamic) AudienceAInspect
Create a G2 Intent - LinkedIn Native (Dynamic) audience (platform customAudienceType=DYNAMIC_G2).
AUDIENCE TYPE (mirrors the UI's "Audience Type" dropdown):
• UI label: "G2 Intent - LinkedIn Native (Dynamic)"
• Platform enum: DYNAMIC_G2
• Refreshes daily as G2 intent signals update; targets LinkedIn natively.
PREREQUISITE:
• Both G2 and LinkedIn integrations MUST be connected. If either is missing, do NOT call this tool — recommend `create_firmographic_audience` instead.
WHEN TO USE (exact user phrasing this tool should match):
• "G2 Intent - LinkedIn Native (Dynamic)"
• "G2 LinkedIn Native Dynamic"
• "LinkedIn native G2 intent audience"
• The user explicitly mentions BOTH G2 intent AND LinkedIn native targeting.
WHEN NOT TO USE:
• If the user asked for "G2 Intent (Dynamic)" without "LinkedIn Native" → use `create_g2_intent_dynamic_audience`.
• If the user asked for "G2 Intent (Static)" → use `create_g2_intent_static_audience`.
BUYING STAGES — REQUIRED BY THE PLATFORM:
The platform UI marks Buying Stages as required. If the user did not name any stages, STOP and ask the user which of AWARENESS / CONSIDERATION / DECISION to target. DO NOT silently default — that produced wrong audiences in PRD-29702 / PRD-29703.
CRITERIA (LinkedIn-native shapes; free-text fields are resolved server-side via the LinkedIn references API):
• employees — LinkedIn-native employee ranges. Valid labels: see the schema (e.g. "201-500", "501-1000", "1001-5000").
• revenues — LinkedIn-native revenue ranges (e.g. "$1M-$10M", "$10M-$100M").
• company_names — free-text company names (resolved to LinkedIn company IDs).
• location_country_ids — country IDs (e.g. 229=US, 228=UK).
• job_titles — free-text titles (resolved to LinkedIn job-title IDs).
• skills — free-text professional skills (resolved to LinkedIn skill IDs).
PARAMETERS:
• name (required, ≤ 50 chars)
• intent_days (required, 1-365)
• buying_stages (REQUIRED by platform — ask the user if missing; do NOT default)
• employees, revenues, company_names, location_country_ids, job_titles, skills (all optional)
RETURNS: id, audience_id, audience_name, audience_type (DYNAMIC_G2), status, buying_stages, intent_days, expectedNumberOfCompanies, expectedNumberOfContacts.| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required, max 50 characters). | |
| skills | No | Free-text professional skills (resolved to LinkedIn skill IDs). Example: ['HubSpot', 'Salesforce', 'Python'] | |
| revenues | No | LinkedIn revenue ranges for audience targeting. Valid values: Under $1M, $1M-$10M, $10M-$100M, $100M-$1B, $1B+. Example: ['$1M-$10M', '$10M-$100M'] | |
| employees | No | LinkedIn employee count ranges for audience targeting. Valid values: 1, 2-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, +10001. Example: ['201-500', '501-1000'] | |
| job_titles | No | Free-text job titles (resolved to LinkedIn job-title IDs). Example: ['Software Engineer', 'Product Manager'] | |
| intent_days | Yes | Days to look back for G2 intent signals (required, 1-365). | |
| buying_stages | No | Buying stages to target. The platform REQUIRES at least one; if the user did not specify, ASK them before calling — do NOT default. | |
| company_names | No | Free-text company names to target (resolved server-side to LinkedIn company IDs). Example: ['Metadata', 'Google', 'Salesforce'] | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnly=false, openWorld=true, destructive=false, so the description carries the full burden of behavioral disclosure. It discloses the platform-required buying-stages constraint with a do-NOT-default instruction and PRD references, explains server-side resolution of free-text criteria via the LinkedIn references API, and notes daily refresh behavior. This goes well beyond the structured metadata.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (AUDIENCE TYPE, PREREQUISITE, WHEN TO USE, WHEN NOT TO USE, BUYING STAGES, CRITERIA, PARAMETERS, RETURNS). There is some redundancy—the parameter list largely repeats the schema, and the title is restated—but for a 9-parameter tool with sibling ambiguity, every major section earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and a complex 9-parameter tool, the description compensates fully: it lists the return fields, documents the user-phrasing triggers and exclusions, calls out the platform-required buying-stages trap with explicit 'ask the user' guidance, and explains how criteria fields are resolved. Nothing an agent needs to call and interpret the result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it flags `buying_stages` as REQUIRED by the platform even though the schema marks it optional, instructs asking the user rather than defaulting, and clarifies that free-text fields like `company_names` and `job_titles` are resolved server-side via the LinkedIn references API. These additions help an agent invoke parameters correctly, though not every parameter receives extra semantic value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pair: 'Create a **G2 Intent - LinkedIn Native (Dynamic)** audience' and names the platform enum `customAudienceType=DYNAMIC_G2`. It also differentiates from sibling tools through explicit 'WHEN NOT TO USE' guidance, so an agent can reliably select it over `create_g2_intent_dynamic_audience` and `create_g2_intent_static_audience`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an exhaustive usage contract: a prerequisite ('Both G2 and LinkedIn integrations MUST be connected'), exact user phrasing to match, and explicit exclusion rules naming the alternative tools. It even instructs the agent to avoid calling the tool and route to `create_firmographic_audience` if prerequisites are unmet, leaving no ambiguity about when to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_g2_intent_static_audienceCreate G2 Intent (Static) AudienceAInspect
Create a G2 Intent (Static) audience (platform customAudienceType=G2_ABM_CONTACT).
AUDIENCE TYPE (mirrors the UI's "Audience Type" dropdown):
• UI label: "G2 Intent (Static)"
• Platform enum: G2_ABM_CONTACT
• SNAPSHOT at creation time — does NOT refresh daily.
PREREQUISITE:
• G2 integration MUST be connected.
WHEN TO USE (exact user phrasing this tool should match):
• "G2 Intent (Static)"
• "Static G2 audience"
• The user explicitly wants the static / snapshot variant rather than the daily-refreshing dynamic one.
WHEN NOT TO USE:
• If the user said "Dynamic" → use `create_g2_intent_dynamic_audience` or `create_g2_intent_linkedin_native_dynamic_audience`.
BUYING STAGES — REQUIRED BY THE PLATFORM:
ASK the user if missing. DO NOT default.
CONTACTS CRITERIA:
Use the following parameters to filter and target specific contacts within accounts:
GEOGRAPHIC TARGETING:
location_country_ids: Array of country IDs (e.g., [29] for Brazil, [229] for United States)
location_state_ids: Array of state IDs (e.g., [5] for California, [32] for New York)
JOB TITLES:
job_title_includes: Array of free text strings to include (e.g., ["Software Engineer", "Manager"])
job_title_excludes: Array of free text strings to exclude (e.g., ["Senior", "Lead"])
JOB FUNCTIONS: Valid job function IDs and their labels:
1: Marketing, 2: Sales, 3: Customer Service, 4: Finance, 5: Human Resources, 6: Public Relations
7: Media, 8: Design, 9: Engineering, 10: Operations, 11: Legal, 12: Education
13: Health, 14: Real Estate, 15: Accounting, 16: Administrative, 17: Business Development
18: Community and Social Services, 19: Consulting, 20: Entrepreneurship, 21: Information Technology
22: Military and Protective Services, 23: Product Management, 24: Program and Project Management
25: Purchasing, 26: Quality Assurance, 27: Research, 28: Trades
job_function_include_ids: Array of job function IDs to include (e.g., [9] for Engineering)
job_function_exclude_ids: Array of job function IDs to exclude
SENIORITY LEVELS: Valid seniority IDs and their labels:
2: Manager, 3: Director, 4: VP, 5: CXO, 6: Unpaid, 7: Training
8: Senior, 9: Owner, 10: Entry, 11: Partner
seniority_include_ids: Array of seniority level IDs to include (e.g., [10, 7] for Entry and Training)
seniority_exclude_ids: Array of seniority level IDs to exclude
CONTACT LIMITS:
contacts_per_company_limit: Maximum number of contacts to target per company (optional). Example: 20
USAGE NOTES:
All ID fields (countries, states, job functions, seniorities) use numeric IDs from the platform
Job titles are free text strings, not IDs
Use include parameters to specify which criteria to target
Use exclude parameters to filter out contacts matching specific criteria
Combine multiple criteria for precise targeting (e.g., Senior Engineers in California)
Criteria are combined with AND logic, so all conditions must be met
CONTACTS CRITERIA PARAMETERS(Usually after other initial audience parameters to be described next):
location_country_ids: Array of country IDs (optional)
location_state_ids: Array of state IDs (optional)
job_title_includes: Array of job title keywords to include (optional)
job_title_excludes: Array of job title keywords to exclude (optional)
job_function_include_ids: Array of job function IDs (optional)
job_function_exclude_ids: Array of job function IDs (optional)
seniority_include_ids: Array of seniority level IDs (optional)
seniority_exclude_ids: Array of seniority level IDs (optional)
contacts_per_company_limit: Maximum contacts per company (optional)
PARAMETERS: • name (required, ≤ 50 chars) • intent_days (required, 1-365) • buying_stages (REQUIRED — ask if missing) • Contact criteria as in CONTACTS CRITERIA above. RETURNS: id, audience_id, audience_name, audience_type (G2_ABM_CONTACT), status, buying_stages, intent_days, counts.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required, max 50 characters). | |
| intent_days | Yes | Days to look back for G2 intent signals (required, 1-365). | |
| buying_stages | No | Buying stages to target. The platform REQUIRES at least one; if the user did not specify, ASK them before calling — do NOT default. | |
| job_title_excludes | No | Free text keywords for job titles to exclude (optional). Example: ['Senior', 'Lead'] | |
| job_title_includes | No | Free text keywords for job titles to include (optional). Example: ['Software Engineer', 'Manager'] | |
| location_state_ids | No | State IDs for geographic targeting (optional). Valid US State IDs: 1 (Alabama), 2 (Alaska), 3 (Arizona), 4 (Arkansas), 5 (California), 6 (Colorado), 7 (Connecticut), 8 (Delaware), 9 (Florida), 10 (Georgia), 11 (Hawaii), 12 (Idaho), 13 (Illinois), 14 (Indiana), 15 (Iowa), 16 (Kansas), 17 (Kentucky), 18 (Louisiana), 19 (Maine), 20 (Maryland), 21 (Massachusetts), 22 (Michigan), 23 (Minnesota), 24 (Mississippi), 25 (Missouri), 26 (Montana), 27 (Nebraska), 28 (Nevada), 29 (New Hampshire), 30 (New Jersey), 31 (New Mexico), 32 (New York), 33 (North Carolina), 34 (North Dakota), 35 (Ohio), 36 (Oklahoma), 37 (Oregon), 38 (Pennsylvania), 39 (Rhode Island), 40 (South Carolina), 41 (South Dakota), 42 (Tennessee), 43 (Texas), 44 (Utah), 45 (Vermont), 46 (Virginia), 47 (Washington), 48 (West Virginia), 49 (Wisconsin), 50 (Wyoming), 52 (District of Columbia). Example: [5] for California, [32] for New York | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| seniority_exclude_ids | No | Seniority level IDs to exclude (optional). Valid IDs: 2-11 as listed above | |
| seniority_include_ids | No | Seniority level IDs to include (optional). Valid IDs: 2 (Manager), 3 (Director), 4 (VP), 5 (CXO), 6 (Unpaid), 7 (Training), 8 (Senior), 9 (Owner), 10 (Entry), 11 (Partner). Example: [10, 7] for Entry and Training | |
| job_function_exclude_ids | No | Job function IDs to exclude (optional). Valid IDs: 1-28 as listed above | |
| job_function_include_ids | No | Job function IDs to include (optional). Valid IDs: 1 (Marketing), 2 (Sales), 3 (Customer Service), 4 (Finance), 5 (HR), 6 (PR), 7 (Media), 8 (Design), 9 (Engineering), 10 (Operations), 11 (Legal), 12 (Education), 13 (Health), 14 (Real Estate), 15 (Accounting), 16 (Administrative), 17 (Business Development), 18 (Community Services), 19 (Consulting), 20 (Entrepreneurship), 21 (IT), 22 (Military Services), 23 (Product Management), 24 (Program/Project Management), 25 (Purchasing), 26 (QA), 27 (Research), 28 (Trades). Example: [9] for Engineering | |
| contacts_per_company_limit | No | Maximum number of contacts to target per company (optional). Example: 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses that the audience is a snapshot at creation time and does not refresh daily, that the G2 integration must already be connected, and that the platform requires `buying_stages` with no defaulting. This gives the agent the non-obvious behavioral context needed for correct invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is heavily redundant: the CONTACTS CRITERIA section is followed by a nearly identical CONTACTS CRITERIA PARAMETERS section, and there is an internal author note ('Usually after other initial audience parameters to be described next') that is not useful to an AI agent. Although headings help, the duplication and unnecessary prose make it overly long and not appropriately sized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter creation tool with no output schema, the description is very complete: it lists prerequisites, buying-stage requirements, all contact criteria semantics, usage notes, AND logic, and the exact return fields. The agent has enough context to decide when to call it, fill parameters correctly, and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already covers all parameters, the description adds meaning by explaining include/exclude semantics, AND logic across criteria, numeric IDs versus free-text job titles, and examples like 'Senior Engineers in California'. It also clarifies that `buying_stages` is platform-required and must be requested from the user, which goes beyond the schema's static description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Create a G2 Intent (Static) audience' and gives the platform enum `customAudienceType=G2_ABM_CONTACT`, a specific verb and resource. It further differentiates from siblings by stating this is the snapshot variant that does not refresh daily and explicitly names `create_g2_intent_dynamic_audience` as the alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides an explicit 'WHEN TO USE' section with exact user phrasings like 'Static G2 audience' and a 'WHEN NOT TO USE' section naming the dynamic sibling tools. It also states the prerequisite that the G2 integration must be connected and instructs the agent to ask for `buying_stages` if missing rather than defaulting.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_business_logo_extensionCreate Google Ads Business Logo Extension (BETA)AInspect
Attach the business logo to a Google Ads text ad for brand recognition. BETA. References a single image-library asset (the logo) and optionally pairs it with the business name and domain (the latter two are also used when the same logo is reused for Microsoft Ads).
ALSO KNOWN AS: business logo, brand logo, logo, company logo, brand mark, mark, identity asset
KEYWORDS: logo, business logo, brand, brand mark, identity, company logo, brand recognition, BETA, google ads, extension
WHEN TO USE:
- "Add our business logo to our Google Ads"
- "Create a logo extension referencing image library ID 123"
- "Attach the Acme Corp logo to our search ads for brand lift"
WHEN NOT TO USE:
- Multiple product / lifestyle shots → use create_google_image_extension
- The logo is not yet in the image library — upload it first, then call this with the resulting ID.
- Same logo for Microsoft Ads / Bing → use create_microsoft_business_logo_extension
INPUTS:
- image_library_id (required): single image library ID pointing to the logo asset.
- business_name: business name displayed alongside the logo (≤25 chars). Required if the same library entry is also used for Microsoft Ads.
- domain_name: business domain (≤50 chars). Used by Microsoft Ads.
EXAMPLE:
create_google_business_logo_extension(
image_library_id=123,
business_name="Acme Corp",
domain_name="acme.com",
)| Name | Required | Description | Default |
|---|---|---|---|
| domain_name | No | ||
| business_name | No | ||
| image_library_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=true, so the agent knows this is a non-destructive creation operation. The description adds valuable context beyond annotations: the BETA status, that it references a single image-library asset, and that business_name/domain_name are reused for Microsoft Ads. It does not contradict annotations and enriches the behavioral profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than minimal but well-organized with clear section headers (WHEN TO USE, WHEN NOT TO USE, INPUTS, EXAMPLE). The core purpose is front-loaded, and the additional sections each add functional value. The 'ALSO KNOWN AS' and 'KEYWORDS' sections are somewhat redundant for agent use but do not harm clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 parameters, no output schema, and cross-platform implications (Microsoft Ads), the description covers prerequisites, exclusions, parameter semantics, and a worked example. Nothing essential for correct invocation is missing; the only potential gap is error handling or return behavior, but that is not specified in any schema and is reasonably omitted given the straightforward creation action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries full responsibility for explaining parameters. The INPUTS section defines each parameter's meaning, constraints (≤25 chars, ≤50 chars), and the conditional requirement for business_name when reusing the asset for Microsoft Ads. This goes well beyond the schema's type and maxLength, fully compensating for the zero schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool attaches a business logo to a Google Ads text ad, with the specific verb 'attach' and resource 'business logo extension'. It differentiates from siblings by explicitly naming create_google_image_extension and create_microsoft_business_logo_extension in the WHEN NOT TO USE section, so an agent can disambiguate without opening their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE and WHEN NOT TO USE sections provide explicit guidance: examples of natural-language triggers, exclusions for product/lifestyle images and Microsoft Ads, and a prerequisite (upload logo first). This leaves no ambiguity about when to invoke this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_callout_extensionCreate Google Ads Callout ExtensionAInspect
Add a short non-clickable selling-point snippet (callout) that appears beneath a Google Ads ad — short trust-builder phrases like "Free Shipping", "24/7 Support", "Money-Back Guarantee", or "No Setup Fees". Callouts reinforce value props without taking up headline space.
ALSO KNOWN AS: callout, callout extension, selling point, trust badge, value prop, value proposition, tagline, ad badge
KEYWORDS: callout, selling point, trust signal, value prop, badge, free shipping, money back, guarantee, support, no fees, google ads, extension
WHEN TO USE:
- "Add a 'Free Shipping' callout to our Google Ads library"
- "Create a callout for 24/7 support"
- "Register a new value-prop tag for the holiday campaigns"
- "I want a 'Money-Back Guarantee' badge to show under our ads"
WHEN NOT TO USE:
- Want a clickable shortcut to a landing page → use create_google_sitelink_extension
- Want a list of named items (e.g. "Brands: Nest, Nexus") → use create_google_structured_snippet_extension
- Same callout for Microsoft Ads / Bing → use create_microsoft_callout_extension
- Anything for Facebook / LinkedIn / Reddit — search-channel-only
INPUTS:
- callout_text: visible snippet (1-25 chars).
EXAMPLE:
create_google_callout_extension(callout_text="Free Shipping")| Name | Required | Description | Default |
|---|---|---|---|
| callout_text | Yes | Callout snippet. 1-25 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, so it's a mutation. The description adds behavioral context: the snippet is 'non-clickable', 'appears beneath an ad', and 'reinforces value props without taking up headline space'. It doesn't contradict annotations. It doesn't detail side effects like account prerequisites, but given the simple create action and annotation coverage, this is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (intro, synonyms, keywords, when to use, when not to use, inputs, example). It's longer than strictly necessary but each section adds value for routing and usage. The core purpose is front-loaded, and the rest is organized logically without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter and no output schema, this description is complete. It covers what the tool does, when to use it, when not to use it, the parameter semantics with examples, and a concrete usage example. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single parameter callout_text is described in the schema (1-25 characters). The description adds value by providing examples ('Free Shipping', '24/7 Support') and clarifying it's the visible snippet. This goes beyond the schema's minimal description, helping the agent understand what constitutes appropriate input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Add a short non-clickable selling-point snippet (callout) that appears beneath a Google Ads ad'. It uses a specific verb (add/create), identifies the resource (Google Ads callout extension), and provides concrete examples. It distinguishes itself from sibling tools by explicitly mentioning what callouts are not (clickable, lists) and contrasts with sitelinks and structured snippets.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has dedicated 'WHEN TO USE' and 'WHEN NOT TO USE' sections. It gives concrete use cases like 'Add a Free Shipping callout' and explicitly routes to alternative tools for other needs (e.g., 'Want a clickable shortcut... → use create_google_sitelink_extension'). This is explicit, unambiguous guidance with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_image_extensionCreate Google Ads Image Extension (BETA)AInspect
Attach visual imagery (1-20 product / lifestyle shots) to a Google Ads text ad to lift click-through. BETA. Re-uses assets already uploaded to the Metadata image library — pass their IDs, not raw files.
ALSO KNOWN AS: image extension, image asset, ad image, visual extension, picture extension, photo extension, hero image
KEYWORDS: image, image extension, photo, picture, visual, hero, asset, library, BETA, google ads, extension, CTR
WHEN TO USE:
- "Attach images to our Google Ads text ad"
- "Add image library IDs 123 and 456 as an image extension"
- "Create an image extension showing product photos under our search ads"
WHEN NOT TO USE:
- The image is a logo / brand mark → use create_google_business_logo_extension
- You haven't uploaded the assets yet — image extensions reference library IDs, so upload to the image library first.
- Want to drive clicks via text snippets → use create_google_sitelink_extension / callout
- Same images for Microsoft Ads / Bing → use create_microsoft_image_extension
INPUTS:
- image_library_ids (required): 1-20 IDs from the Metadata image library.
- alternative_text: accessibility alt text (≤90 chars).
- display_text: short caption overlaid on the image (≤35 chars). E.g. "Shop Now".
- destination_url: landing page when the image is clicked.
EXAMPLE:
create_google_image_extension(
image_library_ids=[123, 456],
alternative_text="Product hero shot",
display_text="Shop Now",
destination_url="https://example.com/landing",
)| Name | Required | Description | Default |
|---|---|---|---|
| display_text | No | ||
| destination_url | No | ||
| alternative_text | No | ||
| image_library_ids | Yes | 1-20 image-library IDs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false and destructiveHint=false, and the description does not contradict this. The description adds critical behavioral context beyond annotations: it is BETA, requires pre-uploaded library IDs rather than raw files, and implies mutation by 'attach'. It does not detail success/failure outcomes or permissions, but given annotations cover the safety profile, the added context is valuable.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with distinct sections (ALSO KNOWN AS, KEYWORDS, WHEN TO USE, WHEN NOT TO USE, INPUTS, EXAMPLE). It front-loads the core purpose and then provides necessary routing and parameter detail. Some redundancy exists (ALSO KNOWN AS and KEYWORDS overlap), but each section serves a purpose for an AI agent searching and parsing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, the description is comprehensive: it covers purpose, usage conditions, parameter semantics, an example, and sibling differentiators. Nothing critical is missing for an agent to correctly invoke the tool, including the prerequisite that assets must already be in the library.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 25% (only image_library_ids has a schema description). The description compensates fully by explaining each parameter: image_library_ids (required, 1-20), alternative_text (≤90 chars), display_text (≤35 chars with example 'Shop Now'), and destination_url (landing page). It also provides a complete example call, making parameter usage crystal clear.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Attach visual imagery') and the target resource ('Google Ads text ad'), plus the benefit ('lift click-through'). It also differentiates from siblings by naming alternatives like logo, sitelink, and Microsoft image extensions, making the tool's scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'WHEN TO USE' and 'WHEN NOT TO USE' sections provide clear conditions and name specific sibling tools (create_google_business_logo_extension, create_google_sitelink_extension, create_microsoft_image_extension). It also states the prerequisite of uploading assets to the library first, leaving no guesswork.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_lead_form_extensionCreate Google Ads Lead Form ExtensionAInspect
Add an inline lead-capture form attached to a Google Ads ad — prospects submit their email plus optional contact and work info without leaving the SERP. Drives higher conversion than landing-page redirects and feeds leads straight into Metadata.
ALSO KNOWN AS: lead form, lead gen form, inline form, lead capture, contact form, demo request form, in-ad form, form extension
KEYWORDS: lead form, lead gen, lead capture, form, contact form, demo request, inline form, conversion, MQL, opt-in, signup, registration, google ads, extension
WHEN TO USE:
- "Add a lead form extension to capture demo requests under our search ads"
- "Create an inline form asking for work email and job title"
- "Set up a Google Ads lead-gen form with a 'Request Demo' CTA"
- "Register a contact-us form extension for the homepage campaign"
WHEN NOT TO USE:
- Just want to drive clicks to a landing page (no inline form) → use create_google_sitelink_extension
- Want to plug a single product / pricing tier under the ad → use create_google_price_extension
- For Microsoft Ads / Bing — Microsoft does not surface inline lead forms via the platform; pick a different extension type or use a landing-page redirect.
- For Facebook lead forms or LinkedIn LeadGen — those are separate channel surfaces, not search-channel ad-extensions.
INPUTS (required):
- headline: form headline (≤30 chars).
- business_name: advertiser name shown in form (≤25 chars).
- privacy_policy_url: link to your privacy policy (Google requires it).
- post_submit_headline: thank-you screen headline (≤30 chars).
- post_submit_description: thank-you screen body (≤200 chars).
- post_submit_call_to_action_type: button on the thank-you screen. VISIT_SITE | DOWNLOAD | LEARN_MORE | SHOP_NOW.
- call_to_action_type: main CTA on the ad. APPLY_NOW | BOOK_NOW | CONTACT_US | DOWNLOAD | GET_INFO | GET_OFFER | GET_QUOTE | GET_STARTED | JOIN_NOW | LEARN_MORE | REGISTER | REQUEST_DEMO | SIGN_UP | SUBSCRIBE.
- call_to_action_description: sub-text under the CTA (≤30 chars).
- email_lead_form_user_input_types: at least one of WORK_EMAIL, EMAIL.
INPUTS (optional):
- description: form body text (≤200 chars).
- contact_lead_form_user_input_types: any of FIRST_NAME, LAST_NAME, PHONE_NUMBER, CITY, POSTAL_CODE, REGION, COUNTRY, STREET_ADDRESS.
- work_lead_form_user_input_types: any of COMPANY_NAME, JOB_TITLE, WORK_PHONE.
- url: thank-you-page URL after submit.| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Optional thank-you-page URL. | |
| headline | Yes | ||
| description | No | ||
| business_name | Yes | ||
| privacy_policy_url | Yes | ||
| call_to_action_type | Yes | ||
| post_submit_headline | Yes | ||
| post_submit_description | Yes | ||
| call_to_action_description | Yes | ||
| post_submit_call_to_action_type | Yes | ||
| work_lead_form_user_input_types | No | ||
| email_lead_form_user_input_types | Yes | ||
| contact_lead_form_user_input_types | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false and destructiveHint=false. The description goes beyond merely confirming a write operation by adding that the form 'feeds leads straight into Metadata' and operates as an inline element on the SERP, which is useful behavioral context not present in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headers and a front-loaded first sentence. However, the 'ALSO KNOWN AS' and 'KEYWORDS' sections are largely redundant with the body and add length without new information, slightly reducing conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 13-parameter creation tool with 9 required fields, the description covers parameter semantics, use cases, alternatives, and exclusions thoroughly. It does not mention how the tool identifies the target ad/campaign (no campaign_id in the schema) or what it returns, which are minor gaps but not critical given the rich behavioral and usage context provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 8%, so the description carries the full burden of parameter documentation. It lists all required and optional inputs with clear semantics, character limits (e.g., '≤30 chars'), enums (e.g., call_to_action_type), and grouping (email, contact, work fields), adding substantial meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function with a specific verb ('Add') and resource ('inline lead-capture form attached to a Google Ads ad'). It distinguishes itself from sibling tools by explicitly naming alternatives (create_google_sitelink_extension, create_google_price_extension) in the 'WHEN NOT TO USE' section.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE' section provides concrete example utterances, and the 'WHEN NOT TO USE' section gives explicit conditions and alternative tools (sitelink, price extension) plus channel exclusions (Microsoft, Facebook, LinkedIn). This leaves no ambiguity about when to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_price_extensionCreate Google Ads Price ExtensionAInspect
Add a price-list shown beneath a Google Ads ad — 3-8 tiles, each with a plan/product name, a short description, a USD amount, and a billing unit. Standard play for SaaS pricing tiers, subscription plans, course catalogs, service menus, or hotel night rates.
ALSO KNOWN AS: price extension, pricing, price list, pricing tiers, plan pricing, subscription pricing, price tiles, rate card, fare list
KEYWORDS: price, pricing, price list, plan, plans, tier, tiers, subscription, monthly, yearly, hourly, daily, fare, rate, cost, dollar, $, USD, google ads, extension
WHEN TO USE:
- "Show our pricing tiers under our Google Ads"
- "Add a price extension with Basic / Pro / Scale plans"
- "Register monthly subscription prices for the campaign"
- "Create a rate card extension starting from $9.99"
WHEN NOT TO USE:
- Single time-bound discount (Black Friday 20% off, promo code) → use create_google_promotion_extension
- Non-priced offerings list (just names, no amounts) → use create_google_structured_snippet_extension
- Same price list for Microsoft Ads / Bing → use create_microsoft_price_extension
INPUTS:
- price_qualifier: prefix shown before each price. UNSPECIFIED (no prefix) | FROM ("From $X") | UP_TO ("Up to $X") | AVERAGE ("Avg $X").
- price_offerings: 3-8 tiles. Each tile:
- url: landing page for that tier (non-blank, ≤2000 chars).
- header: tier name (1-25 chars). E.g. "Basic", "Pro", "Scale".
- description: short tagline (1-25 chars). E.g. "Starter plan".
- amount: USD number (max 999999999.99, two decimals).
- unit: billing cadence. UNSPECIFIED | PER_HOUR | PER_DAY | PER_WEEK | PER_MONTH | PER_YEAR | PER_NIGHT.
EXAMPLE:
create_google_price_extension(
price_qualifier="FROM",
price_offerings=[
{"url": "https://example.com/basic", "header": "Basic",
"description": "Starter plan", "amount": 9.99, "unit": "PER_MONTH"},
{"url": "https://example.com/pro", "header": "Pro",
"description": "Growing teams", "amount": 29.00, "unit": "PER_MONTH"},
{"url": "https://example.com/scale", "header": "Scale",
"description": "Enterprise", "amount": 99.00, "unit": "PER_MONTH"},
],
)| Name | Required | Description | Default |
|---|---|---|---|
| price_offerings | Yes | 3-8 price offerings. | |
| price_qualifier | Yes | Price qualifier shown before the price. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag this as a mutation (readOnlyHint=false, destructiveHint=false). The description adds the placement context ('beneath a Google Ads ad') and the 3-8 tile constraint, but does not disclose any side effects, activation steps, or response behavior. It satisfies the mutation implication but adds little beyond annotations and the obvious create semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with headers (WHEN TO USE, INPUTS, EXAMPLE) and front-loads the core action. The ALSO KNOWN AS and KEYWORDS sections add length but serve retrieval for natural-language user intents, so they earn their place. Minor redundancy between the intro and INPUTS keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given two parameters (one nested with five fields), no output schema, and a requirement to differentiate from six sibling extension tools, the description covers all input semantics, explicit examples, and decision routing. An agent has everything needed to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description goes further by explaining the meaning of price_qualifier (e.g., FROM -> 'From $X'), the field-level constraints for each tile (lengths, amount range, billing unit examples), and providing a full usage example. This meaningfully adds to the bare schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add a price-list shown beneath a Google Ads ad.' It details the tile structure and explicitly names sibling alternatives in the WHEN NOT TO USE section, making it unambiguous against other extension-creation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
WHEN TO USE gives concrete example intents, and WHEN NOT TO USE routes to three specific sibling tools (promotion, structured snippet, Microsoft price extension) with the exact disambiguating conditions. No inference is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_promotion_extensionCreate Google Ads Promotion ExtensionAInspect
Add a time-bound promotional offer (sale, discount, promo code) that shows under a Google Ads ad — flag a holiday occasion, pick the discount style (% off or $ off), optionally attach a promo code or "on orders over $X" qualifier, and set the start/end window. Standard for Black Friday, Cyber Monday, seasonal sales, flash discounts, holiday campaigns.
ALSO KNOWN AS: promotion, promo, discount, sale, offer, coupon, promo code, voucher, deal, holiday sale, seasonal offer
KEYWORDS: promotion, promo, promo code, coupon, sale, discount, offer, deal, black friday, cyber monday, holiday, christmas, summer sale, percent off, dollar off, $ off, voucher, google ads, extension
WHEN TO USE:
- "Set up a Black Friday 20% off promotion for our Pro plan"
- "Add a holiday promo extension with code SUMMER2026"
- "Register a sale: $50 off orders over $200"
- "Create a Cyber Monday discount extension running Nov 30 to Dec 2"
WHEN NOT TO USE:
- Permanent pricing tiers (not a limited-time discount) → use create_google_price_extension
- Plain "Free Shipping" badge → use create_google_callout_extension
- Lead-capture form attached to the ad → use create_google_lead_form_extension
- Same promotion for Microsoft Ads / Bing → use create_microsoft_promotion_extension
INPUTS (required):
- occasion: holiday/event tag (NONE if no specific occasion). Available: NONE, BACK_TO_SCHOOL, BLACK_FRIDAY, BOXING_DAY, CARNIVAL, CHINESE_NEW_YEAR, CHRISTMAS, CYBER_MONDAY, DIWALI, EASTER, EID_AL_ADHA, EID_AL_FITR, END_OF_SEASON, EPIPHANY, FALL_SALE, FATHERS_DAY, HALLOWEEN, HANUKKAH, HOLI, INDEPENDENCE_DAY, LABOR_DAY, MOTHERS_DAY, NATIONAL_DAY, NAVRATRI, NEW_YEARS, PARENTS_DAY, PASSOVER, RAMADAN, ROSH_HASHANAH, SINGLES_DAY, SONGKRAN, SPRING_SALE, ST_NICHOLAS_DAY, SUMMER_SALE, VALENTINES_DAY, WINTER_SALE, WOMENS_DAY, YEAR_END_GIFT.
- url: landing page for the promotion.
- item: what's on sale (1-20 chars). E.g. "Pro subscription".
- category_type: discount style.
* MONETARY → "$X off". Provide category_amount.
* UP_TO_MONETARY → "Up to $X off". Provide category_amount.
* PERCENT → "X% off". Provide category_percent (≤100).
* UP_TO_PERCENT → "Up to X% off". Provide category_percent (≤100).
- details_type: optional qualifier.
* NONE → no qualifier.
* ON_ORDERS_OVER → "on orders over $X". Provide details_amount.
* PROMO_CODE → "with code XXXX". Provide details_promo_code (≤15 chars).
- start_date / end_date: ISO-8601 in pattern "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" (e.g. 2026-11-25T00:00:00.000Z). Both must be today or in the future.
INPUTS (optional, see category_type / details_type above):
- category_amount, category_percent, details_promo_code, details_amount.
EXAMPLE — Black Friday 20% off Pro with promo code:
create_google_promotion_extension(
occasion="BLACK_FRIDAY",
url="https://example.com/sale",
item="Pro subscription",
category_type="PERCENT", category_percent=20,
details_type="PROMO_CODE", details_promo_code="BF2026",
start_date="2026-11-25T00:00:00.000Z",
end_date="2026-11-30T23:59:59.000Z",
)| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| item | Yes | ||
| end_date | Yes | ISO-8601 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". Future or present. | |
| occasion | Yes | ||
| start_date | Yes | ISO-8601 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". Future or present. | |
| details_type | Yes | ||
| category_type | Yes | ||
| details_amount | No | Threshold USD amount; supply when details_type is ON_ORDERS_OVER. | |
| category_amount | No | USD amount; supply when category_type is MONETARY or UP_TO_MONETARY. | |
| category_percent | No | Percent (≤100); supply when category_type is PERCENT or UP_TO_PERCENT. | |
| details_promo_code | No | Promo code; supply when details_type is PROMO_CODE. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag readOnlyHint=false and destructiveHint=false, so the description doesn't need to establish that this is a non-destructive write operation. Beyond that, it adds useful behavioral context: the offer is time-bound, must have start/end dates in the present or future, and attaches to a Google Ads ad. It stops short of describing post-creation effects or any auth/rate-limit caveats, but the core behavior is clear.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headers (ALSO KNOWN AS, KEYWORDS, WHEN TO USE, WHEN NOT TO USE, INPUTS, EXAMPLE). The keyword lists and usage examples earn their place for agent semantic matching, and the example is valuable for a complex conditional parameter set. It is verbose, but every section contributes.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having 11 parameters, 7 required fields, no output schema, and conditional logic between category_type and category_amount/category_percent, the description explains every call-relevant aspect: optional parameters, constraints, enum values, date format, and a full runnable example. An agent has everything needed to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema coverage at only 55%, the description takes on the full burden of explaining the parameters. It defines url as 'landing page for the promotion,' explains item as 'what's on sale (1-20 chars),' maps each category_type to its required amount/percent field, explains details_type qualifiers, and gives the exact ISO-8601 pattern with an example. The included worked example ties everything together.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add a time-bound promotional offer... that shows under a Google Ads ad.' It clearly identifies the tool's exact purpose—creating a promotion extension for Google Ads—and distinguishes it from sibling tools in the WHEN NOT TO USE section by naming create_google_price_extension, create_google_callout_extension, and others.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit WHEN TO USE examples ('Set up a Black Friday 20% off promotion') and an explicit WHEN NOT TO USE list with alternative tools for each excluded scenario, such as permanent pricing tiers → create_google_price_extension and lead-capture forms → create_google_lead_form_extension. This is exactly the level of routing guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_sitelink_extensionCreate Google Ads Sitelink ExtensionAInspect
Add an extra clickable shortcut (sitelink) that appears beneath a Google Ads ad — helpful deep-links like "See Pricing", "Book a Demo", or "Contact Sales" with two short description lines. Sitelinks lift click-through rate by giving searchers alternate landing paths to the same advertiser.
ALSO KNOWN AS: sitelink, site link, extra link, ad link, secondary link, deep link, additional link, jump link
KEYWORDS: sitelink, site link, link, deep link, shortcut, google ads, extension, pricing link, demo link, contact link, landing page, CTR, click through
WHEN TO USE:
- "Add a sitelink to our Google Ads library"
- "Create a 'See Pricing' / 'Book a Demo' / 'Contact Sales' link extension"
- "Register a new sitelink for the homepage redesign"
- "I need a shortcut under our search ads that points to the new pricing page"
WHEN NOT TO USE:
- Want a non-clickable selling-point snippet ("Free Shipping", "24/7 Support") → use create_google_callout_extension
- Want a labeled list of offerings (e.g. "Brands: Nest, Nexus") → use create_google_structured_snippet_extension
- Same sitelink for Microsoft Ads / Bing → use create_microsoft_sitelink_extension (library entries are per-channel)
- Anything for Facebook / LinkedIn / Reddit — ad extensions are a search-channel-only concept
INPUTS (all required):
- url: destination the sitelink opens.
- link_text: visible link text (1-25 chars).
- description1: first description line under the link (1-35 chars).
- description2: second description line (1-35 chars).
EXAMPLE:
create_google_sitelink_extension(
url="https://example.com/pricing",
link_text="See Pricing",
description1="Plans for every team size",
description2="Start free, upgrade anytime",
)
Returns the persisted extension (id, externalId, type=SITELINK, channel=GOOGLE_ADS). A 400 usually means a character-limit was exceeded.| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Destination URL the sitelink points to (non-blank). | |
| link_text | Yes | Visible link text. 1-25 characters. | |
| description1 | Yes | First description line. 1-35 characters. | |
| description2 | Yes | Second description line. 1-35 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only state that the operation is not read-only and not destructive; the description adds significant behavioral context by describing the returned persisted extension (id, externalId, type, channel), typical error behavior for character-limit violations, and the fact that the extension lands under the ad. There is no contradiction between the 'create' semantics and annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headers, a concrete example, and a front-loaded definition, but the 'ALSO KNOWN AS' and 'KEYWORDS' lists contain many redundant synonyms that add bulk without meaningful selection value. It is organized enough to scan quickly while still carrying some fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description discloses the return shape and a common error cause, and it provides all required inputs, a working example, and clear routing to sibling tools. For a four-parameter creation tool, this is complete enough for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers all four parameters with character limits and non-blank constraints, so the baseline is 3. The description adds a complete invocation example and clarifies each parameter's real-world role (e.g., 'visible link text' and 'first description line'), which goes slightly beyond the schema's basic wording. This is useful but somewhat redundant with the schema, hence a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific verb ('Add'), a concrete resource ('extra clickable shortcut / sitelink beneath a Google Ads ad'), and distinguishes it from sibling extension tools by naming what it is not (callouts, structured snippets, Microsoft sitelinks). It also includes examples of link text and landing paths, leaving no ambiguity about what the tool creates.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It contains an explicit WHEN TO USE section with example user requests, and a detailed WHEN NOT TO USE section listing the exact alternative tools for non-clickable snippets, structured snippets, and Microsoft Ads. This directly guides an agent to the correct sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_google_structured_snippet_extensionCreate Google Ads Structured Snippet ExtensionAInspect
Add a labeled list of offerings (structured snippet) shown beneath a Google Ads ad — a category header plus 3-10 short items, e.g. header "Brands" with values "Nest", "Nexus", "Chromebook", or header "Services" with "Hosting", "DNS", "CDN". Helps searchers self-qualify before clicking.
ALSO KNOWN AS: structured snippet, snippet, category list, offering list, header values, product list, service list
KEYWORDS: structured snippet, snippet, header, values, brands, services, products, courses, destinations, list, category, google ads, extension
WHEN TO USE:
- "Add a structured snippet listing our service tiers"
- "Create a snippet under 'Brands' with Nest, Nexus, Chromebook"
- "Register a list of supported integrations as a snippet extension"
- "Show our product categories below our Google Ads"
WHEN NOT TO USE:
- Want a single phrase (e.g. "Free Shipping") → use create_google_callout_extension
- Want clickable links to subpages → use create_google_sitelink_extension
- Want a pricing table (with amounts) → use create_google_price_extension
- Same snippet for Microsoft Ads / Bing → use create_microsoft_structured_snippet_extension
INPUTS:
- header: snippet category title (1-25 chars). The Google-Ads vocabulary requires picking one of Google's predefined header names ("Brands", "Models", "Service catalog", "Insurance coverage", etc.) — pass the chosen header string here.
- values: 3-10 items, each 1-25 chars.
EXAMPLE:
create_google_structured_snippet_extension(
header="Brands",
values=["Nest", "Nexus", "Chromebook"],
)| Name | Required | Description | Default |
|---|---|---|---|
| header | Yes | Snippet header. 1-25 characters. | |
| values | Yes | 3-10 snippet values, each 1-25 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide readOnlyHint=false and destructiveHint=false, indicating a non-read, non-destructive operation, which aligns with the 'Add' action. The description adds useful context about the structure (header + 3-10 values) and the Google predefined header vocabulary, but does not explicitly state side effects (e.g., extension appears immediately) or permission requirements. It does not contradict the annotations, and adds moderate value beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (ALSO KNOWN AS, KEYWORDS, WHEN TO USE, WHEN NOT TO USE, INPUTS, EXAMPLE). Each section earns its place and the main purpose is front-loaded. It is comprehensive without being redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter create tool with no output schema, the description is complete: it explains what the tool does, when to use it, when not to use it, the exact parameter constraints (including the predefined header vocabulary), and provides a full example call. Nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema describes both parameters at 100% coverage, the description adds critical semantic value: it explains that the header must be one of Google's predefined names and provides example values. This is beyond the schema's simple maxLength/minLength constraints and materially improves parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Add') and the resource ('labeled list of offerings (structured snippet) shown beneath a Google Ads ad'), and gives concrete examples (header 'Brands' with values). It also explicitly differentiates from sibling tools in the 'WHEN NOT TO USE' section, so an agent can distinguish it from create_google_callout_extension, create_google_sitelink_extension, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'WHEN TO USE' and 'WHEN NOT TO USE' sections with specific example queries and names the exact alternative tools (callout, sitelink, price, Microsoft snippet). This gives clear routing guidance with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_keywordsCreate KeywordsAInspect
Create one or more positive keywords in the Metadata platform library.
PURPOSE:
Batch create positive keywords that can be used in advertising campaigns. Use this tool to
expand your keyword library by adding new terms, variations, or related keywords for targeting
and campaign optimization.
WHEN TO USE:
- Add new keywords to your campaign library
- Build keyword lists for new product lines or services
- Create variations of existing keywords
- Expand keyword coverage for targeted advertising
- Create keyword groups for seasonal campaigns
- Add long-tail keywords for niche targeting
- Build negative keyword lists (blocked keywords)
- Bulk import keyword lists from external sources
KEY FEATURES:
- BATCH CREATION: Create multiple keywords in a single API request
- SIMPLE FORMAT: Each keyword is simply a string
- FLEXIBLE: Create 1 or 100+ keywords at once
- LIBRARY INTEGRATION: Keywords are added to your keyword library and available for campaigns
KEYWORD FORMAT:
Each keyword in the batch should be a simple string:
- "digital marketing"
- "seo services"
- "ppc advertising"
BATCH SIZE RECOMMENDATIONS:
- Small batches (5-50 keywords): Ideal for testing and quick additions
- Medium batches (50-500 keywords): Good for standard imports
- Large batches (500+ keywords): Use for bulk library imports
- Maximum recommended: 1000 keywords per request for optimal performance
KEYWORD NAMING CONVENTIONS:
- Use lowercase for consistency with platform standards
- Separate multi-word phrases (e.g., "digital marketing" not "DigitalMarketing")
- Avoid special characters unless necessary for the keyword
- Remove leading/trailing whitespace - the API will normalize
- Empty strings are allowed but won't create keywords
- Duplicate names in the batch will be deduplicated by the API
COMMON USE CASES:
1. Create a single keyword:
create_keywords(keywords=["marketing"])
2. Create multiple related keywords:
create_keywords(keywords=[
"digital marketing",
"marketing automation",
"email marketing"
])
3. Create keyword variations:
create_keywords(keywords=[
"seo",
"seo services",
"seo tools",
"seo optimization"
])
4. Create long-tail keywords:
create_keywords(keywords=[
"best digital marketing agency in new york",
"affordable seo services for small business",
"enterprise marketing automation platform"
])
5. Bulk import from external list:
create_keywords(keywords=[
"keyword1",
"keyword2",
"keyword3",
... (repeat for all keywords)
])
6. Create campaign-specific keywords:
create_keywords(keywords=[
"black friday deals",
"cyber monday sales",
"holiday promotions"
])
7. Create product-related keywords:
create_keywords(keywords=[
"product a",
"product a review",
"buy product a",
"product a price"
])
PARAMETERS:
- keywords: Required. Array of keyword strings to create.
Example: ["goku", "ssj", "ssj1"]
- Each keyword is a string
- Minimum: 1 keyword
- Recommended maximum: 1000 keywords per request
- Empty strings are allowed but won't create keywords
- Duplicates will be deduplicated
RESPONSE FORMAT:
Returns a response containing:
- Created keywords with their IDs and metadata
- Success/failure status for each keyword
- Any validation errors for invalid entries
- Confirmation of keywords added to the library
VALIDATION NOTES:
- Empty strings or null values in the batch are skipped
- Platform automatically removes duplicate names in the batch
- Keywords are case-insensitive for deduplication
- Special characters are preserved as provided
- Platform validates keyword length (typically 2-100 characters recommended)
PERFORMANCE TIPS:
- Keep batch sizes under 1000 keywords for faster processing
- Group related keywords together for better organization
- Review the response to confirm all keywords were created successfully
- Check your keyword library after creation to verify the additions
EXAMPLES:
- create_keywords(keywords=["marketing"]) - Create single keyword
- create_keywords(keywords=["seo", "sem", "ppc"]) - Create multiple keywords
- create_keywords(keywords=["digital marketing", "online marketing", "internet marketing"]) - Variations
- create_keywords(keywords=["goku", "ssj", "ssj1", "ssj2"]) - Batch creation| Name | Required | Description | Default |
|---|---|---|---|
| keywords | Yes | Array of keyword strings to create. Example: ["goku", "ssj", "ssj1"] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description substantially extends the sparse annotations (readOnlyHint=false, destructiveHint=false) by disclosing deduplication of duplicates, case-insensitive dedup, whitespace normalization, empty-string skipping, length validation (2-100 chars), and the 1000-keyword batch ceiling. This is rich, non-obvious behavioral context that annotations do not carry. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is heavily bloated. The KEY FEATURES, use cases (1-7), EXAMPLES, and PARAMETERS sections all restate the same facts: batch creation, dedup, empty-string handling, naming. Roughly half the content is redundant, and the KEYWORD FORMAT section merely repeats the schema's string type. Clear header structure notwithstanding, it does not earn its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema, nothing an agent needs is missing: response format (IDs, success/failure, validation errors) is explained, validation rules are enumerated, naming conventions and batch limits are given, and numerous examples are provided. It is genuinely complete despite the redundancy.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single keyword array, so baseline is 3, but the description adds significant value beyond the schema: naming conventions (lowercase, multi-word separation), dedup rules, case-insensitivity, length limits, and batch-size recommendations. It properly compensates for what a bare array schema cannot convey, going well above the minimum.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Create one or more positive keywords in the Metadata platform library') and a separate PURPOSE section. It differentiates from siblings by emphasizing 'positive' keywords, which contrasts with negative-keyword tools like create_negative_keywords_list. However, the contemporaneous WHEN TO USE bullet 'Build negative keyword lists (blocked keywords)' directly contradicts the positive-keywords framing, muddying the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
An explicit WHEN TO USE list provides eight concrete scenarios. But guidance is partly misleading: it includes 'Build negative keyword lists (blocked keywords)' even though dedicated sibling tools exist (create_negative_keywords_list, add_keywords_to_negative_lists) and this tool is for positive keywords. It never names those alternatives nor states when NOT to use this tool, so it fails to route the agent correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_linkedin_engagement_retargeting_audienceCreate LinkedIn Engagement Retargeting AudienceAInspect
Create a LinkedIn Engagement Retargeting audience: people who already engaged with the advertiser's LinkedIn ads, company page, or website. STEP 3 of the flow.
This is NOT create_retargeting_audience, which imports an audience the ad account
already has. This builds a NEW LinkedIn DMP segment from the engagement rule defined
here. Once built it is a normal Metadata audience and can be attached to campaigns.
**REQUIRED WORKFLOW — do not call this tool first:**
1. get_linkedin_engagement_source_types → choose `source_platform` + `engagement_trigger`
2. For every source type EXCEPT WEBSITE: search_linkedin_engagement_sources with that
trigger and lookback → collect each chosen result's `id` into
`engagement_source_urns`
3. Call this tool
Source types, triggers and URNs are LinkedIn's own values, and only steps 1 and 2
can supply them. Do not invent, guess or reuse one from another account: a value
that did not come from those steps either fails outright or, worse, is accepted and
builds an audience that never populates.
**TWO SHAPES, MUTUALLY EXCLUSIVE — mixing them is rejected:**
A) NON-WEBSITE (VIDEO_ADS, SINGLE_IMAGE_ADS, DOCUMENT_ADS, CONVERSATION_ADS,
LEAD_GEN_FORMS, ORGANIZATION_PAGES):
pass `engagement_source_urns`. Do NOT pass page_set_name or url_match_groups.
B) WEBSITE:
pass `page_set_name` and `url_match_groups`. Do NOT pass engagement_source_urns.
Metadata creates the LinkedIn page set from those URL rules for you.
URL MATCH RULES (WEBSITE only) are a LIST OF GROUPS. Rules inside a group are ANDed;
the groups are ORed. Each rule is {matchType, matchValue}, matchType being EXACT
("URL equals"), STARTS_WITH, or CONTAINS.
[[A, B], [C]] means (A AND B) OR C
Worked example — "anyone who hit pricing or any demo page":
[[{"matchType": "STARTS_WITH", "matchValue": "https://example.com/pricing"}],
[{"matchType": "CONTAINS", "matchValue": "/demo"}]]
Use one rule per group for a simple OR list, which is what most requests mean. Reach
for a multi-rule group only for a genuine AND, e.g. a path that also carries a
campaign parameter.
WHEN TO USE:
- "Retarget everyone who watched our video ads in the last 90 days"
- "Build an audience from people who submitted the lead form"
- "Create an audience of visitors to our pricing and demo pages"
- "Retarget people who visited our LinkedIn company page"
- "Make a warm audience from last quarter's ad engagement"
PARAMETERS:
- name: audience name (required). Give it something descriptive of the rule, e.g.
"Video 50% viewers 90d", so it is recognisable in the audience list later.
- source_platform: the chosen `engagementSourceType` (required)
- engagement_trigger: a trigger listed for THAT source type (required). NOTHING
VALIDATES THE PAIRING — see the warning below.
- lookback_window_days: 30, 60, 90, 180 or 365 — WEBSITE caps at 180 (required)
- engagement_source_urns: LinkedIn URNs from search_linkedin_engagement_sources,
copied verbatim. Required for every source type except WEBSITE. Several are
normal: the audience is everyone who engaged with ANY of them.
- page_set_name: internal label for the URL rule set (WEBSITE only, required there).
Only ever seen inside LinkedIn, so a plain descriptive label is fine.
- url_match_groups: the OR-of-ANDs URL expression (WEBSITE only, required there)
RETURNS:
Confirmation with the new audience `id` and name, the `criteria` that define it
(source, trigger, lookback, how many sources), the channel, and a `note` on when it
becomes usable.
**WHAT TO TELL THE USER AFTER IT SUCCEEDS:**
It is created but not yet populated. LinkedIn takes up to 48 hours to build the
audience and a further 24 hours before it delivers, so it will show NO match count
and NO contact or company numbers immediately. That is expected and correct, not a
failure. Say so plainly rather than reporting the audience as empty or broken.
IMPORTANT NOTES:
- **THE TRIGGER MUST BELONG TO THE SOURCE TYPE, AND NOTHING CHECKS THAT FOR YOU.**
A mismatched pair (e.g. VIDEO_ADS with LEAD_FORM_SUBMIT) is accepted by this tool,
by the platform and by LinkedIn, with no error at any layer — it just builds an
audience that can never populate, because the engagement it describes cannot
happen. Verified on stage. Always take the trigger from the source type's own
`triggers` list in step 1; never carry one over from another source type.
- Requires a connected LinkedIn channel on the account.
- **NEVER re-create the audience because it shows no members.** Zero right after
creation is the normal state; creating it again just makes a duplicate.
- This audience type NEVER reports contact or company counts the way a firmographic
audience does. It lives on LinkedIn, so only LinkedIn's own match count applies.
- WEBSITE additionally requires the LinkedIn Insight Tag installed and active on the
pages the URL rules match. Without it the audience stays empty indefinitely, no
matter how long you wait — mention this whenever you build a WEBSITE audience.
- The lookback window doubles as the retention window: it sets both how far back
engagement counts and how long someone stays in the audience.
- Building from sources with no engagement produces an empty audience. If step 2
showed zeros everywhere, raise that with the user instead of creating anyway.
- The rule cannot be edited afterwards. A different trigger or lookback means a new
audience, so confirm the choice before creating when the user was vague.
COMMON ERRORS AND WHAT THEY MEAN:
- "engagement_source_urns is required" — you skipped step 2, or passed a WEBSITE-style
payload for a non-website source type.
- "must be one of [30, 60, 90, 180]" — WEBSITE was given a 365-day lookback.
- "page_set_name / url_match_groups is required" — WEBSITE needs the URL rules, not URNs.| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name for the new audience. Prefer something that describes the rule (e.g. 'Video 50% viewers 90d') so it is recognisable later. | |
| page_set_name | No | WEBSITE only: internal label for the URL rule set created on LinkedIn (e.g. 'Pricing and demo pages'). Required when source_platform is WEBSITE. | |
| source_platform | Yes | The `engagementSourceType` chosen from get_linkedin_engagement_source_types — e.g. VIDEO_ADS, SINGLE_IMAGE_ADS, DOCUMENT_ADS, CONVERSATION_ADS, LEAD_GEN_FORMS, ORGANIZATION_PAGES, or WEBSITE. WEBSITE switches this tool to the URL-rule shape. | |
| url_match_groups | No | WEBSITE only: OR-of-ANDs URL expression. The outer list is ORed, rules inside a group are ANDed. For a plain 'any of these pages' list, use one rule per group. Required when source_platform is WEBSITE. | |
| engagement_trigger | Yes | An `engagementTrigger` listed for THAT source type (e.g. FIRST_QUARTILE for VIDEO_ADS, LEAD_FORM_SUBMIT for LEAD_GEN_FORMS, VISIT for WEBSITE). A trigger from a DIFFERENT source type is accepted without error and silently builds an audience that never populates, so take it from this source type's own trigger list. | |
| lookback_window_days | Yes | How far back engagement counts, and how long a member is retained. WEBSITE accepts 30/60/90/180 only; every other source type also accepts 365. | |
| engagement_source_urns | No | LinkedIn URNs to retarget, taken verbatim from the `id` of each chosen search_linkedin_engagement_sources result. Required for every source type EXCEPT WEBSITE, and must be omitted for WEBSITE. Multiple URNs union their audiences. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (readOnlyHint=false, destructiveHint=false), the description discloses numerous behavioral traits: 'It is created but not yet populated... up to 48 hours to build... 0 more 24 hours before it delivers', 'The rule cannot be edited afterwards', 'a mismatched pair is accepted without error at any layer', and 'WEBSITE additionally requires the LinkedIn Insight Tag'. It also discloses that the audience never reports contact/company countscedented and that lookback acts as retention. This far exceeds what annotations alone communicate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with bolding, numbered steps, headers, and a common-errors section. Every major block earns its place (workflow, shapes, URL rules, user messaging). Some redundancy exists (the trigger-pairing warning appears in both the parameter notes and IMPORTANT NOTES, and the 'zero match count' point appears twice), but this reinforces rather than bloats. It is appropriately sized for a tool with this much pre-requisite nuance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for an agent to call this tool correctly: it states pre-requisite workflow, parameter constraints, return value shape (audience id, name, criteria, channel, note), expected post-creation behavior, and common errors with meanings. Since there is no output schema, the description carries the full burden for return semantics, and it does so explicitly. Nothing an agent needs to know to invoke and interpret the result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds critical semantic content: the two mutually exclusive payload shapes (A: engagement_source_urns vs B: page_set_name + url_match_groups), the OR-of-ANDs interpretation of url_match_groups with a worked example, and the warning that triggers from a different source type are accepted silently. It also tells the agent to copy URNs 'verbatim' from search_linkedin_engagement_sources. These details are not in the schema's structured descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Create a **LinkedIn Engagement Retargeting** audience: people who already engaged with the advertiser's LinkedIn ads, company page, or website.' It then explicitly contrasts with create_retargeting_audience ('This is NOT create_retargeting_audience... This builds a NEW LinkedIn DMP segment'), which distinguishes it from its closest sibling. An agent can tell exactly what this tool does without reading any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit workflow prerequisites ('REQUIRED WORKFLOW — do not call this tool first' with three numbered steps), a explicit 'WHEN TO USE' list of natural-language example requests, and a direct exclusion ('This is NOT create_retargeting_audience...'). It also states when not to use it (e.g., never re-create because zero members is normal). This is textbook usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_linkedin_native_criteria_audienceCreate LinkedIn Native Criteria AudienceAInspect
Create a LinkedIn native criteria audience using LinkedIn-supported targeting criteria. Build audiences based on job titles, skills, company names, employee count ranges, revenue ranges, and geographic location.
ESTIMATE-ONLY MODE:
Pass estimate_only=true to preview audience size WITHOUT creating the audience. In this mode the tool
returns expectedNumberOfContacts. Default is false.
ALSO KNOWN AS: LinkedIn audience, LI criteria audience, native LinkedIn targeting, LinkedIn lead audience
KEYWORDS: LinkedIn, native, criteria, audience, job title, skills, company, company name, employees, revenue, targeting, country, location
WHEN TO USE:
- Create targeted LinkedIn audiences using native LinkedIn criteria
- Target users by job titles (e.g., Software Engineer, Product Manager)
- Target by professional skills (e.g., HubSpot, Salesforce, Python)
- Target by company names (e.g., Metadata, Google, Salesforce)
- Filter by company employee count ranges (e.g., 201-500, 1001-5000)
- Filter by company revenue ranges (e.g., $1M-$10M, $10M-$100M)
- Target by country/geographic location (e.g., United States, United Kingdom)
PARAMETERS:
- name: Audience name (required, must be shorter than 50 characters)
- job_titles: Array of free-text job title strings (optional) - e.g., ["Software Engineer", "Product Manager"]
- skills: Array of free-text skill strings (optional) - e.g., ["HubSpot", "Salesforce", "Python"]
- company_names: Array of free-text company name strings (optional) - e.g., ["Metadata", "Google", "Salesforce"]
- employees: Array of LinkedIn employee count ranges (optional) - valid values: 1, 2-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, +10001
- revenues: Array of LinkedIn revenue ranges (optional) - valid values: Under $1M, $1M-$10M, $10M-$100M, $100M-$1B, $1B+
- location_country_ids: Array of country ID integers (optional) - e.g., [229] for United States
RETURNS:
Audience details with ID, status, and creation info.
IMPORTANT NOTES:
- name is the only required parameter, all other parameters are optional
- Audience name must be shorter than 50 characters
- Job titles, skills, company names, employees, and revenues are free-text arrays
- Country IDs are integer identifiers (e.g., 229 = United States)| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required, must be shorter than 50 characters). | |
| skills | No | Free-text skill strings for targeting. Example: ['HubSpot', 'Salesforce', 'Python'] | |
| revenues | No | LinkedIn revenue ranges for audience targeting. Valid values: Under $1M, $1M-$10M, $10M-$100M, $100M-$1B, $1B+. Example: ['$1M-$10M', '$10M-$100M'] | |
| employees | No | LinkedIn employee count ranges for audience targeting. Valid values: 1, 2-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, +10001. Example: ['201-500', '501-1000'] | |
| job_titles | No | Free-text job title strings for targeting. Example: ['Software Engineer', 'Product Manager'] | |
| company_names | No | Free-text company name strings for targeting. Example: ['Metadata', 'Google', 'Salesforce'] | |
| estimate_only | No | If true, do NOT create the audience — only estimate its size and return the expected contact count. Use this when the user wants to preview LinkedIn audience size before committing. Defaults to false (audience is created). | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate `readOnlyHint=false` (a write operation) and `destructiveHint=false`; the description's 'Create' action aligns with this. It adds behavioral nuance by describing the `estimate_only` mode, which alters the operation to a non-creating preview and returns `expectedNumberOfContacts`. It also specifies the constraint that `name` is required and must be under 50 characters. This goes beyond the annotations and gives useful execution detail, though it does not mention potential idempotency or duplicate errors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long (about 20 lines) but organized with headers ('WHEN TO USE', 'PARAMETERS', 'RETURNS', 'IMPORTANT NOTES'). It is front-loaded with the purpose and key mode. However, it includes redundant sections like 'ALSO KNOWN AS' and 'KEYWORDS' that add noise, and the parameter section largely duplicates schema descriptions. The overall structure helps navigation, but the length and redundancy prevent a higher score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given eight parameters (one required) and no output schema, the description covers the essential aspects: purpose, usage scenarios, parameter details, the `estimate_only` mode, and the name constraint. It also states the return type ('audience details with ID, status, and creation info'). However, it does not explain how multiple criteria are combined (e.g., AND vs. OR), any limitations on array sizes, or error conditions. This leaves gaps that could impact correct invocation for complex audience builds.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already carries a 100% description coverage, including enums for `employees` and `revenues`, a default for `estimate_only`, and a comprehensive list for `location_country_ids`. The description repeats this information with examples for each parameter, but effectively adds little meaning beyond restating schema details. For instance, the valid employee ranges are already in the schema, so the description's repetition is redundant. Baseline 3 is appropriate since the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource: 'Create a LinkedIn native criteria audience using LinkedIn-supported targeting criteria.' It explicitly lists the types of criteria (job titles, skills, company names, employee count, revenue, geography) and distinguishes this tool from other audience-creation siblings like `create_facebook_native_criteria_audience` and `create_linkedin_engagement_retargeting_audience`. The purpose is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated 'WHEN TO USE' section enumerates concrete scenarios: targeting by job titles, skills, company names, employee count, revenue, and location. It also explains the `estimate_only=true` mode as a preview option, which clarifies a distinct use case. However, it does not explicitly state when NOT to use this tool versus alternative audience-creation tools (e.g., `create_audience_from_segment`, `create_firmographic_audience`), so the guidance is strong on positive usage but lacks exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_marketing_automation_contacts_audienceCreate Marketing-Automation Contacts AudienceAInspect
Create a Marketing-Automation-contacts custom audience (platform customAudienceType MA_CONTACTS_STATIC or MA_CONTACTS_DYNAMIC) from a provider library list.
This is one of the audience types eligible for Microsoft Ads (Customer Match). Use it when a user wants a Marketing-Automation-sourced contacts audience, including for a Microsoft Ads campaign.
PREREQUISITE:
• The provider (HUBSPOT or MARKETO) MUST be connected — the platform validates this and returns a clear error if not.
• A library_list_id from list_marketing_automation_lists — do NOT invent one. For HubSpot the list must be DONE; for Marketo READY.
VARIANT (mirrors the UI's static/dynamic choice):
• STATIC → MA_CONTACTS_STATIC — snapshot at creation, does not refresh.
• DYNAMIC → MA_CONTACTS_DYNAMIC — refreshes as the provider data changes.
• If the user did not say which, ASK — do NOT default and do NOT infer it from the source list's type. A HubSpot STATIC_LIST is not the same choice as a STATIC (snapshot) audience; the audience variant is the user's call, independent of the list's type.
ASYNC: the platform creates the audience in the background and returns a flow id, NOT a ready audience id. The audience appears under the account's Marketing-Automation audiences once the flow completes, and its contact count fills in then. Do not expect to associate it to a campaign in the same turn.
PARAMETERS:
• custom_audience_name (required): the audience display name — must NOT contain '/'.
• library_list_id (required): id from list_marketing_automation_lists.
• provider (required): HUBSPOT or MARKETO.
• variant (required): STATIC or DYNAMIC.
• list_name (optional): the source list's own name (from the lookup), forwarded to the flow.
RETURNS: { id, name, status, createdDate, audience_type, async: true } — `audience_type` is the MA_CONTACTS_* you created and `id` is a creation/flow id, not associable yet.| Name | Required | Description | Default |
|---|---|---|---|
| variant | Yes | STATIC = snapshot (MA_CONTACTS_STATIC); DYNAMIC = refreshing (MA_CONTACTS_DYNAMIC). Ask the user if unspecified. | |
| provider | Yes | The Marketing-Automation provider that owns the list. | |
| list_name | No | Optional: the source list's own name, from list_marketing_automation_lists. | |
| library_list_id | Yes | The library list id from list_marketing_automation_lists. | |
| custom_audience_name | Yes | Audience display name. Must not contain '/'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly discloses async creation: the platform returns a flow id, not a ready audience id, and the audience is not associable to a campaign in the same turn. It also details state semantics (STATIC snapshot vs DYNAMIC refresh), post-completion contact-count fill, and provider validation with clear errors -- substantial context far beyond the minimal annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though long, the description is structured into PREREQUISITE, VARIANT, ASYNC, PARAMETERS, and RETURNS sections, with the most decision-critical rule (variant must be asked, not inferred) prominently placed. Every section conveys behavior needed for correct use rather than repeating schema filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating async tool with 5 parameters and no output schema, the description is unusually complete: it covers prerequisites, provider states, source-of-truth for library_list_id, variant policy, async return shape, and post-completion behavior. An agent has what it needs to invoke the tool and set user expectations correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though the input schema covers 100% of parameters, the description adds real semantics: library_list_id must come from list_marketing_automation_lists and must not be invented, variant must be ASKED if unspecified and never inferred from the list type, and HubSpot/Marketo lists must be in DONE/READY status. This materially improves correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create a Marketing-Automation-contacts custom audience ... from a provider library list,' and names the exact platform customAudienceType variants. It also situates the audience as eligible for Microsoft Ads Customer Match, which differentiates it from sibling audience-creation tools even without naming them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger: 'Use it when a user wants a Marketing-Automation-sourced contacts audience, including for a Microsoft Ads campaign.' It also provides clear prerequisites and a decision rule (ASK if variant unspecified), but it does not explicitly name excluded alternatives or say when a different audience tool should be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_business_logo_extensionCreate Microsoft Ads Business Logo Extension (BETA)AInspect
Attach the business logo to a Microsoft Ads (Bing) text ad for brand recognition. BETA. References a single image-library asset (the logo) and optionally pairs it with the business name and domain (which Bing surfaces alongside the logo on its SERP).
ALSO KNOWN AS: business logo, brand logo, logo, company logo, brand mark, mark, identity asset
KEYWORDS: logo, business logo, brand, brand mark, identity, company logo, brand recognition, BETA, microsoft ads, bing, extension
WHEN TO USE:
- "Add our business logo to our Microsoft Ads"
- "Create a Bing logo extension referencing image library ID 123"
- "Attach the Acme Corp logo to our Microsoft Ads search ads for brand lift"
WHEN NOT TO USE:
- Multiple product / lifestyle shots → use create_microsoft_image_extension
- The logo is not yet in the image library — upload it first, then call this with the resulting ID.
- Same logo for Google Ads → use create_google_business_logo_extension
INPUTS:
- image_library_id (required): single image library ID pointing to the logo asset.
- business_name: business name displayed alongside the logo (≤25 chars). Microsoft Ads surfaces this on the SERP.
- domain_name: business domain (≤50 chars). Microsoft Ads surfaces this on the SERP.
EXAMPLE:
create_microsoft_business_logo_extension(
image_library_id=123,
business_name="Acme Corp",
domain_name="acme.com",
)| Name | Required | Description | Default |
|---|---|---|---|
| domain_name | No | ||
| business_name | No | ||
| image_library_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate this is not read-only and not destructive. The description adds useful behavioral context: it references a single existing image-library asset rather than uploading, optionally displays business name/domain on the SERP, and flags BETA status. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The structure is well-organized with WHEN/INPUTS/EXAMPLE sections and front-loaded purpose. Some redundancy exists between the initial text and the repeated 'ALSO KNOWN AS' and 'KEYWORDS' sections, but overall every major section earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a create-style tool with no output schema, the description covers prerequisites (logo must already be in image library), input semantics, an explicit example, and routing to alternatives. This is sufficient for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for parameters. It does so by explaining image_library_id points to the logo asset and clarifying the display behavior and character limits for business_name and domain_name, going beyond raw schema constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Attach') and resource ('business logo' to a Microsoft Ads text ad) and explicitly differentiates itself from the image extension tool, so the agent can identify exactly what this tool does and how it differs from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides concrete 'WHEN TO USE' examples and explicit 'WHEN NOT TO USE' cases, naming alternative tools such as create_microsoft_image_extension and create_google_business_logo_extension. This is clear routing guidance beyond what annotations offer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_callout_extensionCreate Microsoft Ads Callout ExtensionAInspect
Add a short non-clickable selling-point snippet (callout) that appears beneath a Microsoft Ads (Bing) ad — short trust-builder phrases like "Free Shipping", "24/7 Support", "Money-Back Guarantee", or "No Setup Fees". Callouts reinforce value props without taking up headline space.
ALSO KNOWN AS: callout, callout extension, selling point, trust badge, value prop, value proposition, tagline, ad badge
KEYWORDS: callout, selling point, trust signal, value prop, badge, free shipping, money back, guarantee, support, no fees, microsoft ads, bing, extension
WHEN TO USE:
- "Add a 'Free Shipping' callout to our Microsoft Ads library"
- "Create a Bing callout for 24/7 support"
- "Register a new value-prop tag for the holiday Microsoft Ads campaigns"
WHEN NOT TO USE:
- Want a clickable shortcut to a landing page → use create_microsoft_sitelink_extension
- Want a list of named items (e.g. "Brands: Nest, Nexus") → use create_microsoft_structured_snippet_extension
- Same callout for Google Ads → use create_google_callout_extension
- Anything for Facebook / LinkedIn / Reddit — search-channel-only
INPUTS:
- callout_text: visible snippet (1-25 chars).
EXAMPLE:
create_microsoft_callout_extension(callout_text="Free Shipping")| Name | Required | Description | Default |
|---|---|---|---|
| callout_text | Yes | Callout snippet. 1-25 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false (it creates), destructiveHint=false (non-destructive), and openWorldHint=true. The description does not contradict these; it consistently describes a creation operation. However, it adds minimal behavioral context beyond what the annotations imply—no mention of side effects, permissions, or response format. Given the annotations already establish the safety profile, a 3 is appropriate; the description adds context about what a callout is but not deeper behavioral details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headings, front-loading the core definition, then providing usage guidance and examples. It is somewhat verbose with sections for keywords and 'ALSO KNOWN AS', but these aid in natural-language matching. Every section serves a purpose, and it is not bloated with irrelevant details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single parameter, no output schema, and no nested objects, the description is fully sufficient for an agent to call the tool correctly. It explains what the tool does, when to use it, when not to use it, and describes the sole input with an example. Nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (the schema already defines callout_text with min/max lengths). The description adds semantic value by labeling it as a 'visible snippet' and providing examples of valid callout text ('Free Shipping', '24/7 Support'). This helps the agent understand the intended content type beyond the raw schema definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: adding a non-clickable selling-point snippet (callout) beneath Microsoft Ads. It provides concrete examples of callout text and explicitly distinguishes itself from sibling extensions (sitelink, structured snippet). The verb 'Add' and resource 'Microsoft Ads Callout Extension' are specific, and it is clearly differentiated from the Google and Microsoft variants.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has dedicated 'WHEN TO USE' and 'WHEN NOT TO USE' sections with concrete example user queries and explicit exclusions. It names alternative tools (create_microsoft_sitelink_extension, create_microsoft_structured_snippet_extension, create_google_callout_extension) and the conditions that should route an agent to them. This leaves no ambiguity about when to invoke this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_image_extensionCreate Microsoft Ads Image Extension (BETA)AInspect
Attach visual imagery (1-20 product / lifestyle shots) to a Microsoft Ads (Bing) text ad to lift click-through. BETA. Re-uses assets already uploaded to the Metadata image library — pass their IDs, not raw files.
ALSO KNOWN AS: image extension, image asset, ad image, visual extension, picture extension, photo extension, hero image
KEYWORDS: image, image extension, photo, picture, visual, hero, asset, library, BETA, microsoft ads, bing, extension, CTR
WHEN TO USE:
- "Attach images to our Microsoft Ads text ad"
- "Add image library IDs 123 and 456 as a Bing image extension"
- "Create a Microsoft Ads image extension showing product photos under our search ads"
WHEN NOT TO USE:
- The image is a logo / brand mark → use create_microsoft_business_logo_extension
- You haven't uploaded the assets yet — image extensions reference library IDs, so upload to the image library first.
- Want to drive clicks via text snippets → use create_microsoft_sitelink_extension / callout
- Same images for Google Ads → use create_google_image_extension
INPUTS:
- image_library_ids (required): 1-20 IDs from the Metadata image library.
- alternative_text: accessibility alt text (≤90 chars).
- display_text: short caption overlaid on the image (≤35 chars). E.g. "Shop Now".
- destination_url: landing page when the image is clicked.
EXAMPLE:
create_microsoft_image_extension(
image_library_ids=[123, 456],
alternative_text="Product hero shot",
display_text="Shop Now",
destination_url="https://example.com/landing",
)| Name | Required | Description | Default |
|---|---|---|---|
| display_text | No | ||
| destination_url | No | ||
| alternative_text | No | ||
| image_library_ids | Yes | 1-20 image-library IDs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds useful behavior beyond annotations: it is BETA, reuses already-uploaded Metadata library assets rather than accepting raw files, and attaches imagery to a text ad. It does not contradict readOnlyHint=false or destructiveHint=false, though it leaves the target-ad selection implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and BETA warning are front-loaded, sections are clearly organized, and the example earns its place. Some redundancy in the ALIASES and KEYWORDS lists and repeated WHEN TO USE phrasings keeps it from being maximally concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Input semantics, prerequisites, and routing are well covered, but the description never states how the target Microsoft Ads text ad is selected. The input schema has no ad/campaign ID, so an agent must infer that the active/current ad or account context is used, which is a meaningful gap for an attach/create tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 25%, but the description compensates by explaining every parameter: image IDs from the Metadata library, alt-text accessibility with ≤90 chars, display-text overlay with ≤35 chars, and destination URL as the landing page. A concrete example further clarifies usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb/resource: it creates/attaches a Microsoft Ads image extension to a Bing text ad, using 1-20 library images. The WHEN NOT TO USE section also disambiguates it from logo, sitelink, callout, and Google-image siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly lists WHEN TO USE triggers and WHEN NOT TO USE exclusions with named alternatives: logos → create_microsoft_business_logo_extension, text snippets → sitelink/callout, Google Ads → create_google_image_extension, and missing uploads → upload to the image library first.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_price_extensionCreate Microsoft Ads Price ExtensionAInspect
Add a price-list shown beneath a Microsoft Ads (Bing) ad — 3-8 tiles, each with a plan/product name, a short description, a USD amount, and a billing unit. Standard play for SaaS pricing tiers, subscription plans, course catalogs, service menus, or hotel night rates.
ALSO KNOWN AS: price extension, pricing, price list, pricing tiers, plan pricing, subscription pricing, price tiles, rate card, fare list
KEYWORDS: price, pricing, price list, plan, plans, tier, tiers, subscription, monthly, yearly, hourly, daily, fare, rate, cost, dollar, $, USD, microsoft ads, bing, extension
WHEN TO USE:
- "Show our pricing tiers under our Microsoft Ads"
- "Add a Bing price extension with Basic / Pro / Scale plans"
- "Register monthly subscription prices for the Microsoft Ads campaign"
WHEN NOT TO USE:
- Single time-bound discount (Black Friday 20% off, promo code) → use create_microsoft_promotion_extension
- Non-priced offerings list (just names, no amounts) → use create_microsoft_structured_snippet_extension
- Same price list for Google Ads → use create_google_price_extension
INPUTS:
- price_qualifier: prefix shown before each price. UNSPECIFIED (no prefix) | FROM ("From $X") | UP_TO ("Up to $X") | AVERAGE ("Avg $X").
- price_offerings: 3-8 tiles. Each tile:
- url: landing page for that tier (non-blank, ≤2000 chars).
- header: tier name (1-25 chars). E.g. "Basic", "Pro", "Scale".
- description: short tagline (1-25 chars). E.g. "Starter plan".
- amount: USD number (max 999999999.99, two decimals).
- unit: billing cadence. UNSPECIFIED | PER_HOUR | PER_DAY | PER_WEEK | PER_MONTH | PER_YEAR | PER_NIGHT.
EXAMPLE:
create_microsoft_price_extension(
price_qualifier="FROM",
price_offerings=[
{"url": "https://example.com/basic", "header": "Basic",
"description": "Starter plan", "amount": 9.99, "unit": "PER_MONTH"},
{"url": "https://example.com/pro", "header": "Pro",
"description": "Growing teams", "amount": 29.00, "unit": "PER_MONTH"},
{"url": "https://example.com/scale", "header": "Scale",
"description": "Enterprise", "amount": 99.00, "unit": "PER_MONTH"},
],
)| Name | Required | Description | Default |
|---|---|---|---|
| price_offerings | Yes | 3-8 price offerings. | |
| price_qualifier | Yes | Price qualifier shown before the price. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutating operation (readOnlyHint=false), and the description's 'Add' is consistent with that. It adds useful behavioral context about where the extension appears, the 3-8 tile constraint, and required fields per tile. It does not contradict the annotations, though it could go further on post-create behavior such as confirmation or replacement semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headings and front-loaded core purpose. The ALSO KNOWN AS and KEYWORDS sections somewhat overlap, but the WHEN TO USE, WHEN NOT TO USE, INPUTS, and EXAMPLE sections each carry real selection and invocation value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has two parameters, one nested array with five subfields, and no output schema, and the description covers all required invocation knowledge: constraints, enums, field semantics, and an end-to-end example. There is no missing information an agent would need to construct a correct call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description greatly enriches both parameters: it explains price_qualifier display variants with examples ('From $X', 'Up to $X'), details every price_offerings subfield including length, amount limits, and billing units, and provides a full example call. This meaningfully exceeds the schema's terse descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add a price-list shown beneath a Microsoft Ads (Bing) ad', and immediately specifies the count and fields of the tiles. It distinguishes itself from sibling tools such as create_microsoft_promotion_extension, create_microsoft_structured_snippet_extension, and create_google_price_extension, so an agent can tell them apart without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE section gives concrete natural-language triggers ('Show our pricing tiers under our Microsoft Ads'), and the WHEN NOT TO USE section names explicit alternatives for promotions, non-priced snippets, and Google Ads. This gives both positive and negative selection guidance, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_promotion_extensionCreate Microsoft Ads Promotion ExtensionAInspect
Add a time-bound promotional offer (sale, discount, promo code) that shows under a Microsoft Ads (Bing) ad — flag a holiday occasion, pick the discount style (% off or $ off), optionally attach a promo code or "on orders over $X" qualifier, and set the start/end window. Standard for Black Friday, Cyber Monday, seasonal sales, flash discounts, holiday campaigns.
ALSO KNOWN AS: promotion, promo, discount, sale, offer, coupon, promo code, voucher, deal, holiday sale, seasonal offer
KEYWORDS: promotion, promo, promo code, coupon, sale, discount, offer, deal, black friday, cyber monday, holiday, christmas, summer sale, percent off, dollar off, $ off, voucher, microsoft ads, bing, extension
WHEN TO USE:
- "Set up a Black Friday 20% off Microsoft Ads promotion for our Pro plan"
- "Add a Bing holiday promo extension with code SUMMER2026"
- "Register a Microsoft Ads sale: $50 off orders over $200"
WHEN NOT TO USE:
- Permanent pricing tiers (not a limited-time discount) → use create_microsoft_price_extension
- Plain "Free Shipping" badge → use create_microsoft_callout_extension
- Same promotion for Google Ads → use create_google_promotion_extension
INPUTS (required):
- occasion: holiday/event tag (NONE if no specific occasion). Available: NONE, BACK_TO_SCHOOL, BLACK_FRIDAY, BOXING_DAY, CARNIVAL, CHINESE_NEW_YEAR, CHRISTMAS, CYBER_MONDAY, DIWALI, EASTER, EID_AL_ADHA, EID_AL_FITR, END_OF_SEASON, EPIPHANY, FALL_SALE, FATHERS_DAY, HALLOWEEN, HANUKKAH, HOLI, INDEPENDENCE_DAY, LABOR_DAY, MOTHERS_DAY, NATIONAL_DAY, NAVRATRI, NEW_YEARS, PARENTS_DAY, PASSOVER, RAMADAN, ROSH_HASHANAH, SINGLES_DAY, SONGKRAN, SPRING_SALE, ST_NICHOLAS_DAY, SUMMER_SALE, VALENTINES_DAY, WINTER_SALE, WOMENS_DAY, YEAR_END_GIFT.
- url: landing page for the promotion.
- item: what's on sale (1-20 chars). E.g. "Pro subscription".
- category_type: discount style.
* MONETARY → "$X off". Provide category_amount.
* UP_TO_MONETARY → "Up to $X off". Provide category_amount.
* PERCENT → "X% off". Provide category_percent (≤100).
* UP_TO_PERCENT → "Up to X% off". Provide category_percent (≤100).
- details_type: optional qualifier.
* NONE → no qualifier.
* ON_ORDERS_OVER → "on orders over $X". Provide details_amount.
* PROMO_CODE → "with code XXXX". Provide details_promo_code (≤15 chars).
- start_date / end_date: ISO-8601 in pattern "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" (e.g. 2026-11-25T00:00:00.000Z). Both must be today or in the future.
INPUTS (optional, see category_type / details_type above):
- category_amount, category_percent, details_promo_code, details_amount.
EXAMPLE — Black Friday 20% off Pro with promo code:
create_microsoft_promotion_extension(
occasion="BLACK_FRIDAY",
url="https://example.com/sale",
item="Pro subscription",
category_type="PERCENT", category_percent=20,
details_type="PROMO_CODE", details_promo_code="BF2026",
start_date="2026-11-25T00:00:00.000Z",
end_date="2026-11-30T23:59:59.000Z",
)| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| item | Yes | ||
| end_date | Yes | ISO-8601 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". Future or present. | |
| occasion | Yes | ||
| start_date | Yes | ISO-8601 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'". Future or present. | |
| details_type | Yes | ||
| category_type | Yes | ||
| details_amount | No | Threshold USD amount; supply when details_type is ON_ORDERS_OVER. | |
| category_amount | No | USD amount; supply when category_type is MONETARY or UP_TO_MONETARY. | |
| category_percent | No | Percent (≤100); supply when category_type is PERCENT or UP_TO_PERCENT. | |
| details_promo_code | No | Promo code; supply when details_type is PROMO_CODE. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false, correctly indicating a non-destructive write operation. The description elaborates on the behavior: it creates a time-bound offer with specific discount styles and qualifiers, and provides the exact date format. It doesn't mention potential side effects like limits on the number of active extensions or whether the extension attaches to all ads in a campaign, but the core behavior is clearly disclosed and consistent with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is well-organized with clear sections (ALSO KNOWN AS, KEYWORDS, WHEN TO USE, WHEN NOT TO USE, INPUTS, EXAMPLE) that aid scanning. While the KEYWORDS section is somewhat redundant for an agent, it doesn't detract from the core message. The main purpose is front-loaded, and the detailed parameter guidance is appropriately placed. It is verbose but justifiably so given the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but for a creation tool the return value is likely straightforward. The description covers all inputs, enum constraints, conditional parameters, date format, and provides a realistic example. It doesn't mention any prerequisites like having a Microsoft Ads account or connection, but these are implicit in the domain. Overall, an agent has enough information to call the tool correctly without external documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 55%, with some parameters (url, item) lacking descriptions in the schema. The description compensates by exhaustively listing every required and optional parameter, explaining the meaning of each enum value (e.g., category_type with MONETARY/PERCENT and their conditional requirements) and providing an example call. It adds significant semantic context that the schema alone does not provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Add a time-bound promotional offer... that shows under a Microsoft Ads (Bing) ad'. It clearly distinguishes itself from siblings via the 'WHEN NOT TO USE' section, naming create_microsoft_price_extension, create_microsoft_callout_extension, and create_google_promotion_extension as alternatives. An agent can immediately grasp what this tool does and how it differs from related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes dedicated 'WHEN TO USE' and 'WHEN NOT TO USE' sections with concrete examples and explicit alternative tool names. It states conditions like 'Permanent pricing tiers... use create_microsoft_price_extension' and 'Plain Free Shipping badge... use create_microsoft_callout_extension'. This leaves no ambiguity about when to select this tool over its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_sitelink_extensionCreate Microsoft Ads Sitelink ExtensionAInspect
Add an extra clickable shortcut (sitelink) that appears beneath a Microsoft Ads (Bing) ad — helpful deep-links like "See Pricing", "Book a Demo", or "Contact Sales" with two short description lines. Sitelinks lift click-through rate by giving searchers alternate landing paths to the same advertiser.
ALSO KNOWN AS: sitelink, site link, extra link, ad link, secondary link, deep link, additional link, jump link
KEYWORDS: sitelink, site link, link, deep link, shortcut, microsoft ads, bing, extension, pricing link, demo link, contact link, landing page, CTR, click through
WHEN TO USE:
- "Add a sitelink to our Microsoft Ads / Bing library"
- "Create a 'See Pricing' / 'Book a Demo' / 'Contact Sales' link extension for Bing"
- "Register a new Microsoft Ads sitelink for the homepage redesign"
WHEN NOT TO USE:
- Want a non-clickable selling-point snippet ("Free Shipping", "24/7 Support") → use create_microsoft_callout_extension
- Want a labeled list of offerings (e.g. "Brands: Nest, Nexus") → use create_microsoft_structured_snippet_extension
- Same sitelink for Google Ads → use create_google_sitelink_extension (library entries are per-channel)
- Anything for Facebook / LinkedIn / Reddit — ad extensions are a search-channel-only concept
INPUTS (all required):
- url: destination the sitelink opens.
- link_text: visible link text (1-25 chars).
- description1: first description line under the link (1-35 chars).
- description2: second description line (1-35 chars).
EXAMPLE:
create_microsoft_sitelink_extension(
url="https://example.com/pricing",
link_text="See Pricing",
description1="Plans for every team size",
description2="Start free, upgrade anytime",
)
Returns the persisted extension (id, externalId, type=SITELINK, channel=MICROSOFT_ADS). A 400 usually means a character-limit was exceeded.| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | Destination URL the sitelink points to (non-blank). | |
| link_text | Yes | Visible link text. 1-25 characters. | |
| description1 | Yes | First description line. 1-35 characters. | |
| description2 | Yes | Second description line. 1-35 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutation (readOnlyHint false) and non-destructive (destructiveHint false). The description adds that it returns the persisted extension with id, externalId, type, and channel, and that a 400 error usually indicates a character-limit issue. However, it does not mention prerequisites, idempotency, or duplicate handling. The added behavioral context is useful but not exhaustive; given the annotations, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headings (ALSO KNOWN AS, KEYWORDS, WHEN TO USE, INPUTS, EXAMPLE) and the core purpose is front-loaded. However, it is verbose: the KEYWORDS and alias sections are redundant with the main description and add noise. The WHEN NOT TO USE and EXAMPLE are valuable, but the overall length could be trimmed without losing critical information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, so the description correctly explains the return structure (persisted extension with id, externalId, type, channel) and error semantics (400 on char-limit). It also gives a concrete example. For a create tool with 4 required parameters, this is sufficient for an agent to call it correctly. The only minor gap is not explaining whether the sitelink is added to a library versus directly to a campaign, but that is not critical for invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (all four parameters have descriptions with character limits). The description reiterates the char limits and adds context like 'destination the sitelink opens' and 'visible link text', but these are marginal over the schema. Since the schema already documents each parameter, the description adds little extra meaning, warranting a baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (add a sitelink) and the resource (Microsoft Ads/Bing ad), and it distinguishes from siblings by naming alternatives in WHEN NOT TO USE. It also provides aliases and keywords that help match user intent. This is a specific verb+resource definition that is not confused with other extension types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly includes WHEN TO USE examples and WHEN NOT TO USE conditions, naming exact sibling tools (create_microsoft_callout_extension, create_microsoft_structured_snippet_extension, create_google_sitelink_extension) and the conditions that select them. This leaves no ambiguity about when to call this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_microsoft_structured_snippet_extensionCreate Microsoft Ads Structured Snippet ExtensionAInspect
Add a labeled list of offerings (structured snippet) shown beneath a Microsoft Ads (Bing) ad — a category header plus 3-10 short items, e.g. header "Brands" with values "Nest", "Nexus", "Chromebook", or header "Services" with "Hosting", "DNS", "CDN". Helps searchers self-qualify before clicking.
ALSO KNOWN AS: structured snippet, snippet, category list, offering list, header values, product list, service list
KEYWORDS: structured snippet, snippet, header, values, brands, services, products, courses, destinations, list, category, microsoft ads, bing, extension
WHEN TO USE:
- "Add a structured snippet listing our service tiers on Microsoft Ads"
- "Create a Bing snippet under 'Brands' with Nest, Nexus, Chromebook"
- "Register a list of supported integrations as a Microsoft Ads snippet extension"
WHEN NOT TO USE:
- Want a single phrase (e.g. "Free Shipping") → use create_microsoft_callout_extension
- Want clickable links to subpages → use create_microsoft_sitelink_extension
- Want a pricing table (with amounts) → use create_microsoft_price_extension
- Same snippet for Google Ads → use create_google_structured_snippet_extension
INPUTS:
- header: snippet category title (1-25 chars). Microsoft Ads mirrors Google's predefined header vocabulary ("Brands", "Models", "Service catalog", "Insurance coverage", etc.) — pass the chosen header string here.
- values: 3-10 items, each 1-25 chars.
EXAMPLE:
create_microsoft_structured_snippet_extension(
header="Brands",
values=["Nest", "Nexus", "Chromebook"],
)| Name | Required | Description | Default |
|---|---|---|---|
| header | Yes | Snippet header. 1-25 characters. | |
| values | Yes | 3-10 snippet values, each 1-25 characters. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false, covering the safety profile. The description adds context about the creation action and the resulting structure (header plus 3-10 values), plus the note that Microsoft Ads mirrors Google's header vocabulary. It does not mention side effects like requiring an existing account or campaign, but for a create operation this is not a significant gap given the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (purpose, keywords, when to use, when not, inputs, example) and is front-loaded with the core purpose. While the 'KEYWORDS' section adds some redundancy, the overall organization makes it easy to scan, and every other section earns its place, especially the disambiguation guidance. It is longer than minimal but justified by the need to differentiate among many sibling tools.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter create tool, the description is remarkably complete. It covers what the tool does, when to use it, when not to use it (with explicit alternatives), parameter semantics with an example call, and even hints at the header vocabulary. Since there is no output schema, the description doesn't need to explain return values. An agent has all the information needed to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes both parameters with lengths and basic descriptions (100% coverage), so baseline is 3. The description adds value by providing example values ('Brands' with 'Nest', 'Nexus', 'Chromebook'), explaining the header vocabulary mirroring Google's predefined list, and clarifying that values are short items. This goes beyond the schema's minimal constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Add a labeled list of offerings (structured snippet) shown beneath a Microsoft Ads (Bing) ad'. It also provides concrete examples of headers and values, and explicitly differentiates from sibling tools in the 'WHEN NOT TO USE' section, naming alternatives like callout, sitelink, price, and Google snippet extensions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes dedicated 'WHEN TO USE' and 'WHEN NOT TO USE' sections. It lists example user requests that should trigger this tool, and explicitly routes to alternative tools for other scenarios, e.g., 'Want a single phrase → use create_microsoft_callout_extension' and 'Same snippet for Google Ads → use create_google_structured_snippet_extension'. This is exactly what an agent needs to select the correct tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_native_structure_campaignCreate Campaign — Channel First / Native Structure (N×N×N)AInspect
Create a multi-channel campaign using the platform's "Channel First Structure" (N×N×N) — the UI also labels it "Native Structure" / "Platform-First Structure". Your audiences, ads, and offers are organized into the ad platform's NATIVE structure (the WizNativeAdContainer entity) and optimized TOGETHER by the platform's own algorithm — ~1 experiment per channel (LinkedIn is the only exception: one experiment per container), with unified reporting and pacing. You specify the structure as explicit per-container groupings (each container is one audience + its ad_offers rows); the "N×N×N" label refers to the native structure holding your full set of audiences, ads, and offers together (it is NOT one isolated experiment per combination — that's Precision Optimization, create_campaign). Platform product copy: "Traditional hierarchical setup that leverages native platform algorithms while maintaining Metadata's pacing control, unified user experience and reporting." Sets channel.structureType=NATIVE.
KEYWORDS (for tool discovery — many users ask by the math, not the product name): NxNxN, N×N×N, "NxNxN campaign", Channel First Structure, Native Structure, Platform-First Structure, channel-first, platform-first, native platform structure, WizNativeAdContainer, container-based campaign, traditional / hierarchical structure, unified reporting.
NAMING CONVENTION (from the platform UI's "Campaign Structure" selector — match these exact labels):
• "Channel First Structure (NxNxN)" = THIS tool (`create_native_structure_campaign`); the UI also shows "Native Structure" / "Platform-First Structure". Audiences/ads/offers grouped in the platform's native structure and optimized together (~1 experiment per channel). "native" / "platform" here = the native ad platform (LinkedIn / Facebook / Google) whose algorithms this leans on — and structureType=NATIVE matches.
• "Precision Optimization (1x1x1)" = the OTHER tool, `create_campaign` — each audience×ad×offer combination tested as its own isolated experiment. Metadata's signature approach; the DEFAULT.
Routing anchor: "native" / "channel first" / "platform first" / "NxNxN" → this tool; "precision" / "1x1x1" → create_campaign.
════════════════════════════════════════════════════════════════════════════════
WARNING: TWO CAMPAIGN-CREATION TOOLS EXIST — READ BEFORE PICKING ONE
════════════════════════════════════════════════════════════════════════════════
CRITICAL: REMEMBER — HOW TO CHOOSE THE STRUCTURE (the user's decision always wins):
1. If the user explicitly names one, RESPECT IT — "native" / "Native Structure" / "Channel First" / "Platform-First" / "NxNxN" → create_native_structure_campaign (this tool); "precision" / "Precision Optimization" / "1x1x1" → create_campaign.
2. ELSE, if the request involves MANY ads AND audiences (Precision Optimization makes one experiment per combination — a large experiment count), ASK the user which structure they want before creating — do not guess.
3. OTHERWISE, DEFAULT to Precision Optimization (1×1×1) → create_campaign (NOT this tool).
The two build structurally different, non-swappable campaigns — so once the user decides, respect that decision for the rest of the campaign.
USE THIS TOOL (`create_native_structure_campaign`) — "Channel First" / "Native Structure" (N×N×N) — WHEN:
• The user says "native", "Native Structure", "Channel First Structure", "channel-first", "Platform-First Structure", "platform-first", "NxNxN", "N×N×N", "WizNativeAdContainer", or asks for the traditional / hierarchical / native-platform structure.
• The user wants the ad platform's native structure to group and optimize audiences/ads/offers together (~1 experiment per channel, unified reporting) rather than an isolated experiment per combination.
• The user provides explicit per-container groupings of one audience + its (ad, offer) pairs.
USE `create_campaign` ("Precision Optimization", 1×1×1) INSTEAD — DO NOT USE THIS TOOL — WHEN:
• The user says "Precision Optimization", "precision", "1x1x1", "1×1×1", or wants every audience×ad×offer combination tested separately in its own experiment.
• The user wants maximum budget control / fastest per-combination learning.
• No structure was specified — Precision Optimization (`create_campaign`) is the DEFAULT.
If you're unsure whether the user wants isolated per-combination experiments (→ `create_campaign`, Precision Optimization) or the native-platform grouped structure (→ this tool, Channel First), ASK which structure they want — switching modes after creation requires rebuilding the campaign from scratch.
The two tools produce structurally different campaigns on the backend (channel.structureType = METADATA for create_campaign, = NATIVE for this tool) and are NOT swappable mid-campaign. Pick correctly the first time.
════════════════════════════════════════════════════════════════════════════════
WHEN TO USE THIS TOOL:
- The user explicitly asks for "Channel First Structure" / "Native Structure" / "Platform-First Structure" / N×N×N / WizNativeAdContainer / the native-platform structure.
- You want the ad platform's algorithm to optimize audiences/ads/offers together under a unified structure (~1 experiment per channel) instead of isolating every combination.
- You want a compact, platform-managed experiment footprint with unified reporting.
WHEN NOT TO USE THIS TOOL:
- The user wants "Precision Optimization" (1×1×1) — every combination tested as its own isolated experiment — use `create_campaign`.
- No structure was specified (default is Precision Optimization) — use `create_campaign`.
CAMPAIGN TYPES (same as create_campaign):
1. "Lead Gen" — only Lead Gen (LG) offers allowed in any container.
2. "Brand Awareness" — both LG and LP offers allowed.
WARNING: OFFER-CHANNEL CHANNEL-LOCK STILL APPLIES
Lead Gen offers are channel-locked at the offer's creation time. A container under `linkedin.containers` MUST reference an offer whose data.channel='LINKEDIN' (or any Landing Page offer). Cross-channel reuse silently produces a non-serving campaign. The server does NOT validate the pairing. Same rules as create_campaign:
- linkedin.containers[i].ad_offers[].offer → LINKEDIN-locked LG OR any LP
- facebook.containers[i].ad_offers[].offer → FACEBOOK-locked LG OR any LP
- instagram.containers[i].ad_offers[].offer → FACEBOOK/INSTAGRAM-locked LG OR any LP
- google.containers[i].ad_offers[].offer → Landing Page offers ONLY (Google Ads has no native LG form support)
- reddit.containers[i].ad_offers[].offer → Landing Page offers ONLY (Reddit has no native LG form support)
- microsoft.containers[i].ad_offers[].offer → MICROSOFT_ADS-locked LG OR any LP
Each container is one audience × a LIST of (ad, offer) pairs (`ad_offers`, 1+). Put several pairs in one container to group multiple ads/offers under the same audience — the platform's native ad-set with multiple Ad/Offer rows. "1 audience → 3 ads → 1 offer" is ONE container whose `ad_offers` holds 3 pairs that repeat the same `offer` id. (Each pair is exactly one ad with one offer; to run the same audience as two separate ad-sets, send two containers instead.)
WARNING: SEARCH CHANNELS ARE KEYWORD-FIRST — `audience` IS OPTIONAL FOR GOOGLE ADS & MICROSOFT ADS
Google/Microsoft search ad groups are keyword-targeted, so a search container may OMIT `audience` and run keyword-only (just keywords + ad_offers). The platform allows audience-less native search containers, so this tool no longer forces an audience there. `audience` STAYS REQUIRED for the audience-targeted social channels (LinkedIn / Facebook / Instagram / Reddit). A search container with neither an audience nor keywords has nothing to target and is rejected.
REQUIRED FIELDS:
- campaignType: "Lead Gen" | "Brand Awareness"
- name: unique campaign name
- startDate / endDate: YYYY-MM-DD
- budgetGroup: budget group name
- At least one channel block with a non-empty containers list
PER-CHANNEL SHAPE:
Every channel block (linkedin / facebook / instagram / google / reddit / microsoft) takes:
containers: [
{
name: "string (<=255 chars) — visible in the platform UI",
audience: "audience name (resolved server-side via the same matched-poll create_campaign uses). REQUIRED for LinkedIn/Facebook/Instagram/Reddit; OPTIONAL for Google/Microsoft search (omit it for keyword-only ad groups)",
ad_offers: [ {ad: <int WizCreative ID>, offer: <int offer ID>}, ... ] // 1+ Ad/Offer pairs sharing this container's audience; repeat the same offer id to run several ads on it,
target_group: "optional Targeting Group name (singular — one per container)",
exclude_audience: "optional audience name to use as the exclude group for this container"
}
]
SEARCH-CHANNEL EXTRAS (Google Ads + Microsoft Ads, per container):
keywords: ["string", ...] // free-text phrases — created in the keyword library and grouped into this container's keyword group
keyword_ids: [<int>, ...] // optional; existing keyword-library IDs (from list_keywords) to put in this container's group — unioned with `keywords`
match_type: "PHRASE"|"BROAD"|"EXACT" // optional; match type for this container's keyword group (default PHRASE)
negative_keyword_lists: ["name", ...] // optional; applied at the channel level
On a search channel `audience` is OPTIONAL: a keyword-only container (keywords + ad_offers, no audience) is valid and is how non-brand / pure-keyword search is normally structured. You can still pass an audience to layer one on. The keyword group is created and linked to the container automatically. A search container with neither an audience nor keywords (`keywords`/`keyword_ids`) is rejected (nothing to target).
AUDIENCE NAME RESOLUTION:
- `audience` and `exclude_audience` are NAMES, not IDs. Same lookup path as create_campaign — the tool waits up to ~20s per channel for a freshly-created audience to become attachable (firmographics + FB/IG can take 8-15s).
- Audience names are resolved BEFORE any container elements are created: a container whose `audience` cannot be resolved is dropped up front (no keyword group or other element is left behind for it) and the failure is reported in the response `errors[]`. The error states whether retrying can help ("may still be matching") or not ("not available on this channel") — do NOT blind-retry the latter. The rest of the campaign still gets built.
- On Google/Microsoft search containers `audience` may be omitted entirely (keyword-only) — only names that are actually provided are resolved, so leaving it out costs no polling and raises no error.
AD AND OFFER ARE IDS (one `ad_offers` pair = one ad + one offer):
- `ad` is the ID returned by `create_update_image_ad` or `create_update_video_ad`.
- `offer` is the ID returned by `create_update_offer`. The tool looks up each unique offer to discover whether it's a Landing Page or Lead Gen Form and routes it into the right `nativeAds[].landingPageId` vs `nativeAds[].leadGenFormId` slot. Every pair becomes one `nativeAds[]` entry under the container.
BID STRATEGY (automatic):
Same defaults as create_campaign:
- LinkedIn / Facebook / Instagram → AUTO_BID
- Google Ads / Microsoft Ads → TARGET_SPEND (device modifiers reset)
- Reddit → objective-driven, mirroring the platform UI:
Lead Gen forces CLICKS (Traffic) + AUTO_BID; Brand Awareness keeps
IMPRESSIONS + MANUAL_BID. Adjust later with update_reddit_channel_settings.
WHAT THE TOOL DOES FOR YOU (single call, no follow-up needed):
Creates the campaign shell and its budget group, enables each requested
channel and sets it to the NATIVE structure, builds the per-container
keyword group on Google / Microsoft Ads search channels, creates one
native ad container per grouping with its ad/offer pairs, applies the
bid strategy, and sets the schedule. The response reflects the final
campaign state — you do not need to sequence or repeat any of this.
RESPONSE: Same top-level shape as create_campaign (`success`, `campaign_id`, `campaign_url`, `status`, `optimization_group`, `summary`, `full_response`). The per-channel breakdown returns a `containers` array — `[{id, name, experiment_id, audience_group_id, targeting_group_id, group_exclude_id, keyword_group_id, native_ads: [{id, ad_id, landing_page_id, lead_gen_form_id}]}]` — instead of the legacy `audiences`/`ad_groups`/`lead_gen_forms` arrays. On partial failures, returns success=false plus `errors[]` with per-container detail.
EXAMPLE (Lead Gen, LinkedIn-only, two containers):
create_native_structure_campaign(campaign_data={
"campaignType": "Lead Gen",
"name": "Q3_ABM_Native_2026",
"startDate": "2026-06-01",
"endDate": "2026-08-31",
"budgetGroup": "BoFu",
"linkedin": {
"containers": [
{"name": "IT Mgrs > Demo > Form",
"audience": "IT Managers - NA",
"ad_offers": [{"ad": 156502, "offer": 57538}]},
{"name": "CTOs > Demo > Form",
"audience": "CTOs - Tech",
"ad_offers": [{"ad": 156485, "offer": 57504}]}
]
}
})
EXAMPLE (one audience → 3 ads on the SAME offer, ONE container — the multi-ad ad-set):
create_native_structure_campaign(campaign_data={
"campaignType": "Brand Awareness",
"name": "Q3_3Ads_1Offer_2026",
"startDate": "2026-06-01",
"endDate": "2026-07-31",
"budgetGroup": "Brand",
"facebook": {
"containers": [
{"name": "ICP > 3 creatives > TOF offer",
"audience": "26-Q2-ICP-AllPersonas-NA",
"ad_offers": [
{"ad": 210801, "offer": 67269},
{"ad": 210802, "offer": 67269},
{"ad": 210803, "offer": 67269}
]}
]
}
})
EXAMPLE (Brand Awareness, Google + LinkedIn, with keywords):
create_native_structure_campaign(campaign_data={
"campaignType": "Brand Awareness",
"name": "Q3_Brand_Native_2026",
"startDate": "2026-06-01",
"endDate": "2026-07-31",
"budgetGroup": "Brand",
"linkedin": {
"containers": [
{"name": "Professionals A",
"audience": "Professional Audience",
"ad_offers": [{"ad": 173669, "offer": 57538}]}
]
},
"google": {
"containers": [
{"name": "CRM Search",
"audience": "Tech Decision Makers",
"ad_offers": [{"ad": 175260, "offer": 57600}],
"keywords": ["crm software", "lead gen tools"],
"negative_keyword_lists": ["Competitor Brands"]}
]
}
})
EXAMPLE (Brand Awareness, Google keyword-only — NO audience, pure non-brand search):
create_native_structure_campaign(campaign_data={
"campaignType": "Brand Awareness",
"name": "Q3_NonBrand_Search_2026",
"startDate": "2026-06-01",
"endDate": "2026-07-31",
"budgetGroup": "Search",
"google": {
"containers": [
{"name": "Incident Response",
"ad_offers": [{"ad": 210804, "offer": 67269}],
"keywords": ["incident response platform", "on-call alerting"],
"negative_keyword_lists": ["Competitor Brands"]}
# note: no "audience" key — keyword-targeted ad group
]
}
})
BEST PRACTICES:
1. Decide each container's audience and its `ad_offers` pairs up front — this tool will not invent pairings for you. Group several ads under one audience by adding pairs to `ad_offers`. On Google/Microsoft search, audience-less (keyword + ad_offers) containers are valid; pure non-brand search normally has no audience. On Reddit, targeting is the `target_group` (create_reddit_target_group) and `audience` is optional — an audience only exists on a channel the account has CONNECTED, so naming one on a disconnected Reddit loses the container.
2. Use descriptive container names — they show up in the platform UI as the ad-set/ad-group label.
3. For Google Ads, put related keywords in the same container (each container becomes one keyword group). Don't pile dozens of unrelated keywords into a single container.
4. Use Brand Awareness for any container that needs Landing Page offers — Lead Gen campaigns reject LP offers.
5. The campaign URL is returned in the response: https://platform.metadata.io/hub/advertise/campaigns/{campaign_id}| Name | Required | Description | Default |
|---|---|---|---|
| campaign_data | Yes | Complete Channel First / Native Structure (N×N×N) campaign configuration. Each channel takes a `containers` list; each container groups one audience with an `ad_offers` list of {ad, offer} pairs. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations carrying only readOnlyHint=false / destructiveHint=false, the description carries the full burden and exceeds it: it discloses the ~20s audience-resolution wait, that unresolvable containers are dropped up front with failures reported in errors[], partial-failure behavior (success=false + errors[]), that the server does NOT validate offer-channel pairing (silent non-serving), per-channel bid strategy defaults, and keyword-only search container validity. This is rich behavioral context far beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is heavily bloated with redundancy. The tool-vs-create_campaign disambiguation is stated at least four times (naming-convention section, the WARNING box with the same numbered list, the USE THIS/INSTEAD sections, and the WHEN TO USE/NOT sections). The keywords list repeats the routing terms. While front-loaded with a strong opening sentence, most of the middle could be cut by 60% without losing information. This is over-specification, not conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool this complex — six channels, nested containers, per-channel keyword groups, search-channel exclusions, and no output schema — the description is remarkably complete. It documents required fields, per-channel shape, search extras, bid strategy, response shape (containers array with native_ads detail), error semantics, and four worked examples covering LinkedIn-only, multi-ad ad-set, Google+LinkedIn with keywords, and keyword-only search. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds genuine meaning on top: container semantics (one audience + ad_offers list), the multi-ad pattern ('1 audience → 3 ads → 1 offer' is ONE container with repeated offer ids), the keyword-only container validity for Google/Microsoft, and audience NAME resolution rules. This exceeds what the schema alone conveys, justifying a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Create a multi-channel campaign using the platform's Channel First Structure (N×N×N)', and immediately names the underlying entity (WizNativeAdContainer). It sharply differentiates from the sibling create_campaign (Precision Optimization 1×1x1) with explicit structureType values (NATIVE vs METADATA), so an agent cannot confuse the two tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Exceptional. A dedicated warning box gives a numbered decision procedure: respect an explicitly named structure, ASK when many ads AND audiences are present, otherwise DEFAULT to create_campaign. Dedicated 'USE THIS TOOL WHEN / USE create_campaign INSTEAD WHEN' sections spell out the exact triggers and alternatives, including the ambiguous case where the agent should ask. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_negative_keywords_listCreate Negative Keywords ListAInspect
Create a new negative keywords list in the Metadata platform with Google Ads integration.
PURPOSE:
Batch create a negative keywords list that can be used in Google Ads campaigns to exclude specific search terms
from triggering your ads. Use this tool to build negative keyword exclusion lists for campaign optimization
and to prevent wasted ad spend on irrelevant searches.
ACCOUNT LIMIT:
WARNING: MAXIMUM 20 NEGATIVE KEYWORDS LISTS PER ACCOUNT
Users can have a maximum of 20 negative keyword lists. The system will validate this limit
before creating a new list and return an error if the limit has been reached.
To create a new list, you must delete or archive existing lists to free up space.
WHEN TO USE:
- Create a new negative keywords list for Google Ads campaigns
- Build competitor blocking lists (block competitor brand names)
- Create category exclusions (block unwanted product categories)
- Create seasonal exclusion lists (block irrelevant seasonal terms)
- Build intent-based negative lists (block non-commercial searches)
- Prevent wasted spend on irrelevant keywords
- Manage brand protection by blocking misused terms
KEY FEATURES:
- BATCH CREATION: Create one or more negative keywords in a single request
- MATCH TYPE CONTROL: Specify match type for all keywords (EXACT, PHRASE, BROAD)
- FLEXIBLE NAMING: Custom names for organizing negative keyword lists
- GOOGLE ADS INTEGRATION: Lists are created ready for use in Google Ads campaigns
- SIMPLE INTERFACE: Just provide keywords as strings, API handles formatting
- AUTOMATIC VALIDATION: System checks against 20-list limit before creation
KEYWORD MATCH TYPES:
The 'matchType' parameter controls how broadly the negative keyword blocks ads:
1. EXACT ("Exact Match"):
- Blocks ads only for searches that exactly match the keyword
- Most restrictive and precise blocking
- Example: Keyword "free" with EXACT blocks only searches for "free", not "free shipping"
- Best for: High-value keyword protection, brand safety
2. PHRASE ("Phrase Match"):
- Blocks ads when the keyword appears as a phrase within the search
- Moderate blocking scope
- Example: Keyword "vintage furniture" with PHRASE blocks "vintage furniture sale" but not "furniture vintage"
- Best for: Competitive category blocking
3. BROAD ("Broad Match"):
- Blocks ads for searches containing any of the keyword terms
- Least restrictive and broadest blocking
- Example: Keyword "free" with BROAD blocks any search containing "free"
- Best for: General category exclusions
MATCH TYPE SELECTION GUIDE:
- Use EXACT for specific brand names or exact competitor terms
- Use PHRASE for specific multi-word concepts or phrases
- Use BROAD for general categories or very broad exclusions
LIST NAMING CONVENTIONS:
- Use descriptive names that indicate the list's purpose
- Examples: "Competitor Brands", "Low Intent Keywords", "Seasonal Exclusions"
- Avoid special characters - use hyphens or underscores for clarity
- Keep names concise and meaningful
BATCH SIZE RECOMMENDATIONS:
- Small batches (1-10 keywords): For targeted blocking
- Medium batches (10-50 keywords): For category-based lists
- Large batches (50+ keywords): For comprehensive blocking lists
- Maximum recommended: 100+ keywords per list
NEGATIVE KEYWORDS VS POSITIVE KEYWORDS:
- Positive keywords: Terms you WANT to show ads for (create_keywords)
- Negative keywords: Terms you DON'T want to show ads for (create_negative_keywords_list)
- Use together for optimal campaign performance
COMMON USE CASES:
1. Create competitor blocking list (EXACT match):
create_negative_keywords_list(
name="Competitor Brands",
keywords=["competitor a", "competitor b"],
match_type="EXACT"
)
2. Create low-intent keyword list (BROAD match):
create_negative_keywords_list(
name="Low Intent Keywords",
keywords=["free", "how to", "tutorial"],
match_type="BROAD"
)
3. Create job seeker exclusion list (PHRASE match):
create_negative_keywords_list(
name="Job Seekers",
keywords=["job search", "hiring", "career"],
match_type="PHRASE"
)
4. Create seasonal exclusion list:
create_negative_keywords_list(
name="Summer Sale Exclusions",
keywords=["winter coats", "snow gear"],
match_type="PHRASE"
)
5. Create product category exclusions:
create_negative_keywords_list(
name="Non-Ecommerce",
keywords=["news", "forum", "wikipedia"],
match_type="EXACT"
)
PARAMETERS:
- name: Required. Name of the negative keywords list (string)
Example: "Competitor Brands", "Low Intent Keywords"
Use descriptive, meaningful names for easy identification
- keywords: Required. Array of keyword strings to block
Example: ["raichu", "blastoise", "charizard"]
- Minimum: 1 keyword
- Recommended maximum: 100+ keywords per request
- Each item is a simple string representing the keyword
- matchType: Required. Match type for all keywords - EXACT, PHRASE, or BROAD
Example: "EXACT"
Options: EXACT (exact match), PHRASE (phrase match), BROAD (broad match)
RESPONSE FORMAT:
Returns a response containing:
- Confirmation of the negative keywords list creation
- List ID for future reference and management
- Success/failure status
- Details of keywords added to the list
VALIDATION NOTES:
- Name is required and must be a non-empty string
- Keywords array must have at least 1 keyword
- matchType must be exactly one of: EXACT, PHRASE, BROAD (case-sensitive)
- Empty strings in keyword list are not allowed
- Duplicate keywords in the batch will be handled by the API
PERFORMANCE TIPS:
- Create lists with related keywords for better organization
- Group keywords by blocking strategy (competitor, seasonal, intent-based)
- Use EXACT match for high-value keyword protection
- Use BROAD match for general category exclusions
- Review created lists regularly and update as needed
- Can use list_negative_keywords_list() to verify creation
INTEGRATION WITH OTHER TOOLS:
- Use list_negative_keywords_list() to find and manage existing lists
- Use create_keywords() for positive keyword lists
- Combine with campaign creation for comprehensive keyword strategies
EXAMPLES:
- create_negative_keywords_list(name="Competitors", keywords=["competitor1"], matchType="EXACT")
- create_negative_keywords_list(name="Free Content", keywords=["free", "no cost"], matchType="BROAD")
- create_negative_keywords_list(name="Brand Safety", keywords=["controversial term"], matchType="PHRASE")
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
lists, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name of the negative keywords list (string). Example: "Competitor Brands", "Low Intent Keywords" | |
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
| keywords | Yes | Array of keyword strings to block. Example: ["raichu", "blastoise", "charizard"] | |
| match_type | Yes | Match type for all keywords. Options: EXACT (exact match), PHRASE (phrase match), BROAD (broad match). Example: 'EXACT' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond annotations: it warns about the 20-list-per-account limit and automatic validation, explains channel separation (GOOGLE_ADS vs MICROSOFT_ADS hold separate lists), and notes that batch creation is supported. It also states the response includes confirmation, list ID, and status. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely thorough and well-structured with clear headings (PURPOSE, WHEN TO USE, KEY FEATURES, MATCH TYPES, etc.). However, it is verbose and repetitive—match type semantics are covered in at least three separate sections (KEYWORD MATCH TYPES, MATCH TYPE SELECTION GUIDE, PARAMETERS) and there are five full use-case examples. Clear structure keeps it usable, but it could be trimmed without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all essential aspects for correct invocation: purpose, when to use, account limits, match types, naming, batch sizes, validation, response format, integration with other tools, and channel scope. Since there is no output schema, it compensates by describing the return values. It is fully complete for a tool of this complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description profoundly enriches parameter meaning. It explains match types (EXACT/PHRASE/BROAD) with detailed blocking behavior and examples, gives naming conventions, batch size recommendations, and validation notes for each parameter. This goes far beyond the schema descriptions and helps an agent choose correct values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a concrete statement: 'Create a new negative keywords list in the Metadata platform with Google Ads integration.' It then clearly differentiates this from related tools (e.g., add_keywords_to_negative_lists, create_keywords) by specifying that this tool builds a new exclusion list. The purpose is unambiguous and the resource is well-defined.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE' section lists concrete scenarios like competitor blocking, category exclusions, and seasonal lists. It explicitly contrasts negative vs positive keywords, points to create_keywords for positive lists, and tells users to use list_negative_keywords_list for verification. The channel scope warning ('never substitute one channel for the other') gives critical usage nuance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_reddit_target_groupCreate Reddit Target GroupAInspect
Create a new Reddit target group with name and targeting criteria (communities, interests, keywords, location).
PREREQUISITE: All references MUST come from search_reddit_criteria. estimate_target_group with channel="REDDIT" first is MANDATORY: verify isMatchCountTooSmall=false and report the reach to the user BEFORE creating. Same bar as create_target_group and update_target_group (PRD-31759). Reddit estimation went live with PRD-31996; before it there was no way to size one of these, which is why a Reddit target group could be created at zero reach with nothing noticing.
USE FOR: "create a Reddit target group named X targeting r/technology", "save this Reddit audience as X".
WARNING: CHANNEL: Only use this tool when the user explicitly asked for a REDDIT target group. Do NOT infer REDDIT from the underlying audience NAMES (e.g. an audience called "Reddit Conquest Mktg LI_n7q" does NOT mean the user wants a REDDIT target group — audience naming is human convention, not a routing signal). Default to create_target_group (LINKEDIN) when channel is unspecified; ask the user if unsure.
TARGETING STRUCTURE (LOCATION must be the FIRST include block with isModifiable=false): { "include": [ { "isModifiable": false, "criteria": [{"type": "LOCATION", "data": { "countries": [229], "states": [] }}], "audiences": [] }, { "isModifiable": true, "criteria": [{"type": "COMMUNITIES", "data": [ {"externalId": "t5_2qh1i", "name": "r/technology"} ]}], "audiences": [] } ], "exclude": { "isModifiable": true, "criteria": [{"type": "KEYWORDS", "data": [{"externalId": "kw_123", "name": "crypto"}]}], "audiences": [] } }
REDDIT CRITERIA TYPES (all references from search_reddit_criteria):
LOCATION: {"countries": [, ...], "states": [, ...]} — arrays of NUMERIC Metadata IDs (use the numeric
idfrom search_reddit_criteria locations, NOT the {id, name} object). MANDATORY FIRST in include, isModifiable=falseCOMMUNITIES: Array of {externalId, name} — subreddits (e.g. r/technology)
INTERESTS: Array of {externalId, name} — Reddit interest categories
KEYWORDS: Array of {externalId, name} — contextual keywords
INCLUDE: Array of rule blocks (AND-joined). EXCLUDE: single object with criteria and audiences.
AUDIENCES (combine with the criteria above to build complex target groups): each include
block and the exclude object also accept an audiences array, so you can mix existing
Metadata audiences with the Reddit criteria in the same block. Get them from the audience
listing tools / get_matched_audiences. Each audience entry: {mdAudienceId, name, type,
matchCount, matchCountType: "FIXED_SIZE", inactive, criteria: [the audience's own criteria]}.
mdAudienceId MUST be the numeric Custom Audience ID (integer, e.g. 49067): the
customAudienceId / mdAudienceId field of a get_matched_audiences row, NEVER that row's
id (the channel row id) and NEVER the audience name string; the platform's mdAudienceId
is typed Long, the tool rejects non-integer values pre-flight, and it resolves every id on
the platform before the write so a wrong id, an archived audience or one with no live
segment on the channel is refused with the reason instead of a "too small" error. In the exclude block, use the EXCLUDE variant of the type
(e.g. RETARGETING_EXCLUDE).
RESPONSE: {id, name, channel, audienceSize, status, createdDate, targeting}
WORKFLOW: search_reddit_criteria → build targeting (LOCATION first) → confirm → create_reddit_target_group
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name for the new Reddit target group. Must be unique, descriptive, and UNDER 50 characters — the platform rejects 50+ character names with a 400. | |
| targeting | Yes | Complete Reddit targeting configuration with include/exclude rules. LOCATION must be the first include block. All references must come from search_reddit_criteria. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false (a write) and destructiveHint=false (non-destructive). The description adds substantial behavioral context beyond these: the mandatory estimation prerequisite and its failure mode (zero reach created without notice), name validation (50+ char rejection with 400), ID resolution behavior (platform resolves ids and rejects non-integers pre-flight), and the fact that wrong/archived audience ids produce a refused reason instead of a 'too small' error. It also clarifies the tool mutates system state by creating a target group. This is rich, non-contradictory disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but highly structured with labeled sections (PREREQUISITE, USE FOR, WARNING, TARGETING STRUCTURE, REDDIT CRITERIA TYPES, AUDIENCES, RESPONSE, WORKFLOW). Every section adds necessary information for a complex tool; there is no filler. While it could be tightened, the density and organization justify its length. The front-loading is good—purpose and prerequisites come first. Slightly long for a 1-5, but it earns its place, so 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has nested objects with no output schema, and the description covers all aspects: a full targeting example, criteria type definitions, audience mixing, response format, workflow ordering, and prerequisite checks. Given the complexity (2 params but deep nesting) and the absence of an output schema, the description is complete—nothing an agent needs to call it correctly is missing. The workflow list even ties it to sibling search_reddit_criteria and estimate_target_group.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the two parameters (name and targeting), so baseline is 3. The description dramatically enhances understanding: it explains the targeting structure with a full JSON example, mandates LOCATION as the first include block with isModifiable=false, details each criteria type (LOCATION, COMMUNITIES, INTERESTS, KEYWORDS) with precise data formats, explains the audiences array and the critical mdAudienceId requirement (numeric custom audience ID, never the row id or name string). This goes far beyond the schema's generic property descriptions, so score 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Create a new Reddit target group with name and targeting criteria (communities, interests, keywords, location).' It distinguishes the tool from siblings by explicitly stating this is Reddit-specific and later warning to default to create_target_group (LinkedIn) when channel is unspecified. The purpose is unambiguous and differentiates from the many other create_* tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use and when-not-to-use guidance: a 'USE FOR' section gives concrete example utterances, and a 'WARNING' section states 'Only use this tool when the user explicitly asked for a REDDIT target group' and 'Default to create_target_group (LINKEDIN) when channel is unspecified; ask the user if unsure.' It also mandates a prerequisite: call estimate_target_group with channel='REDDIT' and verify isMatchCountTooSmall=false. This is comprehensive routing guidance with exclusions and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_retargeting_audienceCreate Retargeting AudienceAInspect
Create a new retargeting audience on the Metadata platform from native channel audiences.
This tool creates a retargeting audience by importing an existing audience from a native advertising
channel (Google Ads, LinkedIn, or Facebook). The audience can be selected from the list of available
retargeting audiences returned by the get_retargeting_audiences tool.
**REQUIRED TWO-STEP WORKFLOW:**
STEP 1: Get available audiences for your channel
- Call get_retargeting_audiences with your channel (GOOGLE_ADS, LINKEDIN, or FACEBOOK)
- Review the returned list of available audiences with their details (name, matchCount, etc.)
- Select the audience you want to import by its ID or by matching its properties
STEP 2: Create the retargeting audience
- Use this tool (create_retargeting_audience) with the audience data from Step 1
- Provide the audience details from the get_retargeting_audiences response
- The audience will be created and imported into the Metadata platform
SUPPORTED CHANNELS:
- GOOGLE_ADS: Google Ads retargeting audiences
- LINKEDIN: LinkedIn retargeting audiences
- FACEBOOK: Facebook retargeting audiences
WHEN TO USE:
- "Create a retargeting audience from [audience name] in [channel]"
- "Import [native channel] audience into Metadata"
- "Add [audience name] from [channel] as a retargeting audience"
- "Create a new retargeting audience based on [channel] native audience"
WORKFLOW EXAMPLE:
User: "Create a retargeting audience from my Google Ads campaign audience"
1. Call get_retargeting_audiences(channel="GOOGLE_ADS") to list available audiences
2. Select the desired audience from the results
3. Call create_retargeting_audience with the audience object from the results
PARAMETERS:
- audience_data: Complete audience object from get_retargeting_audiences response (required)
Should include: id, name, type, subtype, channel, matchCount, externalAccountId
Note: This is typically the entire audience object returned by get_retargeting_audiences
AUDIENCE DATA STRUCTURE:
The audience_data parameter should be a dictionary containing:
- id: Unique audience ID (required)
- name: Audience name (required)
- type: Audience type (e.g., GoogleAdsAudience, LinkedInAudience, FacebookAudience) (required)
- subtype: Audience subtype (e.g., GOOGLE_ADS_RETARGETING, LINKEDIN_RETARGETING) (required)
- channel: Channel type identifier (required)
- matchCount: Number of matches/members in the audience
- externalAccountId: Associated account ID on the advertising platform (required)
- mdId: Metadata ID (optional, typically null for new imports)
- externalName: External name (optional)
- externalSubType: External subtype (optional)
- seedSourcePlatform: Source platform for the audience seed (optional)
RETURNS:
Success confirmation with details about the created retargeting audience including:
- Audience ID
- Audience name
- Type and subtype
- Channel
- Match count
- Creation status
COMMON USE CASES:
- Create retargeting audiences from Google Ads native audiences
- Import LinkedIn retargeting audiences into Metadata
- Setup Facebook retargeting audiences for multi-channel campaigns
- Consolidate native channel audiences into Metadata platform
IMPORTANT NOTES:
- Audience must be selected from get_retargeting_audiences results
- The audience object must contain all required fields
- Channel must be GOOGLE_ADS, LINKEDIN, or FACEBOOK
- Audience creation is immediate and the audience becomes available for targeting
- Once created, the audience can be used in campaigns across channels| Name | Required | Description | Default |
|---|---|---|---|
| audience_data | Yes | Complete audience object from get_retargeting_audiences response. Should contain: id, name, type, subtype, channel, matchCount, externalAccountId, and other relevant fields. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=false, and openWorldHint=true. The description adds behavioral context beyond these: creation is immediate, the audience becomes available for targeting, and it can be used in campaigns across channels. It also discloses the return confirmation details. This enriches the agent's understanding of side effects and lifecycle without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headers and front-loaded purpose, but it is very verbose. Multiple sections repeat similar information: 'WHEN TO USE' and 'COMMON USE CASES' overlap, and the 'WORKFLOW EXAMPLE' partially reiterates the two-step workflow. Not every sentence earns its place, making it less concise than it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one nested parameter and no output schema, the description provides a full workflow, parameter structure, return details, and important notes. It explains how to obtain the input object and what fields are required. Minor gap: matchCountType appears in the schema but is not listed in the description's AUDIENCE DATA STRUCTURE, though the schema already covers it. Overall it is complete enough for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds significant meaning: it specifies that audience_data should be the complete object from get_retargeting_audiences, lists the required fields and optional fields, and notes it is 'typically the entire audience object returned'. This goes beyond the schema's per-field descriptions by conveying the source and packaging of the value, which is crucial for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states exactly what the tool does: 'Create a new retargeting audience on the Metadata platform from native channel audiences' and explains it imports an existing audience from Google Ads, LinkedIn, or Facebook. It distinguishes this import-based tool from siblings like create_linkedin_engagement_retargeting_audience or create_facebook_native_criteria_audience by making the 'import existing native audience' angle explicit, so an agent can tell them apart without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a detailed two-step workflow, a 'WHEN TO USE' section with natural-language triggers, and a concrete workflow example. It explicitly names get_retargeting_audiences as the required prerequisite. However, it does not explicitly state when NOT to use this tool or contrast it with alternative audience-creation tools (e.g., create_linkedin_engagement_retargeting_audience), so it misses clear exclusion guidance for a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_salesforce_contacts_audienceCreate Salesforce Contacts AudienceAInspect
Create a Salesforce-contacts custom audience (platform customAudienceType SFDC_CONTACTS_STATIC or SFDC_CONTACTS_DYNAMIC) from a Salesforce mixed-criteria.
This is one of the audience types eligible for Microsoft Ads (Customer Match). Use it when a user wants a Salesforce-sourced contacts audience, including for a Microsoft Ads campaign.
PREREQUISITE:
• Salesforce integration MUST be connected — the tool checks this and, if not connected, creates nothing and returns { warning, connected: false }.
• A criteria_id from list_salesforce_mixed_criteria — do NOT invent one.
VARIANT (mirrors the UI's static/dynamic choice):
• STATIC → SFDC_CONTACTS_STATIC — snapshot at creation, does not refresh.
• DYNAMIC → SFDC_CONTACTS_DYNAMIC — refreshes as the Salesforce data changes.
• If the user did not say which, ASK; do not default silently.
ASYNC: the platform creates the audience in the background and returns a flow id, NOT a ready audience id. The audience appears under the account's Salesforce audiences once the flow completes, and its contact count fills in then. Do not expect to associate it to a campaign in the same turn.
PARAMETERS:
• name (required): audience display name.
• criteria_id (required): id from list_salesforce_mixed_criteria.
• variant (required): STATIC or DYNAMIC.
RETURNS: { id, name, status, createdDate, audience_type, async: true } — `audience_type` is the SFDC_CONTACTS_* you created and `id` is a creation/flow id, not associable yet. If Salesforce is not connected: { warning, connected: false }, and nothing is created.| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience display name. | |
| variant | Yes | STATIC = snapshot (SFDC_CONTACTS_STATIC); DYNAMIC = refreshing (SFDC_CONTACTS_DYNAMIC). Ask the user if unspecified. | |
| criteria_id | Yes | The Salesforce mixed-criteria id from list_salesforce_mixed_criteria. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses async behavior (returns flow id, not ready audience id), the connection prerequisite with a specific failure response, static vs. dynamic refresh semantics, and the 'not associable yet' caveat. This goes far beyond the sparse annotations and gives the agent a precise model of execution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but every section earns its place: prerequisites, variant explanation, async warning, parameters, and returns. It is cleanly structured with headers and bullet points, making it easily scannable for an agent while conveying genuinely useful details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description fully compensates by stating the exact return shape, error case, and async limitations. Combined with the parameter details and prerequisites, nothing necessary for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes all three parameters (100% coverage), so the baseline is 3. The description adds essential context: criteria_id must come from list_salesforce_mixed_criteria, variant maps to SFDC_CONTACTS_* types holistically, and 'Ask the user if unspecified' reinforces the enum behavior. This additional meaning justifies a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Create', the resource 'Salesforce-contacts custom audience', the platform types (SFDC_CONTACTS_STATIC/DYNAMIC), and the source 'Salesforce mixed-criteria'. It is unambiguous and distinct from the many sibling audience-creation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use: 'Use it when a user wants a Salesforce-sourced contacts audience, including for a Microsoft Ads campaign.' It also provides a conditional instruction to ask when variant is unspecified. However, it does not explicitly compare against alternative tools or list when-not-to-use scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_segmentCreate SegmentAInspect
Create a saved Insights (Spotlight) account-journey segment: a reusable filter over the account's engaged companies, and the input of create_audience_from_segment (and of get_insights_report).
WHEN: the audience or list is defined by BEHAVIOUR or CRM STATE rather than by firmographics alone: "accounts that visited /pricing", "high engagement score and not in the CRM", "accounts we already served more than 200 LinkedIn impressions" (a saturation exclusion for a sequenced program), "open opportunities that went cold". Plain firmographic / technographic / intent asks do NOT need a segment: use those audience tools directly.
WORKFLOW:
search_insights_criteria_fields (omit keywords for the full catalog) for exact field names, types, operators and picklist options.
list_segments: reuse a segment that already expresses the ask. This tool refuses a duplicate name.
create_segment with a descriptive name and the criteria below. Pass lookback_window to get
accountscounted inside the window the audience will use.create_audience_from_segment(segment_id, name, lookback_window, audience_type).
REQUIRES an active Insights (Spotlight) subscription on the account: the platform gates segment creation on it, and this tool checks it before writing. A refusal naming the subscription state (expired, trial expired, no plan) is final: tell the user the subscription must be renewed, and do not retry with other criteria. Reading existing segments and building audiences from them keep working.
CRITERIA SHAPE: a group {"operator": "AND"|"OR", "match": [criterion | nested group]}, up to three nested levels. Each criterion: {"field": , "operator": <one of the field's operators>, "type": <the field's type>, "value": ...}. Before the call every criterion is checked against the live catalog: a missing type is filled in, names and operators are case-normalised, and an unknown field, an operator the field does not accept, or a picklist value that is not one of its options is refused with the valid choices (nothing is created).
VALUES BY TYPE:
NUMERIC: a number; operators EQUALS, GREATER_THAN, GREATER_OR_EQUAL, LESS_THAN, LESS_OR_EQUAL. Metrics (LINKEDIN_IMPRESSIONS, LINKEDIN_ADS_ENGAGEMENT, WEBSITE_VISITS, TOTAL_PAGE_VIEWS, FORM_SUBMISSIONS, ...) are summed over the lookback window the audience is created with, so "more than 200 impressions in the last 90 days" is {"field": "LINKEDIN_IMPRESSIONS", "operator": "GREATER_THAN", "type": "NUMERIC", "value": 200} plus lookback_window 90 on the audience.
MULTIPICKLIST: a list of options; plain strings are accepted and matched to the catalog options by name or label; operators IN, NOT_IN.
BOOLEAN: true or false, operator null (or omitted).
STRING: text; EQUALS, NOT_EQUAL, LIKE (contains), NOT_LIKE. PAGE_URL LIKE "/pricing" is the page-visit filter.
ARRAY (UTM_* and REFERRER): a list of strings; IN, NOT_IN, LIKE, NOT_LIKE.
DATE (CRM date fields): {"days": N} with IN_THE_LAST / NOT_IN_THE_LAST / IN_THE_NEXT, or {"startDate", "endDate"} (ISO) with BETWEEN.
CRM (dynamic) fields: {"field": "DYNAMIC", "entity": , "property": , "operator", "type", "value"}.
EXAMPLE, saturation exclusion for a sequenced LinkedIn program: {"name": "Saturated: 200+ LinkedIn impressions", "lookback_window": 90, "criteria": {"operator": "AND", "match": [{"field": "LINKEDIN_IMPRESSIONS", "operator": "GREATER_THAN", "type": "NUMERIC", "value": 200}]}}
EXAMPLE, warm accounts not yet in the CRM: {"operator": "AND", "match": [{"field": "SCORE", "operator": "IN", "type": "MULTIPICKLIST", "value": ["High"]}, {"field": "IN_CRM", "operator": null, "type": "BOOLEAN", "value": false}]}
RETURNS: {success, id, name, status (READY | PENDING | FAILED), last_updated_date, lookback_window, accounts, criteria (as stored), notes}. PENDING means a CRM field is still being extracted: wait and re-check with get_segment_criteria before building an audience. accounts of 0 means an audience would be empty: loosen the criteria or widen the window.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Descriptive, unique segment name, e.g. 'Saturated: 200+ LinkedIn impressions'. | |
| criteria | Yes | Criteria group: {"operator": "AND"|"OR", "match": [criterion | nested group]}. See VALUES BY TYPE. | |
| lookback_window | No | Optional. Days to evaluate the segment over when counting `accounts` in the response; use the window the audience will be created with. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond annotations by disclosing the subscription gate, duplicate-name refusal, live catalog validation with case-normalisation, type filling, and final refusals with valid choices. It also explains PENDING status semantics and the meaning of accounts=0, giving the agent a clear behavioral model for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but tightly organized with WHEN, WORKFLOW, CRITERIA SHAPE, VALUES BY TYPE, EXAMPLES, and RETURNS sections. Every section adds decision-relevant detail, and the examples make the nested criteria shape concrete. The structure front-loads the core purpose and usage conditions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex nested-parameter tool with no output schema, the description is self-sufficient: it names prerequisites, provides a workflow, documents the full criteria grammar, gives examples, and describes return fields plus status meanings. An agent has everything needed to invoke this tool correctly and to know what to do next with PENDING or zero-account results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema covers all three parameters, the description massively enriches their meaning with per-type operators, value shapes, examples, and lookback_window semantics. It explains how NUMERIC metrics are summed, how MULTIPICKLIST strings are matched, and how CRM dynamic fields are structured, which the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Create a saved Insights (Spotlight) account-journey segment') and clarifies it is a reusable filter that feeds create_audience_from_segment and get_insights_report. This distinguishes it clearly from the many sibling audience-creation tools, so an agent can select it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN section explicitly specifies when segments are appropriate (behaviour or CRM state) and when they are not (plain firmographic/technographic/intent asks). The WORKFLOW lists the sibling tools to call before and after, and the subscription requirement states the refusal is final and should not be retried.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_target_groupCreate Target GroupAInspect
Create a new target group with name and targeting criteria. Supports BOTH include AND exclude rules — including excluding existing Metadata audiences.
PREREQUISITE: All criteria IDs MUST come from search_target_group_criteria. estimate_target_group first is MANDATORY: verify isMatchCountTooSmall=false and report the reach to the user BEFORE creating. A target group created without an estimate can land at zero matches and nothing downstream will notice (PRD-31759). Same bar as update_target_group.
USE FOR: "create target group named X with criteria Y", "save this target group as X", "create new audience called X", "create target group excluding companies Z", "create target group that excludes audience X".
WARNING: CHANNEL: This tool creates LINKEDIN target groups only. Do NOT infer channel from the underlying audience NAMES (e.g. an audience called "Reddit Conquest Mktg LI_n7q" does NOT mean the user wants a REDDIT target group — audience naming is human convention, not a routing signal). Use REDDIT only when the user explicitly named the REDDIT channel in the request; in that case use create_reddit_target_group instead. When in doubt, ask the user which channel.
CRITICAL FOR LINKEDIN: LOCATION must be FIRST criteria in include array with isModifiable=false.
TARGETING STRUCTURE (full example with include + exclude criteria + exclude audiences): { "include": [ { "isModifiable": false, "criteria": [{"type": "NATIVE_LOCATION", "data": [ {"externalId": "urn:li:geo:101165590", "name": "United Kingdom"}, {"externalId": "urn:li:geo:103644278", "name": "United States"} ]}], "audiences": [] }, { "isModifiable": true, "criteria": [{"type": "AGE", "data": [{"externalId": "urn:li:ageRange:(25,34)", "name": "25 to 34"}]}], "audiences": [] } ], "exclude": { "isModifiable": true, "criteria": [ {"type": "COMPANY_NAME", "data": [{"externalId": "urn:li:organization:1090", "name": "Philips"}]} ], "audiences": [ { "mdAudienceId": 45316, "name": "ICP Pharma LifeSci Leaders", "type": "FIRMOGRAPHIC_EXCLUDE", "matchCount": 213127, "matchCountType": "FIXED_SIZE", "inactive": false, "criteria": [{"type": "NATIVE_LOCATION", "data": [{"externalId": "urn:li:geo:103644278", "name": "United States"}]}] } ] } }
INCLUDE: Array of rule blocks (AND-joined). Each block holds a criteria group.
EXCLUDE: Single object (NOT array) with criteria and audiences. Anything matching exclude is removed.
WARNING: AUDIENCES ≠ TARGET GROUPS. Both include[].audiences and exclude.audiences accept Custom Audience records ONLY (the entities returned by get_matched_audiences). Target Groups (the entities returned by list_target_groups / retrieve_target_group_by_id) are a separate entity in a separate ID space and CANNOT be attached here; the platform silently drops or rejects them. If the user names "X" and only list_target_groups matches it (not get_matched_audiences), do NOT pass the Target Group's id as mdAudienceId. Stop, tell the user "X is a Target Group, not a Custom Audience", and offer to rebuild X as a Custom Audience (e.g. via create_audiences with the same criteria) before retrying.
INCLUDE AUDIENCES: include[].audiences accepts ANY Metadata audience type — there is NO allow-list and NO restriction to specific types. The audience must be live on the channel, though: a row with inactive=true (LinkedIn segment archived, failed or still building) is refused by the platform and sized at 0, so pick an active row. Pass any audience returned by the audience listing tools (e.g. FIRMOGRAPHIC_INCLUDE, FIRMOGRAPHIC_INCLUDE_SFDC, NATIVE_LINKEDIN, NATIVE_FACEBOOK, RETARGETING, TECHNOGRAPHIC, SFDC_ACCOUNT_DYNAMIC, MA_CONTACTS_DYNAMIC, CONTACT_LIST, and any other type, including types not enumerated in any tool schema). Type-name enums seen in create_audiences / search_audiences describe how audiences are CLASSIFIED, not which can be attached here. Caveat: estimates may under-report (or return zero) when combining server-resolved audiences (e.g. SFDC dynamic, retargeting) with native LinkedIn criteria — that is an estimate-side reconciliation issue, not a creation constraint, so a zero estimate does not necessarily mean the platform will reject the create call. If a zero estimate is suspected to be a reconciliation artifact, attempt the create and verify in the UI.
HOW TO EXCLUDE AN EXISTING METADATA CUSTOM AUDIENCE: Add it as an object in exclude.audiences. The tool pre-flight-rejects placeholder values — never invent ids or types when you don't know them, call get_matched_audiences (or search_audiences) first and use the real values from the response. Required fields:
mdAudienceId(integer, REQUIRED): The numeric Custom Audience ID fromget_matched_audiences, itscustomAudienceId/mdAudienceIdfield (e.g. 49067, 45316), NEVER that row'sid(the channel row id). NEVER the audience name string, NEVER a placeholder like 1/2/3/4 (real Custom Audience IDs are 5-digit numbers; the tool rejects anything under 100), and NEVER a Target Group id (those come fromlist_target_groups; see the AUDIENCES ≠ TARGET GROUPS note above).name(string): Audience name.type(string): MUST be the EXCLUDE variant of the audience type, e.g.FIRMOGRAPHIC_EXCLUDE,RETARGETING_EXCLUDE,CONTACT_LIST_EXCLUDE. NEVER the placeholder string "AUDIENCE" — the tool rejects that pre-flight.matchCount(int),matchCountType("FIXED_SIZE"),inactive(bool): copy from audience record. The tool pre-flight-rejects entries withinactive: true(an audience still matching after creation cannot be attached yet — attach it once it is active).criteria: The audience's own criteria array (copy from the audience's definition).
CRITERIA TYPES (all IDs from search_target_group_criteria), valid in BOTH include and exclude:
NATIVE_LOCATION / LOCATION: location data — MANDATORY FIRST in include. Multi-country geo goes in ONE location criterion with one {externalId, name} entry per country (e.g. "Canada and USA" = 2 entries in the same data array). Never silently drop a country the user named.
AGE, COMPANY_CATEGORY, COMPANY_GROWTH_RATE, INDUSTRY, COMPANY_NAME, REVENUE, EMPLOYEE: Array of {externalId, name}
JOB_FUNCTION, JOB_TITLE, MEMBER_GROUP, MEMBER_INTEREST, MEMBER_SKILL, MEMBER_BEHAVIOR, SENIORITY, FOLLOWED_COMPANIES: Array of {externalId, name}
YEARS_OF_EXPERIENCE_RANGE: {"min": 4, "max": 5}
WORKFLOW: search_target_group_criteria → build targeting (include + optional exclude criteria/audiences) → estimate_target_group → confirm → create_target_group
RESPONSE: {id, name, channel, audienceSize, status, createdDate, targeting}
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name for the new target group. Must be unique, descriptive, and UNDER 50 characters — the platform rejects 50+ character names with a 400. | |
| channel | Yes | The advertising channel for the target group. Only LINKEDIN is currently supported. | |
| targeting | No | Complete targeting configuration with include/exclude rules... |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With only readOnlyHint=false, destructiveHint=false, and openWorldHint=false, the annotations carry almost no behavioral weight. The description compensates fully: it warns that creating without an estimate can silently land at zero matches (PRD-31759), explains pre-flight rejections of placeholders, notes the platform silently drops Target Groups passed as audiences, and discloses estimate-side reconciliation issues that may require attempting the create anyway.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with bolded section headings (PREREQUISITE, WARNING, TARGETING STRUCTURE, etc.) and front-loads the most critical routing and precreation constraints. There is minor redundancy (location-first appears in both CRITICAL and CRITERIA TYPES), and some sections could be tightened, but the detail directly addresses common failure modes and earns its place for a tool this complex.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is comprehensive: it supplies the full workflow, response shape ({id, name, channel, audienceSize, status, createdDate, targeting}), channel-specific guidance, pitfalls with target groups vs audiences, and detailed rules for both include and exclude. Even though there is no output schema, the response fields are stated. Given the complexity of the schema and sparse annotations, this description gives an agent everything needed to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema description coverage is 100%, the JSON schema entries are generic ('Complete targeting configuration with include/exclude rules...'). The description adds the real semantics: the full targeting structure example, include as AND‑joined array of blocks vs exclude as single object, required fields for audience entries (mdAudienceId, type, matchCount, etc.), acceptable criteria types, and the mandatory location-first rule. This goes far beyond the schema and is essential for correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Create a new target group with name and targeting criteria.' It clearly distinguishes itself from siblings by stating it supports both include and exclude rules, and explicitly contrasts with create_reddit_target_group and update_target_group in later sections.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit USE FOR examples, a mandatory prerequisite workflow (search→estimate→confirm→create), and a strong CHANNEL warning: use create_reddit_target_group only when the user explicitly says REDDIT, otherwise ask. It also names the sibling update_target_group as the same bar for estimation, leaving no ambiguity about when to choose this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_technographic_audienceCreate Technographic AudienceAInspect
Creates B2B audiences based on technology stack, software usage, and firmographic attributes.
ESTIMATE-ONLY MODE:
Pass estimate_only=true to preview audience size (companies + contacts) WITHOUT creating the audience.
In this mode the tool returns expectedNumberOfCompanies,
expectedNumberOfContacts, and cappedContactCount. Default is false (audience is created).
WHEN TO USE:
- Target companies using specific technologies or software
- Create audiences based on technology adoption patterns
- Target by technology categories (CRM, Marketing Automation, Analytics, etc.)
- Combine technology targeting with firmographic filters
- Build tech-savvy audience segments for B2B campaigns
- User wants to target companies and contacts that are familiar/using some specific software like hubspot, g2, etc.
TECHNOLOGY CATEGORIES:
- CRM: Salesforce, HubSpot, Microsoft Dynamics, Zoho, Pipedrive
- Marketing Automation: Marketo, Pardot, Eloqua, HubSpot, Mailchimp
- Analytics: Google Analytics, Adobe Analytics, Mixpanel, Amplitude
- E-commerce: Shopify, Magento, WooCommerce, BigCommerce
- Content Management: WordPress, Drupal, Joomla, Adobe Experience Manager
- Collaboration: Slack, Microsoft Teams, Zoom, Asana, Monday.com
- Cloud Infrastructure: AWS, Azure, Google Cloud, Oracle Cloud
- Database: MySQL, PostgreSQL, MongoDB, Oracle, SQL Server
- And many more technology categories available
FIRMOGRAPHIC FILTERS (OPTIONAL):
- Industries: Use industry IDs (1-148, same as firmographic audiences)
- Employees: "LESS_THAN_10", "FROM_10_TO_50", "FROM_50_TO_200", "FROM_200_TO_500", "FROM_500_TO_1000", "FROM_1000_TO_5000", "FROM_5000_TO_10000", "OVER_10000"
- Revenue: "LESS_THAN_1M", "FROM_1M_TO_10M", "FROM_10M_TO_50M", "FROM_50M_TO_100M", "FROM_100M_TO_200M", "FROM_200M_TO_500M", "FROM_500M_TO_1000M", "OVER_1000M"
CONTACTS CRITERIA:
Use the following parameters to filter and target specific contacts within accounts:
GEOGRAPHIC TARGETING:
location_country_ids: Array of country IDs (e.g., [29] for Brazil, [229] for United States)
location_state_ids: Array of state IDs (e.g., [5] for California, [32] for New York)
JOB TITLES:
job_title_includes: Array of free text strings to include (e.g., ["Software Engineer", "Manager"])
job_title_excludes: Array of free text strings to exclude (e.g., ["Senior", "Lead"])
JOB FUNCTIONS: Valid job function IDs and their labels:
1: Marketing, 2: Sales, 3: Customer Service, 4: Finance, 5: Human Resources, 6: Public Relations
7: Media, 8: Design, 9: Engineering, 10: Operations, 11: Legal, 12: Education
13: Health, 14: Real Estate, 15: Accounting, 16: Administrative, 17: Business Development
18: Community and Social Services, 19: Consulting, 20: Entrepreneurship, 21: Information Technology
22: Military and Protective Services, 23: Product Management, 24: Program and Project Management
25: Purchasing, 26: Quality Assurance, 27: Research, 28: Trades
job_function_include_ids: Array of job function IDs to include (e.g., [9] for Engineering)
job_function_exclude_ids: Array of job function IDs to exclude
SENIORITY LEVELS: Valid seniority IDs and their labels:
2: Manager, 3: Director, 4: VP, 5: CXO, 6: Unpaid, 7: Training
8: Senior, 9: Owner, 10: Entry, 11: Partner
seniority_include_ids: Array of seniority level IDs to include (e.g., [10, 7] for Entry and Training)
seniority_exclude_ids: Array of seniority level IDs to exclude
CONTACT LIMITS:
contacts_per_company_limit: Maximum number of contacts to target per company (optional). Example: 20
USAGE NOTES:
All ID fields (countries, states, job functions, seniorities) use numeric IDs from the platform
Job titles are free text strings, not IDs
Use include parameters to specify which criteria to target
Use exclude parameters to filter out contacts matching specific criteria
Combine multiple criteria for precise targeting (e.g., Senior Engineers in California)
Criteria are combined with AND logic, so all conditions must be met
CONTACTS CRITERIA PARAMETERS(Usually after other initial audience parameters to be described next):
location_country_ids: Array of country IDs (optional)
location_state_ids: Array of state IDs (optional)
job_title_includes: Array of job title keywords to include (optional)
job_title_excludes: Array of job title keywords to exclude (optional)
job_function_include_ids: Array of job function IDs (optional)
job_function_exclude_ids: Array of job function IDs (optional)
seniority_include_ids: Array of seniority level IDs (optional)
seniority_exclude_ids: Array of seniority level IDs (optional)
contacts_per_company_limit: Maximum contacts per company (optional)
PARAMETERS: - name: Audience name (required) - **IMPORTANT: Name MUST NOT exceed 50 characters. This is a mandatory requirement.** - technologies: Array of technology names (required) - industries: Array of industry IDs (optional) - employees: Array of employee count ranges (optional) - revenue: Array of revenue ranges (optional) RETURNS: Audience details with ID, size estimation, and creation status, plus `technologies_requested`, `technologies_targeted` (the indexed names actually sent) and `technology_resolution`. COMMON USE CASES: - Target companies using Salesforce and HubSpot - Find AWS users in the software industry - Build audiences of companies using specific MarTech stacks - Combine technology and firmographic targeting for precise B2B campaigns IMPORTANT NOTES: - **CRITICAL: Audience name MUST NOT exceed 50 characters - this is mandatory and will cause creation to fail if exceeded** - name and technologies are required parameters - All other parameters are optional for flexible audience creation - Technology names are resolved against the platform's indexed product catalog: an exact name is used as given; otherwise the closest indexed match is used and reported back in `technology_resolution` (requested, used, exact_match, alternatives) plus a plain-words `technology_note`. A name with no catalog match fails the call with an error; nothing is dropped silently. - When the call fails as too small and the error names a substituted technology, retry with one of the listed alternatives or a broader technology name. Do NOT loosen industries, seniority, employee bands or countries first: the substituted product is the cause. - Contact criteria fields work the same as in other audience types - Audience size depends on technology filters and applied criteria
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Audience name (required). Maximum 50 characters. | |
| revenue | No | Revenue ranges for firmographic filtering (optional). Valid enum values: LESS_THAN_1M ($0-$1M), FROM_1M_TO_10M ($1M-$10M), FROM_10M_TO_50M ($10M-$50M), FROM_50M_TO_100M ($50M-$100M), FROM_100M_TO_200M ($100M-$200M), FROM_200M_TO_500M ($200M-$500M), FROM_500M_TO_1000M ($500M-$1B), OVER_1000M ($1B+). Example: ['FROM_10M_TO_50M', 'FROM_50M_TO_100M'] | |
| employees | No | Employee count ranges for firmographic filtering (optional). Valid enum values: LESS_THAN_10 (0-9), FROM_10_TO_50 (10-49), FROM_50_TO_200 (50-199), FROM_200_TO_500 (200-499), FROM_500_TO_1000 (500-999), FROM_1000_TO_5000 (1,000-4,999), FROM_5000_TO_10000 (5,000-9,999), OVER_10000 (10,000+). Example: ['FROM_50_TO_200', 'FROM_200_TO_500'] | |
| industries | No | Industry IDs for firmographic/technographic filtering (optional). Valid IDs: 1=Defense & Space, 3=Computer Hardware, 4=Computer Software, 5=Computer Networking, 6=Internet, 7=Semiconductors, 8=Telecommunications, 9=Law Practice, 10=Legal Services, 11=Management Consulting, 12=Biotechnology, 13=Medical Practice, 14=Hospital & Health Care, 15=Pharmaceuticals, 16=Veterinary, 17=Medical Device, 18=Cosmetics, 19=Apparel & Fashion, 20=Sporting Goods, 21=Tobacco, 22=Supermarkets, 23=Food Production, 24=Consumer Electronics, 25=Consumer Goods, 26=Furniture, 27=Retail, 28=Entertainment, 29=Gambling & Casinos, 30=Leisure, Travel & Tourism, 31=Hospitality, 32=Restaurants, 33=Sports, 34=Food & Beverages, 35=Motion Pictures & Film, 36=Broadcast Media, 37=Museums & Institutions, 38=Fine Art, 39=Performing Arts, 40=Recreational Facilities & Services, 41=Banking, 42=Insurance, 43=Financial Services, 44=Real Estate, 45=Investment Banking, 46=Investment Management, 47=Accounting, 48=Construction, 49=Building Materials, 50=Architecture & Planning, 51=Civil Engineering, 52=Aviation & Aerospace, 53=Automotive, 54=Chemicals, 55=Machinery, 56=Mining & Metals, 57=Oil & Energy, 58=Shipbuilding, 59=Utilities, 60=Textiles, 61=Paper & Forest Products, 62=Railroad Manufacture, 63=Farming, 64=Ranching, 65=Dairy, 66=Fishery, 67=Primary/Secondary Education, 68=Higher Education, 69=Education Management, 70=Research, 71=Military, 72=Legislative Office, 73=Judiciary, 74=International Affairs, 75=Government Administration, 76=Executive Office, 77=Law Enforcement, 78=Public Safety, 79=Public Policy, 80=Marketing & Advertising, 81=Newspapers, 82=Publishing, 83=Printing, 84=Information Services, 85=Libraries, 86=Environmental Services, 87=Package/Freight Delivery, 88=Individual & Family Services, 89=Religious Institutions, 90=Civic & Social Organization, 91=Consumer Services, 92=Transportation/Trucking/Railroad, 93=Warehousing, 94=Airlines/Aviation, 95=Maritime, 96=Information Technology & Services, 97=Market Research, 98=Public Relations & Communications, 99=Design, 100=Non-profit Organization Management, 101=Fundraising, 102=Program Development, 103=Writing & Editing, 104=Staffing & Recruiting, 105=Professional Training & Coaching, 106=Venture Capital & Private Equity, 107=Political Organization, 108=Translation & Localization, 109=Computer Games, 110=Events Services, 111=Arts & Crafts, 112=Electrical & Electronic Manufacturing, 113=Online Media, 114=Nanotechnology, 115=Music, 116=Logistics & Supply Chain, 117=Plastics, 118=Computer & Network Security, 119=Wireless, 120=Alternative Dispute Resolution, 121=Security & Investigations, 122=Facilities Services, 123=Outsourcing/Offshoring, 124=Health, Wellness & Fitness, 125=Alternative Medicine, 126=Media Production, 127=Animation, 128=Commercial Real Estate, 129=Capital Markets, 130=Think Tanks, 131=Philanthropy, 132=E-learning, 133=Wholesale, 134=Import & Export, 135=Mechanical Or Industrial Engineering, 136=Photography, 137=Human Resources, 138=Business Supplies & Equipment, 139=Mental Health Care, 140=Graphic Design, 141=International Trade & Development, 142=Wine & Spirits, 143=Luxury Goods & Jewelry, 144=Renewables & Environment, 145=Glass, Ceramics & Concrete, 146=Packaging & Containers, 147=Industrial Automation, 148=Government Relations. Example: [4, 96, 11] for Software, IT Services, Consulting | |
| technologies | Yes | Array of technology names to target (required). Example: ['Salesforce', 'HubSpot', 'Marketo'] | |
| estimate_only | No | If true, do NOT create the audience — only estimate its size and return the counts. Use this when the user wants to preview how many companies/contacts match the criteria before committing. Defaults to false (audience is created). | |
| job_title_excludes | No | Free text keywords for job titles to exclude (optional). Example: ['Senior', 'Lead'] | |
| job_title_includes | No | Free text keywords for job titles to include (optional). Example: ['Software Engineer', 'Manager'] | |
| location_state_ids | No | State IDs for geographic targeting (optional). Valid US State IDs: 1 (Alabama), 2 (Alaska), 3 (Arizona), 4 (Arkansas), 5 (California), 6 (Colorado), 7 (Connecticut), 8 (Delaware), 9 (Florida), 10 (Georgia), 11 (Hawaii), 12 (Idaho), 13 (Illinois), 14 (Indiana), 15 (Iowa), 16 (Kansas), 17 (Kentucky), 18 (Louisiana), 19 (Maine), 20 (Maryland), 21 (Massachusetts), 22 (Michigan), 23 (Minnesota), 24 (Mississippi), 25 (Missouri), 26 (Montana), 27 (Nebraska), 28 (Nevada), 29 (New Hampshire), 30 (New Jersey), 31 (New Mexico), 32 (New York), 33 (North Carolina), 34 (North Dakota), 35 (Ohio), 36 (Oklahoma), 37 (Oregon), 38 (Pennsylvania), 39 (Rhode Island), 40 (South Carolina), 41 (South Dakota), 42 (Tennessee), 43 (Texas), 44 (Utah), 45 (Vermont), 46 (Virginia), 47 (Washington), 48 (West Virginia), 49 (Wisconsin), 50 (Wyoming), 52 (District of Columbia). Example: [5] for California, [32] for New York | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| seniority_exclude_ids | No | Seniority level IDs to exclude (optional). Valid IDs: 2-11 as listed above | |
| seniority_include_ids | No | Seniority level IDs to include (optional). Valid IDs: 2 (Manager), 3 (Director), 4 (VP), 5 (CXO), 6 (Unpaid), 7 (Training), 8 (Senior), 9 (Owner), 10 (Entry), 11 (Partner). Example: [10, 7] for Entry and Training | |
| job_function_exclude_ids | No | Job function IDs to exclude (optional). Valid IDs: 1-28 as listed above | |
| job_function_include_ids | No | Job function IDs to include (optional). Valid IDs: 1 (Marketing), 2 (Sales), 3 (Customer Service), 4 (Finance), 5 (HR), 6 (PR), 7 (Media), 8 (Design), 9 (Engineering), 10 (Operations), 11 (Legal), 12 (Education), 13 (Health), 14 (Real Estate), 15 (Accounting), 16 (Administrative), 17 (Business Development), 18 (Community Services), 19 (Consulting), 20 (Entrepreneurship), 21 (IT), 22 (Military Services), 23 (Product Management), 24 (Program/Project Management), 25 (Purchasing), 26 (QA), 27 (Research), 28 (Trades). Example: [9] for Engineering | |
| contacts_per_company_limit | No | Maximum number of contacts to target per company (optional). Example: 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes far beyond the annotations, disclosing that estimate_only=true previews without creating, that technology names are resolved against a catalog with no silent drops, that name length >50 chars causes failure, and how to retry on too-small failures. It also states AND logic and the exact return fields, which is rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The text is heavily bloated and repetitive: the contacts criteria parameter list appears twice, the first five parameters are re-listed in a PARAMETERS section, and the 50-character name warning is repeated three times. Headings help structure, but many sentences and lists do not earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 15-parameter tool with no output schema, the description covers essentially everything: all firmographic, geographic, contact, and limit criteria, estimate behavior, return values, failure modes, and retry guidance. Nothing an agent needs to invoke it correctly appears to be missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds real value on top: technology category examples, explicit statement that job titles are free text while IDs are numeric, the AND-combination rule, and include/exclude semantics. This elevates parameter understanding beyond the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Creates B2B audiences based on technology stack, software usage, and firmographic attributes.' It clearly identifies the technographic angle that distinguishes it from sibling audience tools, but it never explicitly names or contrasts a sibling such as create_firmographic_audience.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated 'WHEN TO USE' section lists concrete triggers (target companies using Salesforce, combine technology and firmographic filters, etc.). It gives clear context for when to invoke the tool and clarifies estimate_only usage, though it lacks explicit 'when NOT to use' or named alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_carousel_adCreate or Update Reddit Carousel AdADestructiveInspect
Create OR update a CAROUSEL ad on Reddit (Reddit only).
TO UPDATE: include id; to CREATE: omit it.
A carousel is a SINGLE ad with 2 to 6 swipeable cards. Each card is an
image with its own optional CTA; the headline is shared across the whole ad.
CREATIVE WORKFLOW:
1. Upload each card image via `upload_image_creative` -> response gives `id` (the imageLibraryId).
2. Pass those ids as cards[].imageLibraryId here (2 to 6 cards, no duplicate images).
3. Optionally upload a separate thumbnail image and pass its id as thumbnailLibraryId.
ALSO KNOWN AS: create carousel ad, update carousel ad, edit carousel ad,
modify carousel ad, multi-image ad, swipeable ad, Reddit carousel.
CLIENT-SIDE VALIDATION (mirrors what the platform UI rejects):
- adName: required, max 50 chars.
- headline: required, max 300 (shared across all cards).
- cards: 2 to 6 items; each needs imageLibraryId; no duplicate images.
- cards[].cta: optional, must be a valid Reddit CTA enum.
- text: optional body, max 2000.
- thumbnailLibraryId: optional.
REDDIT CTA VALUES: Apply Now, Contact Us, Download, Get a Quote, Learn More,
Play Now, Sign Up, View More, Watch Now, Book Now, Listen Now, Read More, Subscribe.
See `create_update_image_ad` / `create_update_video_ad` for single-creative Reddit ads.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Include to UPDATE an existing carousel ad; omit to CREATE. | |
| text | No | Optional body text. Max 2000. | |
| cards | Yes | 2 to 6 carousel cards. Each card needs a distinct image (no duplicates). | |
| adName | Yes | Ad name. Required, max 50 chars. | |
| headline | Yes | Headline shared across all cards. Required, max 300. | |
| completionStatus | No | DRAFT (default) persists locally without publishing; COMPLETED finalizes the ad. | |
| thumbnailLibraryId | No | Optional thumbnail image library id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (destructiveHint, readOnlyHint), the description adds substantial context: it explains the carousel structure (2-6 cards), the requirement that cards have distinct images, the shared headline, and the DRAFT vs COMPLETED persistence semantics. It also states the validation rules mirror the platform UI, which is valuable behavioral insight.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with clear sections (workflow, validation, CTA values, sibling reference). However, the Reddit CTA values are duplicated in the schema enum, adding redundancy. Everything else earns its place, and the critical information (create/update rule, workflow) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters and no output schema, the description is complete: it covers prerequisites (image upload), constraints (card count, no duplicates), enum values, create/update behavior, and alternatives. An agent has everything needed to invoke it correctly without external lookups.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds workflow meaning: it explains that `imageLibraryId` comes from `upload_image_creative`, that `headline` is shared across all cards, and that `thumbnailLibraryId` is optional. This goes beyond the schema descriptions by connecting the parameters to a real sequence of actions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states 'Create OR update a CAROUSEL ad on Reddit (Reddit only)' with a clear verb, resource, and platform restriction. It explicitly distinguishes create vs update via the `id` field, and the closing reference to `create_update_image_ad`/`create_update_video_ad` differentiates it from sibling single-creative tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'TO UPDATE: include `id`; to CREATE: omit it,' giving a direct conditional for use. It also instructs to upload images first via `upload_image_creative` and then pass the resulting ids, and points to sibling tools for single-creative ads, making the decision boundary clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_convo_adCreate or Update LinkedIn Conversation AdADestructiveInspect
Create or update a LinkedIn Conversation Ad ("convo ad") — a branching in-message chat where each step contains a message bubble and a list of button actions that drive the conversation forward.
BEHAVIOR:
- If `id` is provided → UPDATES the existing convo ad with that ID.
- If `id` is omitted → CREATES a new convo ad.
PREREQUISITES (MUST DO BEFORE CALLING):
1. Call get_linkedin_senders to get a valid (senderId, senderName) pair.
These are LinkedIn-issued IDs — do NOT invent them.
2. If using a banner image: upload it via upload_image_creative and pass
the returned imageLibraryId as `bannerCreativeLibraryId`. The banner
is OPTIONAL — omit the field to skip it.
THE STEP GRAPH:
A convo is a directed graph of message "steps". Each step has:
- `stepId` — unique integer; stepId=1 is ALWAYS the entry message.
- `message` — the bubble text; HTML allowed (e.g.,
'<p style="margin:0">Hi!</p>').
- `actions` — the buttons under the bubble (1 to 5).
ACTIONS — each action has a `type` from this enum:
- NEXT_STEP → click jumps to another step by `nextStepId`. Use this to
build branches ("Interested? YES / NO").
- WEBSITE_URL → click opens an external URL given in `link`. Use this for
"learn more" / external resources.
- MAIN_CTA → click opens the offer attached at campaign launch (either
a lead-gen form OR a landing page, depending on the offer).
DO NOT set `link` or `nextStepId` on a MAIN_CTA — they
are resolved by the campaign builder later.
WARNING: STRUCTURAL RULES (validated client-side before POST):
1. Every action.type MUST be one of NEXT_STEP / WEBSITE_URL / MAIN_CTA.
2. NEXT_STEP MUST have `nextStepId` pointing to an existing stepId, and
cannot point at itself.
3. WEBSITE_URL MUST have a non-empty `link`.
4. MAIN_CTA needs neither `link` nor `nextStepId`.
5. The flow MUST terminate — any step with NO NEXT_STEP action must
include at least one MAIN_CTA or WEBSITE_URL so the user has an exit.
6. `stepId=1` MUST exist — it is the entry point.
7. stepIds must be unique.
A single step CAN mix action types — e.g., step 1 can offer "Tell me
more" (NEXT_STEP), "Visit site" (WEBSITE_URL), and "Book demo"
(MAIN_CTA) all at once.
INPUT PARAMETERS:
- name (required, max 50 chars): Ad name in the platform library.
- senderId (required): From get_linkedin_senders.
- senderName (required): Matching display name from get_linkedin_senders.
- headlineText (required): Subject line shown above the message thread.
- bannerCreativeLibraryId (optional): imageLibraryId for the banner image
above the chat. Omit to skip the banner.
- completionStatus (optional, default "DRAFT"): "DRAFT" or "COMPLETED".
- flowId (optional, default 7): LinkedIn convo flow version ID.
- templateId (optional, default 1): LinkedIn convo template ID.
- id (optional): For UPDATE only — existing ad ID.
- steps (required, ≥1): The step graph (see schema).
EXAMPLE — TWO-STEP BRANCH WITH MULTI-ACTION FIRST STEP:
create_update_convo_ad(
name="DemoConvo_Q4",
senderId="fQdRPtecbv",
senderName="Josh Desmarais",
headlineText="Quick question about your marketing stack",
completionStatus="DRAFT",
steps=[
{
"stepId": 1,
"message": "<p style=\"margin:0\">Want a 15-min demo?</p>",
"actions": [
{"type": "NEXT_STEP", "text": "Tell me more", "nextStepId": 2},
{"type": "WEBSITE_URL", "text": "Visit site", "link": "https://metadata.io"},
{"type": "MAIN_CTA", "text": "Book demo"}
]
},
{
"stepId": 2,
"message": "<p style=\"margin:0\">More info — ready to book?</p>",
"actions": [
{"type": "MAIN_CTA", "text": "Yes, book"}
]
}
]
)
SUCCESS RESPONSE:
{
"success": true,
"id": 21241,
"ad_url": "https://platform.metadata.io/hub/library/ads?adId=21241",
"name": "DemoConvo_Q4",
"channelType": "LINKEDIN",
"adType": "CONVO",
"completionStatus": "DRAFT",
"request": { "convo": { ... } }
}
COMMON MISTAKES:
- Inventing a senderId — IDs MUST come from get_linkedin_senders.
- Putting `link` on a MAIN_CTA — the offer link is set at campaign launch.
- Putting `nextStepId` on a MAIN_CTA / WEBSITE_URL — only NEXT_STEP uses it.
- Forgetting the terminator — every leaf must end with MAIN_CTA or WEBSITE_URL.
- Skipping stepId=1 — the entry must exist and be exactly 1.
NOTES:
- Convo ads are LinkedIn-only. channelType is fixed to "LINKEDIN".
- `message` supports HTML; preserve the user's markup verbatim.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing convo ad ID — include to UPDATE; omit to CREATE. | |
| name | Yes | Ad name in the platform library (max 50 chars). | |
| steps | Yes | Ordered list of conversation steps. MUST include stepId=1 as the entry. | |
| flowId | No | LinkedIn convo flow version. Defaults to 7 — keep the default unless told otherwise. | |
| senderId | Yes | LinkedIn sender ID. MUST come from get_linkedin_senders. | |
| senderName | Yes | Display name matching senderId from get_linkedin_senders. | |
| templateId | No | LinkedIn convo template ID. Defaults to 1 — keep the default unless told otherwise. | |
| headlineText | Yes | Subject line shown above the message thread. | |
| completionStatus | No | Defaults to DRAFT. | |
| bannerCreativeLibraryId | No | Optional: imageLibraryId of the banner image. Upload first via upload_image_creative. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses extensive behavior beyond annotations: the step graph structure, action types and their rules, structural validation rules, the requirement for stepId=1, termination conditions, and mixing action types. It also includes a success response example and notes about HTML preservation. Annotations declare destructiveHint=true and readOnlyHint=false, which align with the create/update nature; no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with headings like BEHAVIOR, PREREQUISITES, THE STEP GRAPH, ACTIONS, WARNING, INPUT PARAMETERS, EXAMPLE, SUCCESS RESPONSE, COMMON MISTAKES, and NOTES. It front-loads the purpose and core behavior, then systematically details rules and examples. Every section earns its place given the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 10 parameters, nested steps, and multiple validation rules, the description is exceptionally complete. It includes a full example, success response format, common mistakes, and notes on HTML and channelType. An agent has everything needed to invoke the tool correctly, including edge cases like termination and entry step requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning beyond the schema's 100% coverage. For each parameter, it explains source (senderId from get_linkedin_senders), defaults (completionStatus, flowId, templateId), and relationships (bannerCreativeLibraryId from upload_image_creative). It also clarifies which fields are required for each action type. The schema descriptions are helpful, but the description enriches them with workflow context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the verb 'Create or update' and the resource 'LinkedIn Conversation Ad', then defines the branching in-message chat concept. It clearly distinguishes between create and update based on the presence of `id`, and differentiates from sibling ad-creation tools by focusing on the convo ad structure. The title reinforces this but the description adds specific behavioral detail.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit prerequisites: 'Call get_linkedin_senders to get a valid (senderId, senderName) pair' and 'upload it via upload_image_creative' for banners. It explicitly states when to use create vs update (id provided vs omitted). It also lists common mistakes that guide against misuse, effectively telling the agent what NOT to do. This is comprehensive usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_ctv_adCreate or Update LinkedIn CTV (Connected TV) AdADestructiveInspect
Create OR update a LinkedIn CTV (Connected TV) video ad. LinkedIn only.
TO UPDATE: include id; to CREATE: omit it.
CTV ads play on streaming TV inventory through the LinkedIn Audience
Network. On the platform they are LinkedIn VIDEO ads with adType=CTV,
and they carry rules the campaign must meet:
- Campaign type Brand Awareness only (never Lead Gen); the LinkedIn
channel launches as objective BRAND_AWARENESS optimized for REACH.
- The LinkedIn channel MUST use AUTO_BID (a manual bid fails
pre-launch validation); `update_linkedin_channel_settings` sets it.
- Audiences and target groups may target the United States and
Canada ONLY; any other location fails pre-launch validation.
- Video spec, enforced when the creative is uploaded: 6 to 60 seconds,
1920x1080 or 1280x720, at most 500 MB. LinkedIn recommends exactly
15, 30, 45 or 60 seconds for delivery.
CREATIVE WORKFLOW:
1. Upload the video via `upload_video_creative` with `usage_type: "CTV"`
-> response gives `id` (the videoLibraryId). The platform runs the
CTV checks at that step and rejects a non-compliant file.
2. Pass that integer as `creativeID` here. A video uploaded without
the CTV usage type is not eligible for a CTV ad.
3. Ann attaches the returned ad id to a Brand Awareness campaign's
LinkedIn channel like any other ad.
ALSO KNOWN AS: connected tv ad, ctv ad, streaming tv ad, linkedin tv ad,
ott ad, tv commercial on linkedin.
KEYWORDS: ctv, connected tv, streaming, tv, ott, linkedin ctv, video,
brand awareness, reach, audience network, commercial.
CLIENT-SIDE VALIDATION (refuses what the platform UI would also reject):
- adName: required, max 50 chars, same pattern as the other ad tools.
- creativeID: required integer (videoLibraryId).
- linkedinDisplayURL: required, ABSOLUTE (http:// or https://), max 2000.
- linkedinHeadline: required, max 200. linkedinCTA: required enum.
- linkedinText: optional, max 3000. No description field (same DTO as
LinkedIn VIDEO ads).
COMMON CTA VALUES: same as `create_update_video_ad` on LinkedIn.
RESPONSE: same envelope as `create_update_video_ad` (`created_ads[]` with
adType "CTV", channelType "LINKEDIN").
See `create_update_video_ad` for in-feed video ads and
`create_update_image_ad` for image / GIF ads.
| Name | Required | Description | Default |
|---|---|---|---|
| ads_data | Yes | Array of LinkedIn CTV ads to create or update. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, openWorldHint=true, destructiveHint=true, and the description thoroughly complements them by detailing mutation behavior, client-side validation, the requirement for AUTO_BID, location restrictions, video specs, and the response envelope. It also notes that the platform runs CTV checks during upload and rejects non-compliant files, providing essential behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (purpose, constraints, workflow, validation, response). It front-loads the core purpose and then adds necessary detail. While verbose, every sentence contributes value given the tool's complexity; no fluff is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is exceptionally complete: it covers the campaign prerequisites, bid strategy, location limits, video specifications, the two-step workflow, client-side validation, CTA enums, response format, and cross-references to sibling tools. Nothing an agent needs to correctly invoke this tool is missing, even including keywords and synonyms.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents each field, but the description adds significant meaning: it explains that creativeID is the videoLibraryId from upload_video_creative with usage_type CTV, clarifies that id must be included for updates, and notes the absence of a description field (same DTO as video ads). It also lists client-side validation rules that map to parameters, going beyond schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool creates or updates a LinkedIn CTV video ad, naming the specific resource and action. It also distinguishes itself from sibling tools like create_update_video_ad and create_update_image_ad by clarifying which ad type it handles, making it impossible to confuse.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: it names alternatives (create_update_video_ad for in-feed video ads, create_update_image_ad for image/GIF ads) and clearly outlines the workflow involving upload_video_creative and update_linkedin_channel_settings. It also lists hard constraints (Brand Awareness campaign, AUTO_BID, US/Canada only) that determine correct usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_document_adCreate or Update LinkedIn Document AdADestructiveInspect
Create a new or update an existing LinkedIn Document Ad on the Metadata platform.
A LinkedIn Document Ad promotes a multi-page document (a PDF — e.g. a
whitepaper, ebook, report, or guide) natively in the LinkedIn feed.
Members preview the first few pages inline, then unlock the full
document (typically gated behind a lead form). It is LinkedIn-only.
IMPORTANT: This tool is ONLY for LinkedIn Document Ads
(channelType=LINKEDIN, adType=DOCUMENT). For IMAGE/GIF ads use
create_update_image_ad; for VIDEO ads use create_update_video_ad; for
CONVO use create_update_convo_ad; for Sponsored Messaging use
create_update_linkedin_message_ad.
BEHAVIOR:
- If `id` is NOT provided -> creates a new Document Ad.
- If `id` IS provided -> updates the existing Document Ad with that ID.
CREATIVE WORKFLOW (MUST DO BEFORE CALLING):
1. The document must already exist in the creative library as a
DOCUMENT asset. Find it with
`search_library_creatives_by_name(contentTypes="DOCUMENT")`, or
confirm a specific id with `fetch_creative_details`.
2. Pass that asset's integer id as `libraryId`. It MUST be a
DOCUMENT-type creative — an image or video id will be rejected
by LinkedIn. Unlike IMAGE/VIDEO ads there is NO display URL: the
gated document is the destination, so no link field is accepted.
CHARACTER LIMITS (mirror the LinkedIn ad limits the platform UI enforces):
- name <= 50 chars (ad name in the library)
- headline <= 200 chars (the headline shown with the document)
- text <= 3000 chars (the introductory text)
INPUT PARAMETERS:
- id (optional): Existing Document Ad ID. Provide to UPDATE; omit to CREATE.
- name (required, <= 50): Ad name in the library.
- libraryId (required): Integer id of the DOCUMENT creative in the
library (contentType=DOCUMENT). NOT an image/video id.
- headline (required, <= 200): Headline shown with the document.
- text (required, <= 3000): Introductory text shown with the document.
- ctaType (optional, default UNLOCK_FULL_DOCUMENT): the call-to-action.
UNLOCK_FULL_DOCUMENT is the document-gate CTA.
- maxPreviewPages (optional, default 1): how many pages of the document
are previewable before the unlock gate. Positive integer.
- completionStatus (optional, default DRAFT): "DRAFT" or "COMPLETED".
Use COMPLETED only when every required field is final.
WHEN TO USE:
- User asks to "create a LinkedIn Document Ad" / "whitepaper ad" /
"promote a PDF / ebook / report on LinkedIn".
- User wants to update an existing Document Ad.
WHEN NOT TO USE:
- Feed image / GIF ad -> create_update_image_ad
- Feed video ad -> create_update_video_ad
- Branching conversation flow -> create_update_convo_ad
- One-shot Sponsored Message -> create_update_linkedin_message_ad
EXAMPLE USAGE (Create):
create_update_document_ad(
name="Q3_Whitepaper_LI_Document",
libraryId=15791,
headline="The 2026 State of B2B Marketing",
text="Download our latest research on pipeline attribution.",
maxPreviewPages=2,
)
EXAMPLE USAGE (Update):
create_update_document_ad(
id=29144,
name="Q3_Whitepaper_LI_Document_v2",
libraryId=15791,
headline="The 2026 State of B2B Marketing (Updated)",
text="Now with fresh benchmarks.",
)
COMMON MISTAKES:
- Passing an IMAGE/VIDEO libraryId — the asset must be a DOCUMENT
(use search_library_creatives_by_name(contentTypes="DOCUMENT")).
- Passing a display / landing URL — Document Ads have no link field.
- Using this tool for a non-LinkedIn channel — Document Ads are LinkedIn-only.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing Document Ad ID — include to UPDATE; omit to CREATE. | |
| name | Yes | Ad name in the platform library (max 50 characters). | |
| text | Yes | Introductory text shown with the document (max 3000 characters). | |
| ctaType | No | Call-to-action. Defaults to UNLOCK_FULL_DOCUMENT (the document-gate CTA). | |
| headline | Yes | Headline shown with the document (max 200 characters). | |
| libraryId | Yes | Integer id of the DOCUMENT creative in the library (contentType=DOCUMENT). Get it from search_library_creatives_by_name(contentTypes="DOCUMENT"). NOT an image/video id. | |
| maxPreviewPages | No | How many document pages are previewable before the unlock gate. Defaults to 1. | |
| completionStatus | No | Defaults to DRAFT. Use COMPLETED only when every required field is final. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive/read-write behavior, but the description adds substantial non-obvious context: create-versus-update logic based on id, no display URL accepted, LinkedIn-only enforcement, rejection of image/video libraryIds, defaults for ctaType/maxPreviewPages/completionStatus, and character limits mirroring platform UI. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is tightly organized with scannable headings, bulleted requirements, character-limit summaries, examples, and a COMMON MISTAKES list. The essential create/update behavior is front-loaded before details. Every major block earns its place for an 8-parameter tool with prerequisites and sibling alternatives.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers prerequisites, parameter semantics, routing, examples, and failure-prone mistakes thoroughly. The only notable gap is that it does not describe the return value or response shape after create/update, and no output schema exists to fill that gap. This is a minor omission against an otherwise complete definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, yet the description still adds meaningful semantics beyond the schema: libraryId must be a DOCUMENT creative and not an image/video id, UNLOCK_FULL_DOCUMENT is the document-gate CTA, no link field exists for this ad type, and completionStatus should be COMPLETED only when required fields are final. It also gives realistic create and update examples that bind parameters to use cases.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names the exact verb+resource: 'Create a new or update an existing LinkedIn Document Ad on the Metadata platform.' It further narrows scope with 'LinkedIn-only', distinguishes DOCUMENT ads from IMAGE/GIF/VIDEO/CONVO/Sponsored Messaging, and makes it impossible to confuse with sibling ad-creation tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a dedicated WHEN TO USE section with concrete user-phrase triggers, a WHEN NOT TO USE section that names four specific sibling tools, and a MUST-DO creative workflow requiring the document to exist in the library first. This is explicit routing guidance, not vague inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_google_ads_adCreate or Update Google Ads AdADestructiveInspect
Create a new or update an existing Google Ads text ad on the Metadata platform. IMPORTANT: This tool is ONLY for Google Ads (GOOGLE_ADS channel) text ads. Do NOT use this tool for Facebook, LinkedIn, or Instagram ads. For other channels or ad types use the dedicated tools: create_update_image_ad (IMAGE/GIF) or create_update_video_ad (VIDEO). CAROUSEL is not yet covered by the new tools — flag it if you hit that case.
BEHAVIOR:
- If "id" is NOT provided → creates a new Google Ads text ad.
- If "id" IS provided → updates the existing Google Ads text ad with that ID.
CRITICAL — GOOGLE ADS CHARACTER LIMITS (HARD LIMITS — API WILL REJECT IF EXCEEDED)
- Headlines: MAXIMUM 30 characters each (minimum 3, maximum 15 headlines)
- Descriptions: MAXIMUM 90 characters each (2 to 4 descriptions). Each description string MUST be 90 characters or fewer. Count every letter, space, and punctuation mark. 90 is the absolute maximum.
- Ad name: MAXIMUM 50 characters
WARNING: DESCRIPTIONS — 90 CHARACTER HARD LIMIT — READ THIS CAREFULLY
THIS IS THE #1 MOST COMMON FAILURE MODE. DO NOT SKIP THIS SECTION.
- 90 characters is an ABSOLUTE, NON-NEGOTIABLE HARD CEILING.
- 91 characters = REJECTION. 100 characters = REJECTION. 89 characters = OK.
- "Characters" means EVERY character: letters, digits, spaces, punctuation,
apostrophes, hyphens, slashes, line breaks, and emoji code points. ALL count.
- There is NO grace, NO rounding, NO partial credit. The boundary is exact.
- The MCP schema enforces maxLength=90 — an over-length string is rejected
before your tool call even runs. The server ALSO truncates as a backstop,
meaning your over-length copy will be SILENTLY CUT MID-SENTENCE if it
somehow slips through. Either way, you will not get the description you wrote.
- This rule applies to EACH description independently. 4 descriptions of 80
chars each is fine. 1 description of 91 chars is NOT fine.
- Do NOT pad descriptions to "use the space." Shorter is always safer.
- Do NOT rely on the user noticing — you are responsible for compliance.
COMMON WAYS LLMs BLOW THE 90-CHAR LIMIT (avoid these):
- Writing a "complete sentence" without counting first.
- Adding a CTA at the end ("Sign up today!") that pushes past 90.
- Including the company name AND a tagline AND a benefit in one description.
- Using em dashes (—), ellipses (…), or smart quotes (" ") which still count
as characters and often appear longer than expected when counted.
- Trusting your "feel" for length — LLMs systematically underestimate by 5-15
characters. ALWAYS COUNT.
RECOMMENDED SAFETY MARGIN:
- Target 70-85 characters per description. This leaves headroom for sanitization
(smart-quote conversion, whitespace normalization) and avoids edge-case
rejections. 90 is the cliff — do not write to the cliff.
MANDATORY PRE-CALL VALIDATION — YOU MUST DO THIS BEFORE EVERY CALL:
1. Write out each headline and count its characters — each MUST be ≤ 30 characters
2. Write out each description and count its characters — each MUST be ≤ 90 characters (this is the most common error — descriptions MUST NOT exceed 90 characters)
3. For EACH description, do an explicit character count: len(description). If the
number is 91 or higher, REWRITE before calling. Do not "estimate" — count.
4. If any text exceeds the limit, rewrite and shorten it BEFORE calling the tool
5. Do NOT rely on the API to catch these errors — validate client-side first
6. When in doubt, make descriptions shorter. A 70-character description is better than a rejected 91-character one
7. If a user provides copy that is too long, shorten it yourself and proceed —
do NOT submit known-bad copy and hope for the best.
EXAMPLES — DESCRIPTIONS AT THE 90-CHAR BOUNDARY:
- "Shop the best deals online." (27 chars) SAFE
- "Free shipping on every order over fifty dollars. Sign up today!" (63 chars) SAFE
- "Discover our award-winning marketing platform built for B2B teams of every size today" (89 chars) SAFE — at the edge
- "Discover our award-winning marketing platform built for modern B2B teams of every size today" (94 chars) REJECTED — 4 over
- "Transform your B2B marketing strategy with AI-powered automation that drives real revenue today!" (98 chars) REJECTED — REWRITE
USAGE INSTRUCTIONS FOR LLM:
Use this tool when users want to:
- Create a new Google Ads text ad
- Update an existing Google Ads text ad (headlines, descriptions, or name)
- Set up a Google Ads responsive search ad with headlines and descriptions
WHEN TO USE:
- User asks "create a Google Ads ad"
- User wants to create a text ad for Google Ads
- User says "make a new Google ad with these headlines and descriptions"
- User wants to update the headlines or descriptions of an existing Google Ads ad
- User says "update Google ad 23149 with new headlines"
WHEN NOT TO USE:
- User wants to create a Facebook, LinkedIn, Instagram, or Reddit IMAGE ad → use create_update_image_ad
- User wants to create a Facebook, LinkedIn, Instagram, or Reddit VIDEO ad → use create_update_video_ad
- User wants to update a non-Google Ads ad → use create_update_image_ad or create_update_video_ad (whichever matches the ad's adType)
INPUT PARAMETERS:
- id: The ad ID (optional). If provided, the ad with this ID will be updated. If omitted, a new ad is created. This is the adLibraryId inside the creatives of the google channel in campaign response.
- name: The name/label for the ad (required, max 50 characters)
- headlines: Array of headline text strings (required, minimum 3, maximum 15 headlines, each STRICT MAX 30 CHARACTERS)
- descriptions: Array of description text strings (required, 2 to 4 descriptions, each STRICT MAX 90 CHARACTERS — count characters carefully, this is the most common validation failure)
EXAMPLE USAGE (Create):
create_update_google_ads_ad(
name="My Google Ad Q1 2025",
headlines=["Buy Now", "Best Deals", "Free Shipping"],
descriptions=["Shop the best deals online.", "Free shipping on all orders."]
)
EXAMPLE USAGE (Update):
create_update_google_ads_ad(
id=23149,
name="My Google Ad Q1 2025 Updated",
headlines=["Updated Headline 1", "Updated Headline 2", "Updated Headline 3"],
descriptions=["Updated description 1.", "Updated description 2."]
)| Name | Required | Description | Default |
|---|---|---|---|
| id | No | The existing ad ID to update. If omitted, a new ad will be created. | |
| name | Yes | The name/label for the ad in Metadata platform (max 50 characters) | |
| headlines | Yes | List of headline texts for the Google Ads ad (minimum 3, maximum 15 headlines, each max 30 characters) | |
| descriptions | Yes | List of description texts for the Google Ads ad (2 to 4 descriptions). CRITICAL #1 FAILURE MODE: each description MUST be ≤ 90 characters — this is enforced by maxLength schema validation AND by server-side truncation. Going over 90 means either (a) the call is rejected before it runs, or (b) the description is silently cut at 90 mid-sentence. Count every character (incl. spaces/punctuation/emoji). Target 70-85 chars to leave margin for sanitization. Shorter is always safer. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and readOnlyHint=false, and the description fully aligns with and expands on this by explaining that updates mutate the existing ad. It goes well beyond annotations by disclosing schema rejection before execution, server-side silent truncation as a backstop, the id-based create/update switch, and the adLibraryId provenance. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized and front-loaded with the most critical channel scoping, but it is heavily redundant: the 90-character hard limit warning is repeated in multiple sections, and phrases like 'count characters' and 'shorter is safer' recur several times. The structure is clear, but the length could be substantially reduced without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's destructive nature and the high-stakes character limit failure mode, the description is exceptionally complete. It covers validation steps, common LLM failure patterns, explicit character counts for boundary examples, update workflows, and exclusions for sibling tools. With no output schema, the description appropriately focuses on call correctness, examples, and failure prevention.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds substantial semantic value: it explains id as adLibraryId inside creatives, clarifies the create/update branching behavior, and provides worked examples with character-count annotated strings. The mandatory pre-call validation steps and recommended 70-85 character safety margin give agents actionable guidance far beyond raw schema constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool creates or updates Google Ads text ads on the Metadata platform, with a specific verb, resource, and channel. It explicitly distinguishes itself from sibling tools by naming create_update_image_ad and create_update_video_ad and noting that CAROUSEL is not covered. The 'ONLY for Google Ads (GOOGLE_ADS channel) text ads' scoping leaves no ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides exhaustive WHEN TO USE and WHEN NOT TO USE sections with concrete user-phrase examples and explicit sibling tool names. It covers the create-vs-update decision (presence of id), exclusions for Facebook/LinkedIn/Instagram/Reddit, and routes the agent to the correct alternative tool. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_image_adCreate or Update Image AdADestructiveInspect
Create OR update an IMAGE (or GIF) ad on Facebook, Instagram, LinkedIn, and/or Reddit.
TO UPDATE: include id; to CREATE: omit it.
CREATIVE WORKFLOW:
1. Upload the image/GIF via `upload_image_creative` → response gives `id` (the imageLibraryId).
2. Pass that integer as `creativeID` here.
- Need a new image? `generate_brand_creative` → `upload_image_creative` → `create_update_image_ad`.
ALSO KNOWN AS: create image ad, update image ad, edit image ad,
modify image ad, image creative, post image, image post, photo ad.
KEYWORDS: image, gif, create, update, edit, modify, ad, ads, image ad, image ads,
image creative, photo, picture, banner, image campaign, image upload,
LinkedIn image, Facebook image, Instagram image, Reddit image, IG post.
CLIENT-SIDE VALIDATION (refuses what the platform UI would also reject):
- adName: required, max 50 chars, pattern `[a-zA-Z0-9 _.?,:'/+\-=&;%$#\[\]|()]`.
- creativeID: required integer (imageLibraryId from `upload_image_creative`).
- Landing-page URL is per channel (`facebookDisplayURL`,
`instagramDisplayURL`, `linkedinDisplayURL`, `redditDisplayURL`).
Required for FB/IG/LinkedIn, optional for Reddit. Per-channel
caps: LinkedIn max 2000, Reddit max 100, FB/IG no length rule.
URL format accepts both `metadata.io` and `https://metadata.io`
for IMAGE ads. If only one channel's URL is set the server fans
it across the other targeted channels; each channel's cap is
then enforced per channel.
- LinkedIn: linkedinText (required, max 3000), linkedinHeadline (required,
max 200), linkedinDescription (optional, max 300 — IMAGE only),
linkedinCTA (required, must be a valid LinkedIn CTA enum).
- Facebook: metaCTA (required), facebookText (required, no length rule on
Facebook), facebookHeadline (required, max 250), facebookDescription
(optional, max 300).
- Instagram: metaCTA (required), instagramText (required, max 125),
instagramHeadline (required, max 40), instagramDescription (optional, max 30).
- FB+IG ad with one body text: set just one of facebookText / instagramText
and the server copies it across (capped at the receiving channel's limit).
Set both explicitly only when you want per-channel copy.
- Reddit: redditHeadline (required, max 300), redditCTA (required, must be a
valid Reddit CTA enum). redditThumbnailLibraryId is optional and defaults to
creativeID.
COMMON CTA VALUES:
- LinkedIn: LEARN_MORE, REGISTER, APPLY_NOW, DOWNLOAD, JOIN, SIGN_UP,
GET_QUOTE, ATTEND, REQUEST_DEMO, SUBSCRIBE. (UNLOCK_FULL_DOCUMENT is
DOCUMENT-only — use create_update_document_ad, not this tool.)
- Facebook/Instagram: APPLY_NOW, DOWNLOAD, GET_QUOTE, LEARN_MORE, SIGN_UP, SUBSCRIBE.
(SCREAMING_SNAKE form only; the platform supports a strict subset of Meta's
native catalog. Out-of-set values like BOOK_NOW / GET_STARTED are rejected.)
- Reddit: Apply Now, Contact Us, Download, Get a Quote, Learn More, Play Now,
Sign Up, View More, Watch Now, Book Now, Listen Now, Read More, Subscribe.
See `create_update_video_ad` for video-creative ads (different libraryId source +
stricter URL format).
| Name | Required | Description | Default |
|---|---|---|---|
| ads_data | Yes | Array of IMAGE ads to create or update. Each item targets one or more of FB/IG/LinkedIn/Reddit; the platform creates one ad row per (ad, channel). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
While annotations already flag mutating/destructive behavior (readOnlyHint=false, destructiveHint=true), the description goes well beyond them: it discloses client-side validation that refuses what the platform UI rejects, server-side URL fanning across channels, DRAFT vs COMPLETED semantics (DRAFT persists locally without round-tripping to the channel API), the FB+IG body-text copy-across behavior, and the CTA subset limitation of Meta's catalog. Nothing contradicts the annotations; the description richly supplements them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but earned for a multi-channel create/update tool with per-channel validation rules; it is well-sectioned and front-loaded with the core purpose and the create/update rule. The 'ALSO KNOWN AS' and 'KEYWORDS' blocks are search-optimization padding that add little for an agent and inflate length — the only real bloat in an otherwise disciplined structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool this complex, coverage is exceptional: workflow, per-channel required/optional fields, validation caps, CTA enums, defaults, and sibling routing are all present. The one notable gap is the absence of any guidance on return values (what the tool returns on success — ad IDs, status, etc.), which matters more because there is no output schema; update semantics (overwrite vs merge) are also only implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 100% schema coverage, the description adds substantial meaning: it explains that `creativeID` is the integer imageLibraryId from `upload_image_creative` (NOT a URL), maps per-channel URL requirements and caps, defines `completionStatus` push semantics, documents that `redditThumbnailLibraryId` defaults to `creativeID`, and adds acceptance rules like `metadata.io` vs `https://metadata.io`. This is genuinely additive beyond the schema's own field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states the exact verb (create OR update), resource (IMAGE or GIF ad), and scope (Facebook, Instagram, LinkedIn, Reddit), and the create/update distinction via `id` is made immediately. It explicitly names the sibling tools it is not (`create_update_document_ad` for DOCUMENT-only CTAs, `create_update_video_ad` for video creatives with a different libraryId source), so an agent can disambiguate without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when/when-not guidance: include `id` to update, omit to create. It dictates the exact 3-step creative workflow (`upload_image_creative` → `creativeID`; `generate_brand_creative` → `upload_image_creative` → this tool), routes DOCUMENT-only CTAs to `create_update_document_ad`, and directs video-creative ads to `create_update_video_ad`. Alternatives and their selection conditions are stated outright rather than left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_linkedin_message_adCreate or Update LinkedIn Message AdADestructiveInspect
Create a new or update an existing LinkedIn Message Ad on the Metadata platform.
A LinkedIn Message Ad is a Sponsored Messaging asset: a one-shot direct
message delivered to a member's LinkedIn inbox from a specific sender,
with a subject line, a body, an optional banner image, and a single
call-to-action button. It is NOT a Conversation Ad — there is no
branching step graph. Use create_update_convo_ad for multi-step convos.
IMPORTANT: This tool is ONLY for LinkedIn Sponsored Messaging
(channelType=LINKEDIN, adType=MESSAGE). For IMAGE/GIF ads use
create_update_image_ad; for VIDEO ads use create_update_video_ad; for CONVO
use create_update_convo_ad; for Google Ads text ads use
create_update_google_ads_ad; for DOCUMENT ads use
create_update_document_ad. SPOTLIGHT / FOLLOWER are not yet
covered by the dedicated tools; LinkedIn CTV (Connected TV) ads use
create_update_ctv_ad.
BEHAVIOR:
- If `id` is NOT provided → creates a new Message Ad.
- If `id` IS provided → updates the existing Message Ad with that ID.
PREREQUISITES (MUST DO BEFORE CALLING):
1. Call get_linkedin_senders to fetch a valid (senderId, senderName) pair.
Message Ads share LinkedIn's sponsored-messaging sender allow-list
with Conversation Ads — both pull from the same endpoint. Do NOT
invent sender IDs.
2. If using a banner image: upload it via upload_image_creative and
pass the returned imageLibraryId as `bannerCreativeLibraryId`. The
banner is OPTIONAL — omit the field to skip it. LinkedIn requires
an IMAGE creative ≤ 2 MB; oversize banners are rejected upstream.
CHARACTER LIMITS (enforced by the platform; mirror the UI validator at
metadata-ui-v3/.../li/message/edit/validation.ts):
- name ≤ 50 chars (ad name in the library)
- headlineText ≤ 60 chars (the message subject line)
- messageText ≤ 2000 chars (the message body)
- actionText ≤ 20 chars (the CTA button label)
PERSONALIZATION MACROS IN messageText:
The body supports LinkedIn personalization macros. Pass them verbatim
inside `%...%` — the platform substitutes at send time. The validator
accepts ONLY these five macros (any other %...% token is rejected):
%FIRSTNAME%
%LASTNAME%
%COMPANYNAME%
%JOBTITLE%
%INDUSTRY%
Do not use `{firstName}` or any other syntax — only `%MACRO%`.
USAGE INSTRUCTIONS FOR LLM:
Use this tool when users want to:
- Create a new LinkedIn Sponsored Message ad
- Update an existing Message Ad (subject, body, CTA, sender, or banner)
WHEN TO USE:
- User asks "create a LinkedIn Message Ad" / "InMail ad" /
"Sponsored Messaging ad"
- User wants a one-shot LinkedIn DM with subject + body + CTA
- User wants to update an existing Message Ad
WHEN NOT TO USE:
- User wants a branching conversation flow → use create_update_convo_ad
- User wants a feed image / GIF ad → use create_update_image_ad
- User wants a feed video ad → use create_update_video_ad
- User wants a Google Ads text ad → use create_update_google_ads_ad
INPUT PARAMETERS:
- id (optional): Existing Message Ad ID. Provide to UPDATE; omit to
CREATE.
- name (required, ≤ 50): Ad name in the library.
- senderId (required): LinkedIn sender ID from get_linkedin_senders.
- senderName (required): Display name matching senderId.
- headlineText (required, ≤ 60): Subject line shown in the inbox.
- messageText (required, ≤ 2000): Message body. Supports the five
%MACRO% tokens listed above.
- actionText (required, ≤ 20): CTA button label.
- bannerCreativeLibraryId (optional): imageLibraryId of the banner
image. Upload first via upload_image_creative. Omit to skip the
banner.
- completionStatus (optional, default DRAFT): "DRAFT" or "COMPLETED".
Use COMPLETED only when every required field is final.
EXAMPLE USAGE (Create):
create_update_linkedin_message_ad(
name="Q1_Demo_Outreach_LI_Message",
senderId="fQdRPtecbv",
senderName="Josh Desmarais",
headlineText="Quick question about your marketing stack",
messageText="Hi %FIRSTNAME%, as a %JOBTITLE% at %COMPANYNAME% you know how hard pipeline attribution is. Want a 15-min walkthrough?",
actionText="Book a demo",
bannerCreativeLibraryId=482931,
)
EXAMPLE USAGE (Update):
create_update_linkedin_message_ad(
id=29144,
name="Q1_Demo_Outreach_LI_Message_v2",
senderId="fQdRPtecbv",
senderName="Josh Desmarais",
headlineText="Following up — quick demo?",
messageText="Hi %FIRSTNAME%, circling back…",
actionText="Book a demo",
)
SUCCESS RESPONSE (mirrors create_update_convo_ad):
{
"success": true,
"id": 29144,
"ad_url": "https://platform.metadata.io/hub/library/ads?adId=29144",
"name": "Q1_Demo_Outreach_LI_Message",
"channelType": "LINKEDIN",
"adType": "MESSAGE",
"completionStatus": "DRAFT",
"request": { "message": { ... } }
}
COMMON MISTAKES:
- Inventing a senderId — IDs MUST come from get_linkedin_senders.
- Passing a banner URL instead of an imageLibraryId — upload first.
- Using `{firstName}`-style macros — LinkedIn uses `%FIRSTNAME%`.
- Using an unsupported macro (anything outside the five listed) —
the platform/UI validator rejects it.
- Using this tool for a multi-step flow — use create_update_convo_ad.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Existing Message Ad ID — include to UPDATE; omit to CREATE. | |
| name | Yes | Ad name in the platform library (max 50 characters). | |
| senderId | Yes | LinkedIn sender ID. MUST come from get_linkedin_senders. Do not invent. | |
| actionText | Yes | Call-to-action button label (max 20 characters). | |
| senderName | Yes | Display name matching senderId, also from get_linkedin_senders. | |
| messageText | Yes | Message body (max 2000 characters). Supports LinkedIn personalization macros — ONLY %FIRSTNAME%, %LASTNAME%, %COMPANYNAME%, %JOBTITLE%, %INDUSTRY%. Any other %...% token is rejected by the platform validator. | |
| headlineText | Yes | Message subject line shown in the recipient's inbox (max 60 characters). | |
| completionStatus | No | Defaults to DRAFT. Use COMPLETED only when every required field is final. | |
| bannerCreativeLibraryId | No | Optional: imageLibraryId of the banner image shown above the message. Upload the image first via upload_image_creative and pass the returned ID. Omit to skip the banner. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false, destructiveHint=true, and openWorldHint=true, and the description both confirms and enriches this: it specifies id-based dispatch ('If id is NOT provided → creates; If id IS provided → updates'), mandates calling get_linkedin_senders first with a warning against inventing sender IDs, details the upload_image_creative → bannerCreativeLibraryId flow, and discloses platform-enforced character limits mirroring a UI validator file path. The destructive update semantics are consistent with destructiveHint=true, and the description adds far more behavioral context than annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but rigorously organized with scannable section headers (BEHAVIOR, PREREQUISITES, CHARACTER LIMITS, WHEN TO USE/NOT, COMMON MISTAKES) and is front-loaded with purpose. Nearly every section carries operational value — the two worked examples (create and update) and the COMMON MISTAKES list earn their space. It loses a point because the INPUT PARAMETERS section largely duplicates the 100%-covered schema descriptions rather than only adding the workflow context that the schema lacks.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description provides a SUCCESS RESPONSE block with concrete fields (success, id, ad_url, channelType, adType, completionStatus). Given the tool's real complexity — dual create/update behavior, two external prerequisites (sender fetch and banner upload), five macro constraints, four character limits, and 9 parameters — the description covers everything needed for correct invocation: both invocation paths are exemplified, failure modes are anticipated in COMMON MISTAKES, and sibling routing is complete. Nothing an agent needs is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, setting a baseline of 3. The description adds genuine meaning beyond the schema: it explains that senderId/senderName must be a valid pair fetched from get_linkedin_senders (with the shared allow-list note for Conversation Ads), it gives the upload-then-pass workflow for bannerCreativeLibraryId, it ties character limits to a specific validator, and it explains the create vs update dispatch of id. The macro whitelist in messageText is also reinforced with the anti-pattern {firstName}. Slight redundancy with schema text prevents a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb-resource pair ('Create a new or update an existing LinkedIn Message Ad on the Metadata platform') and defines the asset precisely as a one-shot Sponsored Messaging direct message with subject, body, optional banner, and single CTA. It explicitly differentiates from Conversation Ads ('no branching step graph') and later names each sibling (create_update_convo_ad, create_update_image_ad, create_update_video_ad, create_update_google_ads_ad) so an agent can disambiguate without opening their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description contains dedicated WHEN TO USE and WHEN NOT TO USE sections with concrete user-intent triggers ('User asks create a LinkedIn Message Ad / InMail ad / Sponsored Messaging ad') and explicit exclusions for branching flows, feed image/GIF, video, Google Ads text, DOCUMENT, SPOTLIGHT/FOLLOWER, and CTV ads with the correct sibling tool named for each. This is as explicit as usage guidance gets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_microsoft_ads_adCreate or Update Microsoft Ads AdADestructiveInspect
Create a new or update an existing Microsoft Ads (Bing) text ad on the Metadata platform. IMPORTANT: This tool is ONLY for Microsoft Ads (MICROSOFT_ADS channel) text ads. Ad library entries are PER-CHANNEL: a Google RSA can NOT be attached to a Microsoft Ads channel, and vice versa. Building the "same" ad for both channels means two calls, one per tool. For Google Ads text ads use create_update_google_ads_ad. Do NOT use this tool for Facebook, LinkedIn, Instagram or Reddit ads: use create_update_image_ad (IMAGE/GIF) or create_update_video_ad (VIDEO).
ALSO KNOWN AS: Microsoft Ads text ad, Bing text ad, Bing search ad, MS Ads ad, Microsoft responsive search ad
BEHAVIOR:
- If "id" is NOT provided -> creates a new Microsoft Ads text ad.
- If "id" IS provided -> updates the existing Microsoft Ads text ad with that ID.
CHARACTER LIMITS (HARD LIMITS — THE API REJECTS ANYTHING OVER)
Microsoft Ads and Google Ads share one text-ad shape on the platform, so the limits are identical:
- Headlines: MAXIMUM 30 characters each (minimum 3, maximum 15 headlines)
- Descriptions: MAXIMUM 90 characters each (minimum 2, maximum 4 descriptions)
- Ad name: MAXIMUM 50 characters
DESCRIPTIONS — 90 CHARACTER HARD LIMIT — READ THIS CAREFULLY
THIS IS THE #1 MOST COMMON FAILURE MODE.
- 90 characters is an ABSOLUTE ceiling. 91 = REJECTION. 89 = OK.
- EVERY character counts: letters, digits, spaces, punctuation, apostrophes, hyphens, line breaks, emoji.
- The MCP schema enforces maxLength=90, and the server truncates as a backstop, so over-length copy is either rejected outright or SILENTLY CUT MID-SENTENCE.
- Target 70-85 characters per description. Do not write to the cliff.
- LLMs systematically underestimate length by 5-15 characters. ALWAYS COUNT, never estimate.
EVERY HEADLINE AND EVERY DESCRIPTION MUST BE UNIQUE
The platform rejects the WHOLE ad when two headlines carry identical text ("Enter a headline that is different from: '<text>'"), and applies the same rule to descriptions. Writing 12 real headlines plus 3 near-copies of them is the second most common rejection. Make every line genuinely different.
NO EXCLAMATION MARK IN A HEADLINE
"!" is rejected in headline text ("! is not supported"). Descriptions accept it.
DYNAMIC KEYWORD INSERTION
A headline may use the "{KeyWord:fallback text}" form; the platform measures the 30-character limit against the fallback text inside the braces.
MANDATORY PRE-CALL VALIDATION — DO THIS BEFORE EVERY CALL:
1. Count each headline: every one MUST be 30 characters or fewer, and free of "!".
2. Count each description: every one MUST be 90 characters or fewer.
3. Check for repeats across headlines, and across descriptions. Rewrite any duplicate.
4. Rewrite anything over the limit BEFORE calling. Do not submit known-bad copy and hope.
USAGE INSTRUCTIONS FOR LLM:
Use this tool when users want to:
- Create a new Microsoft Ads / Bing text ad
- Update an existing Microsoft Ads text ad (headlines, descriptions, or name)
- Give a Microsoft Ads campaign the ad it needs to become launch-ready
WHEN TO USE:
- User asks "create a Microsoft Ads ad" / "Bing ad" / "MS Ads search ad"
- A campaign has Microsoft Ads enabled and the channel has no ad yet
- User says "update Microsoft ad 23149 with new headlines"
WHEN NOT TO USE:
- User wants the Google Ads version of the ad -> use create_update_google_ads_ad
- User wants a Facebook, LinkedIn, Instagram or Reddit IMAGE ad -> use create_update_image_ad
- User wants a Facebook, LinkedIn, Instagram or Reddit VIDEO ad -> use create_update_video_ad
- User wants a sitelink, callout or other extension -> use the create_microsoft_*_extension tools
INPUT PARAMETERS:
- id: The ad ID (optional). If provided, that ad is updated. If omitted, a new ad is created. This is the adLibraryId inside the creatives of the microsoft channel in a campaign response.
- name: The name/label for the ad (required, max 50 characters)
- headlines: Array of headline text strings (required, minimum 3, maximum 15, each STRICT MAX 30 CHARACTERS, all distinct, no "!")
- descriptions: Array of description text strings (required, minimum 2, maximum 4, each STRICT MAX 90 CHARACTERS, all distinct)
EXAMPLE USAGE (Create):
create_update_microsoft_ads_ad(
name="Bing Hosting Q1 2026",
headlines=["EU Data Centers", "Local Expert Support", "Hosting Built For Founders"],
descriptions=["Keep your business data in Europe.", "2000+ local experts, one platform."]
)
EXAMPLE USAGE (Update):
create_update_microsoft_ads_ad(
id=23149,
name="Bing Hosting Q1 2026 v2",
headlines=["Updated Headline 1", "Updated Headline 2", "Updated Headline 3"],
descriptions=["Updated description one.", "Updated description two."]
)| Name | Required | Description | Default |
|---|---|---|---|
| id | No | The existing ad ID to update. If omitted, a new ad will be created. | |
| name | Yes | The name/label for the ad in Metadata platform (max 50 characters) | |
| headlines | Yes | List of headline texts for the Microsoft Ads ad (minimum 3, maximum 15 headlines, each max 30 characters). Every headline must be DISTINCT — the platform rejects the ad if two share the same text — and must not contain '!'. | |
| descriptions | Yes | List of description texts for the Microsoft Ads ad (2 to 4 descriptions — 2 is the platform minimum, a single-description ad is rejected). Each description MUST be 90 characters or fewer and MUST be distinct from the others. Count every character (incl. spaces/punctuation/emoji); target 70-85 chars to leave margin for sanitization. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (destructiveHint, openWorldHint) carry only the safety profile, so the description carries the behavioral burden and over-delivers: create-vs-update semantics keyed on id, hard character limits with server silent-truncation backstop, whole-ad rejection on duplicate headlines/descriptions, '!' rejection in headlines, and {KeyWord:fallback} length measurement. No contradiction with annotations — update overwrites existing ad, consistent with destructiveHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear headers and critical warnings front-loaded, but substantially redundant: the 90-character rule is stated at least four times (CHARACTER LIMITS section, DESCRIPTIONS warning section, INPUT PARAMETERS, and pre-call validation steps) and repeats what the schema already documents. The uniqueness requirement and headline limits are also restated multiple times. The emphasis is pedagogically motivated, but many sentences duplicate rather than add.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-param tool with no output schema, the description is exhaustive: channel restrictions, create/update id semantics, hard limits, validation failure modes, how to locate the ad id, and worked examples for both create and update flows. An agent has everything needed to call the tool correctly; the only omission (return value) is minor for an input-heavy mutation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds genuine value beyond the schema: id is decoded as 'the adLibraryId inside the creatives of the microsoft channel in a campaign response', and the {KeyWord:fallback} headline-measurement rule is absent from the schema. Most validation constraints (30/90 chars, distinctness, no '!') are already in the schema, which caps this at 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb+resource ('Create a new or update an existing Microsoft Ads (Bing) text ad on the Metadata platform') and explicitly differentiates from siblings by naming create_update_google_ads_ad, create_update_image_ad, and create_update_video_ad, plus the channel-scoping rule. An agent can select this tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Dedicated WHEN TO USE and WHEN NOT TO USE sections give concrete triggers ('User says update Microsoft ad 23149 with new headlines') and explicit alternatives for every exclusion (Google ads, FB/LinkedIn/IG/Reddit image/video, sitelink/callout extensions). Also explains the per-channel library rule that makes a second call necessary. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_offerCreate or Update OfferADestructiveInspect
Create or update Lead Gen or Landing Page offers in Metadata platform.
Returns direct URL to access the offer in the platform.
OPERATION MODE:
- CREATE: When 'id' field is NOT included in data
- UPDATE: When 'id' field IS included in data
OFFER TYPES:
1. Lead Gen - Native forms rendered inside LinkedIn, Facebook, or Instagram. User never leaves the platform.
2. Landing Page - External page hosted on the advertiser's website. Works on EVERY channel (LinkedIn, Facebook, Instagram, Google Ads, Reddit, Microsoft Ads).
WARNING: LEAD GEN ON LINKEDIN / META CAN BE DONE TWO WAYS — pick the right one for the user's intent:
- Native Lead Gen form (offer_type='Lead Gen', data.channel=<channel>, goal=CPL): user fills the form INSIDE LinkedIn/Meta. Lower friction, higher conversion, but leads stay in the ad platform until synced. Channel-locked — see below.
- Landing Page lead capture (offer_type='Landing Page', goal=CPL, landingPageUrl + thankYouUrl + EMAIL field): user clicks through to the advertiser's own landing page and submits the form there. Choose this when the user wants branded landing pages, tracking pixels, or server-side enrichment. Channel-agnostic — one offer works on every channel.
Both flows count as Lead Gen (goal=CPL). Default to native Lead Gen for LinkedIn/Meta unless the user explicitly wants their own landing page.
WARNING: CHANNEL-LOCK ON NATIVE LEAD GEN OFFERS (read this BEFORE planning your offer batch)
The data.channel value you set on a Lead Gen offer PERMANENTLY locks the returned offer_id to that one channel. The same offer_id CANNOT be used in another channel's slot inside create_campaign / add_and_edit_campaign_elements — those tools accept the mismatch SILENTLY and produce a broken campaign that returns a successful response but cannot serve. Landing Page offers are NOT channel-locked and can be safely reused across channels.
What this means for planning:
- Want a native Lead Gen "Demo" concept on BOTH LinkedIn AND Facebook? You MUST call create_update_offer TWICE for that one concept — once with data.channel='LINKEDIN', once with data.channel='FACEBOOK'. Track both offer_ids and assign each to the matching channel slot.
- Three concepts × two native Lead Gen channels = SIX create_update_offer calls. That is correct, not over-creation. The "2-3 offers" guidance refers to distinct CONCEPTS, not call count.
- Want a single offer that works on every channel including Google? Use offer_type='Landing Page' (omit data.channel — Landing Pages have no channel field and are channel-agnostic). Google Ads ONLY accepts Landing Page offers.
- Want Lead Gen on LinkedIn using the advertiser's OWN landing page instead of LinkedIn's native form? Use offer_type='Landing Page' with goal='CPL' — then assign the returned offer_id to linkedin.offers[]. This is fully supported and a single LP offer_id can serve LinkedIn, Meta, Google simultaneously.
Right after each successful create_update_offer call, write down (offer_id, channel, concept) so you can correctly map them in the create_campaign call later. If you lose track, call get_offer(name=<offer_name>) to look up the offer and read back the channel field before submitting a campaign.
REQUIRED PARAMETERS:
- offer_type: "Lead Gen" or "Landing Page"
- data: Offer configuration object
- id: (optional) Include only when updating an existing offer
IMPORTANT LIMITS:
- offerName: MUST be unique AND under 50 characters. If name + timestamp exceeds 49 chars, shorten the base name.
WARNING: ALLOWED CHARACTERS: letters (a-z, A-Z), numbers (0-9), spaces, and these punctuation marks ONLY:
_ . ? , : ' / + - = & ; % $ # [ ] | ( )
Any other character (em-dashes, smart quotes, emoji, non-ASCII letters, ©, ™, !, @, *, {, }, <, >, ", \, ^, ~, `) will be REJECTED by the platform on Landing Page offers and stripped by this tool before the request is sent. Stick to ASCII letters/digits/space and the punctuation set above.
- offerHeader: max 60 chars
- offerDetails: max 160 chars
- thankYouMessage: max 60 chars (LinkedIn)
- privacyText: max 70 chars (Facebook/Instagram)
- Fields should always be included
CHANNEL-SPECIFIC REQUIREMENTS:
LinkedIn Lead Gen (offer_type="Lead Gen", channel="LINKEDIN"):
- REQUIRED: channel, offerName, offerHeader, thankYouMessage, thankYouUrl, privacyUrl, privacyText, fields
- CTA (linkedinCTA): REQUIRED by the backend. Defaults to DOWNLOAD_NOW when omitted. Must be one of
LEARN_MORE | VIEW_NOW | DOWNLOAD_NOW | TRY_NOW | VISIT_COMPANY_WEBSITE. Any other value silently falls
back to VISIT_COMPANY_WEBSITE on LinkedIn's side — always set linkedinCTA explicitly for predictable behavior.
- offerDetails: OPTIONAL but STRONGLY RECOMMENDED. Populates the description shown above the form on LinkedIn
and improves conversion. Not mandatory on LinkedIn (unlike FB/IG) but there's no reason to skip it.
Facebook/Instagram Lead Gen (offer_type="Lead Gen", channel="FACEBOOK" or "INSTAGRAM"):
- REQUIRED: channel, offerName, offerHeader, offerDetails, thankYouHeadline,
thankYouMessage, thankYouDescription, thankYouPageButtonText, websiteUrl, privacyUrl
- Meta's thank-you screen has THREE distinct text blocks — populate all three for a complete
UX:
• thankYouHeadline → title
• thankYouMessage → short_message (small text under the headline)
• thankYouDescription → body (longer copy). Falls back to thankYouMessage if omitted,
but supplying both is strongly preferred.
- thankYouPageButtonType (enum, default VIEW_WEBSITE). Cross-field rules:
• VIEW_WEBSITE → websiteUrl (or thankYouUrl fallback) is required
• VIEW_ON_FACEBOOK → thankYouAssetId (library creative ID) is required; without it the
backend validation will reject the offer.
- CRITICAL: offerDetails is MANDATORY when offerHeader is provided. If the user doesn't
specify offer details, generate a brief description based on the offer context.
Omitting offerDetails when offerHeader is set will cause an API validation error.
- The backend HTTP-probes followUpActionUrl (derived from websiteUrl / thankYouUrl) during
validation, so the URL MUST resolve to a live page — not a placeholder.
- linkedinCTA is ignored on FB/IG.
Landing Page (offer_type="Landing Page"):
- REQUIRED: offerName, landingPageUrl, thankYouUrl, fields
- CRITICAL: fields MUST include an EMAIL entry SPECIFICALLY. The platform's
`INVALID_LANDINGPAGE_FORM: Email mapping is required` check is satisfied
ONLY by EMAIL — BUSINESS_EMAIL alone does NOT satisfy it and the offer is
rejected. Without an email capture, the form cannot deliver a lead. If the
user does not mention form fields at all, default to:
fields: [{"name": "email", "field": "EMAIL"}, {"name": "firstName", "field": "FIRST_NAME"}, {"name": "lastName", "field": "LAST_NAME"}, {"name": "company", "field": "COMPANY"}]
BUSINESS_EMAIL may be added as an EXTRA field when the user explicitly wants
to filter out personal email domains, but it can NEVER replace EMAIL — keep
EMAIL in the form. (The server auto-corrects a lone BUSINESS_EMAIL to EMAIL.)
AVAILABLE FIELD TYPES BY OFFER TYPE:
For Lead Gen offers, the supported field types DIFFER BY CHANNEL — and the enum
SPELLINGS differ too (LinkedIn PHONE_NUMBER/ZIP_CODE vs Meta PHONE/ZIP). Mixing
them up is what causes the "Cannot deserialize Convo LeadForm JSON" attach failure.
PREFER the channel's DEFAULT-VISIBLE fields (marked [default] below) — they cover
the standard B2B form; only reach for the rest when the brief specifically needs them.
LinkedIn Lead Gen (channel="LINKEDIN") — these 22 types ONLY (source of truth:
the platform's LinkedIn Lead Gen Form dialog):
[default] "EMAIL", "WORK_EMAIL", "FIRST_NAME", "LAST_NAME", "COMPANY_NAME", "LINKEDIN_PROFILE_LINK"
[more] "PHONE_NUMBER", "WORK_PHONE_NUMBER", "COUNTRY", "CITY", "STATE", "ZIP_CODE", "JOB_TITLE",
"JOB_FUNCTION", "SENIORITY", "INDUSTRY", "COMPANY_SIZE", "DEGREE", "SCHOOL",
"FIELD_OF_STUDY", "GRADUATION_DATE", "START_DATE"
LinkedIn has NO field for REVENUE, EMPLOYEES (use COMPANY_SIZE), GENDER, DOB, MESSENGER,
STREET_ADDRESS, etc. LinkedIn caps a form at 12 fields.
Facebook/Instagram Lead Gen (channel="FACEBOOK"/"INSTAGRAM") — these 19 types ONLY
(source of truth: the platform's FB/IG Lead Gen Form dialog):
[default] "EMAIL", "WORK_EMAIL", "FIRST_NAME", "LAST_NAME", "COMPANY_NAME", "COUNTRY"
[more] "PHONE", "WORK_PHONE_NUMBER", "STREET_ADDRESS", "CITY", "STATE", "PROVINCE",
"POST_CODE", "ZIP", "GENDER", "MARITIAL_STATUS", "RELATIONSHIP_STATUS",
"MILITARY_STATUS", "JOB_TITLE"
Meta has NO field for REVENUE, EMPLOYEES, COMPANY_SIZE, SENIORITY, INDUSTRY, JOB_FUNCTION,
or the education fields (those are LinkedIn-only). "MARITIAL_STATUS" is the literal enum
(the typo is load-bearing — do not "fix" it). No field-count cap on Meta.
IMPORTANT: Do NOT use "BUSINESS_EMAIL" for Lead Gen - use "WORK_EMAIL" instead.
IMPORTANT: Do NOT use "COMPANY" for Lead Gen - use "COMPANY_NAME" instead.
IMPORTANT: Do NOT use "PHONE" for LinkedIn Lead Gen - use "PHONE_NUMBER" instead (auto-corrected if provided).
IMPORTANT: Do NOT use "PHONE_NUMBER" or "ZIP_CODE" for Facebook/Instagram - use "PHONE" / "ZIP" instead (auto-corrected if provided).
IMPORTANT: Custom / free-text questions are NOT supported. Every fields[].field MUST be one of the
predefined types for the offer's channel. Do NOT pass "CUSTOM", and do NOT invent a field for a concept
the brief names but that has no predefined type (e.g. "monthly transaction volume", "budget", "ad spend",
"use case", "team size"). Neither channel has a revenue/spend/budget field — DROP such a field. For
headcount: LinkedIn uses COMPANY_SIZE; Meta has no equivalent (drop). This server auto-normalizes near-miss
spellings (LinkedIn: EMPLOYEES->COMPANY_SIZE, ZIP->ZIP_CODE, POST_CODE->ZIP_CODE, PROVINCE->STATE; Meta:
PHONE_NUMBER->PHONE, ZIP_CODE->ZIP) and then DROPS any field the offer's channel still can't render
(logged), so the offer ships with its valid fields instead of failing at campaign-attach — but pass
channel-correct fields up front so nothing the user asked for is silently dropped.
For Landing Page offers (LandingPageFieldType):
"EMAIL", "BUSINESS_EMAIL", "FIRST_NAME", "LAST_NAME", "COUNTRY", "PHONE", "CITY", "STATE", "ZIP",
"JOB_TITLE", "SENIORITY", "COMPANY", "COMPANY_DOMAIN", "COMPANY_PHONE", "EMPLOYEES", "INDUSTRY",
"REVENUE", "LINKEDIN_URL", "UTM_SOURCE", "UTM_MEDIUM", "UTM_TERM", "UTM_CONTENT"
IMPORTANT: Do NOT use "COMPANY_NAME" for Landing Pages - use "COMPANY" instead.
IMPORTANT: Do NOT use "WORK_PHONE_NUMBER" for Landing Pages - use "PHONE" instead.
EXAMPLES:
CREATE LinkedIn Offer:
create_or_update_offer("Lead Gen", {
"channel": "LINKEDIN",
"status": "COMPLETED",
"offerName": "Free AI Marketing Audit",
"offerHeader": "Unlock Growth with AI",
"offerDetails": "A 30-minute audit of your current AI stack with tailored recommendations.",
"linkedinCTA": "DOWNLOAD_NOW",
"thankYouMessage": "We'll contact you soon!",
"thankYouUrl": "https://example.com/thanks",
"privacyUrl": "https://example.com/privacy",
"privacyText": "We respect your privacy",
"fields": [
{"name": "email", "field": "EMAIL"},
{"name": "firstName", "field": "FIRST_NAME"},
]
})
UPDATE LinkedIn Offer:
create_or_update_offer("Lead Gen", {
"id": 62148,
"channel": "LINKEDIN",
"status": "COMPLETED",
"offerName": "Free AI Marketing Audit 2025",
"offerHeader": "Unlock Growth with AI",
"offerDetails": "A 30-minute audit of your current AI stack with tailored recommendations.",
"linkedinCTA": "LEARN_MORE",
"thankYouMessage": "We'll contact you soon!",
"thankYouUrl": "https://example.com/thanks",
"privacyUrl": "https://example.com/privacy",
"privacyText": "We respect your privacy",
"fields": [
{"name": "email", "field": "EMAIL"},
{"name": "firstName", "field": "FIRST_NAME"},
]
})
CREATE Facebook/Instagram Offer:
create_or_update_offer("Lead Gen", {
"channel": "FACEBOOK",
"status": "COMPLETED",
"offerName": "Free Consultation",
"offerHeader": "Get Expert Advice",
"offerDetails": "Book a 30-minute consultation with our senior strategists.",
"thankYouHeadline": "Thank You!",
"thankYouMessage": "We'll be in touch soon",
"thankYouDescription": "A member of our team will email you within one business day to schedule your session.",
"thankYouPageButtonText": "Visit Website",
"thankYouPageButtonType": "VIEW_WEBSITE",
"websiteUrl": "https://example.com",
"privacyUrl": "https://example.com/privacy",
"privacyText": "Privacy Policy",
"fields": [
{"name": "email", "field": "EMAIL"},
{"name": "firstName", "field": "FIRST_NAME"},
]
})
CREATE Landing Page Offer:
create_or_update_offer("Landing Page", {
"offerName": "Free Demo",
"landingPageUrl": "https://example.com/landing",
"thankYouUrl": "https://example.com/thanks",
"fields": [
{"name": "email", "field": "EMAIL"},
{"name": "firstName", "field": "FIRST_NAME"},
]
})
RESPONSE: Success returns offer_id, offer_url, and configuration details.
VALIDATION: Checks URLs start with https://, character limits, required fields per channel.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | Offer configuration data. Required fields depend on offer_type and channel - see description for details. | |
| offer_type | Yes | Type of offer to create |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only signal mutation (readOnlyHint=false, destructiveHint=true), but the description adds substantial behavioral disclosures: permanent channel lock, silent fallbacks (linkedinCTA→VISIT_COMPANY_WEBSITE), server auto-correction of near-miss field spellings, silent dropping of unsupported fields, auto-stripping of invalid characters, and HTTP-probing of thankYouUrl during validation. These go far beyond the annotations and are critical for correct use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and well-structured with clear headings, warnings, and examples. However, it is very long and contains some redundancy with the schema (e.g., allowed-character list appears in both places, and several IMPORTANT warnings are repeated). Still, each section carries necessary operational detail for a high-stakes, channel-sensitive tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description covers return values ('Success returns offer_id, offer_url, and configuration details'). It also specifies validation behavior (URLs must start with https://, character limits, per-channel rules) and gives examples for every major path (LinkedIn, FB/IG, Landing Page, update). Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema description coverage is 100%, the description adds extensive parameter semantics: allowed character sets for offerName, channel-specific required fields, the full per-channel field-type enums, defaults (linkedinCTA, status, thankYouPageButtonType), maximum lengths, and the 'EMAIL required for Landing Pages' rule. It also clarifies that 'MARITIAL_STATUS' is the literal enum and must not be 'fixed'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states exactly what the tool does: 'Create or update Lead Gen or Landing Page offers in Metadata platform.' It names a specific verb (create/update), a specific resource (offers), and the two offer types. The description further distinguishes it from siblings by explaining how it fits into campaign creation (mapping offer_id to create_campaign) and when to use get_offer as a lookup fallback.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance on when to use which path: CREATE vs UPDATE based on presence of 'id', native Lead Gen vs Landing Page based on user intent, and channel-lock-driven call planning (e.g., 'You MUST call create_update_offer TWICE for that one concept'). It also tells the agent what to do after success ('write down (offer_id, channel, concept)') and points to get_offer as an alternative when tracking is lost.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_update_video_adCreate or Update Video AdADestructiveInspect
Create OR update a VIDEO ad on Facebook, Instagram, LinkedIn, and/or Reddit.
TO UPDATE: include id; to CREATE: omit it.
CREATIVE WORKFLOW:
1. Upload the video via `upload_video_creative` → response gives `id` (the videoLibraryId).
2. Pass that integer as `creativeID` here.
- For Reddit, ALSO upload a still thumbnail via `upload_image_creative` and pass
its imageLibraryId as `redditThumbnailLibraryId` (required; the video cannot
be its own thumbnail).
ALSO KNOWN AS: create video ad, update video ad, edit video ad,
modify video ad, video creative, post video, video post, motion ad.
KEYWORDS: video, create, update, edit, modify, ad, ads, video ad, video ads, mp4, motion,
video creative, video campaign, video upload, video post, video promo,
LinkedIn video, Facebook video, Instagram video, Reddit video, IG reel.
CLIENT-SIDE VALIDATION (refuses what the platform UI would also reject):
- adName: required, max 50 chars, pattern `[a-zA-Z0-9 _.?,:'/+\-=&;%$#\[\]|()]`.
- creativeID: required integer (videoLibraryId from `upload_video_creative`).
- Landing-page URL is per channel (`facebookDisplayURL`,
`instagramDisplayURL`, `linkedinDisplayURL`, `redditDisplayURL`).
Required for FB/IG/LinkedIn, optional for Reddit. Per-channel
caps: LinkedIn max 2000, Reddit max 100, FB/IG no length rule.
For VIDEO the URL MUST be ABSOLUTE (http:// or https:// is
required); inputs like `metadata.io` or `www.foo.com` are
rejected the same way the UI rejects them. If only one channel's
URL is set the server fans it across the other targeted channels.
- LinkedIn: linkedinText (max 3000, OPTIONAL for VIDEO unlike IMAGE),
linkedinHeadline (required, max 200), linkedinCTA (required, valid enum).
linkedinDescription is NOT accepted on VIDEO ads (the platform DTO
does not declare it).
- Facebook: metaCTA (required), facebookText (required, no length rule on
Facebook), facebookHeadline (required, max 250), facebookDescription
(optional, max 300).
- Instagram: metaCTA (required), instagramText (required, max 125),
instagramHeadline (required, max 40), instagramDescription (optional, max 30).
- FB+IG ad with one body text: set just one of facebookText / instagramText
and the server copies it across (capped at the receiving channel's limit).
Set both explicitly only when you want per-channel copy.
- Reddit: redditHeadline (required, max 300), redditCTA (required, valid enum),
redditThumbnailLibraryId (REQUIRED — separate IMAGE library id).
COMMON CTA VALUES: same as `create_update_image_ad` (see that tool for the lists).
See `create_update_image_ad` for image/GIF ads (the URL rule is looser there).
For LinkedIn CTV (Connected TV) ads use `create_update_ctv_ad`; the video
must be uploaded with `upload_video_creative(usage_type="CTV")`.
| Name | Required | Description | Default |
|---|---|---|---|
| ads_data | Yes | Array of VIDEO ads to create or update. Each item targets one or more of FB/IG/LinkedIn/Reddit; the platform creates one ad row per (ad, channel). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=true, but the description adds substantial behavioral context beyond that: 'Each channel produces one ad row', 'DRAFT persists locally without round-tripping', and 'If only one channel's URL is set the server fans it across the other targeted channels.' This gives the agent a clear model of side effects without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long (approximately 40 lines) but highly organized with clear sections (CREATIVE WORKFLOW, CLIENT-SIDE VALIDATION, etc.) and front-loaded purpose. The KEYWORDS section is somewhat redundant with the description text itself, slightly reducing conciseness, but every other section earns its place given the complexity of the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (multiple channels, per-channel constraints, DRAFT/COMPLETED behavior) and no output schema, the description covers all necessary invocation details: required fields, URL rules, limits, and workflow. It does not mention the return value or response format, which an agent might need to know, but this is a minor omission for a create/update tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with rich per-field descriptions, yet the description still adds significant meaning: it explains that creativeID is a libraryId from upload_video_creative, that redditThumbnailLibraryId must be a separate image library id, and details cross-field behavior like URL fan-out and per-channel copy capping. This adds value well beyond the schema's structured fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb-resource pair: 'Create OR update a VIDEO ad on Facebook, Instagram, LinkedIn, and/or Reddit.' It explicitly distinguishes this tool from siblings like create_update_image_ad and create_update_ctv_ad by naming them and the conditions for their use. The ALSO KNOWN AS and KEYWORDS sections further disambiguate the tool's scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use and when-not-to-use guidance: 'See create_update_image_ad for image/GIF ads', 'For LinkedIn CTV ads use create_update_ctv_ad'. It also gives a creative workflow (upload via upload_video_creative, pass id) and per-channel validation rules that effectively tell the agent how to invoke the tool correctly and which alternatives to choose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
deep_funnel_statsGet Deep Funnel Analysis StatisticsBRead-onlyInspect
Comprehensive funnel conversion analysis: funnel conversions, ROI statistics, experiment performance.
USE FOR: Funnel conversion analysis, stage progression, ROI metrics, pipeline attribution, experiment performance within funnels, conversion rate optimization.
REQUIRED: funnel_id, date range (YYYY-MM-DD to YYYY-MM-DD format)
OPPORTUNITY MODELS: ALL (default), TRIGGERED, INFLUENCED
| Name | Required | Description | Default |
|---|---|---|---|
| endDate | No | End date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: '2025-12-31T23:59:59.999Z' | |
| funnel_id | Yes | The funnel ID to analyze. Example: 35 | |
| startDate | No | Start date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: '2025-01-01T00:00:00.000Z' | |
| opportunityModel | No | Opportunity attribution model. Options: ALL (default), TRIGGERED, INFLUENCED | ALL |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true and destructiveHint=false, so the description mainly adds the list of metric categories and opportunity models. It does not disclose return format, aggregation level, date-range defaults, or behavior when dates are omitted, leaving some behavioral ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear labels and is reasonably short, but it repeats similar concepts: 'funnel conversion analysis' appears in the opening and in USE FOR, and ROI/metrics are restated. The content earns its place, yet some redundancy and the inaccurate REQUIRED statement reduce clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers what the tool analyzes, required inputs, and the opportunity model enum, which is enough for basic invocation. However, there is no output schema and the description does not explain the return structure, pagination, or how results are grouped, leaving meaningful gaps for a comprehensive stats tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description introduces a conflicting format: it says 'date range (YYYY-MM-DD to YYYY-MM-DD format)' while the schema specifies ISO 8601 timestamps for startDate/endDate. It also lists date range as REQUIRED even though only funnel_id is required in the schema, which could mislead an agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as funnel conversion analysis with specific outputs (conversions, ROI, experiment performance), and the title matches the operation. It does not explicitly differentiate from siblings like experiment_performance_stats or performance_metrics, which slightly overlaps in scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section provides explicit contexts such as funnel conversion analysis, ROI metrics, pipeline attribution, and conversion rate optimization. However, it does not state when not to use this tool or point to alternatives for more specialized stats like experiment-only performance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_negative_keyword_listsDelete Negative Keyword ListsADestructiveInspect
Permanently delete one or more entire Google Ads negative keyword lists, only when the user has explicitly asked.
PURPOSE:
Wipe negative keyword lists that the user has named for deletion. The platform
supports a multi-id delete in one HTTP call, so batch every list the user
identified into a single tool call instead of calling once per list.
ONLY CALL THIS TOOL WHEN THE USER HAS EXPLICITLY NAMED LISTS TO DELETE.
Examples that qualify:
- "Delete the 'Old competitors' list"
- "Drop these three lists: A, B, C"
- "Yes, delete the one I just showed you"
Examples that do NOT qualify:
- "Create a new list called X" — even if the 20-list account cap blocks the
create call, do NOT pick a list and delete it. Surface the cap to the user
(via list_negative_keywords_list so they see what's there), and ask which
list(s) THEY want to delete before calling this tool.
- "Clean up my lists" — too vague; first list_negative_keywords_list, present
the current set, and let the user pick which to drop.
WARNING:
This deletes the LIST itself (every keyword in it goes with it, and any
campaigns attaching the list lose the attachment). To remove specific
keywords inside a list without dropping the list, use
remove_keywords_from_negative_list instead.
LOOKING UP LIST IDS:
Call list_negative_keywords_list to map the names the user gave you to ids.
The 'id' field returned there is what you pass here.
COMMON USE CASES:
1. Delete a single list the user named:
delete_negative_keyword_lists(listIds=[43256533])
2. Delete several at once (mirrors the UI's "Select rows -> Delete" action):
delete_negative_keyword_lists(listIds=[43256533, 43258891, 43261107])
PARAMETERS:
- listIds (array of integers, required, min 1): IDs of the negative keyword
lists the user asked to delete, as returned by list_negative_keywords_list.
RESPONSE FORMAT:
Returns the platform response. The channels service typically responds with
204 No Content on success, in which case the wrapper returns a code 204 +
Success envelope with the ids that were deleted.
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
lists, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
| listIds | Yes | IDs of the negative keyword lists to delete (from list_negative_keywords_list). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses the full destructive cascade: deleting the list removes every keyword in it and detaches any campaigns using it. It also warns that deletion is permanent and explains the response envelope on success, which is essential because there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headings, a front-loaded warning, and each section serving a purpose. Some redundancy exists in the qualification examples, but for a destructive tool with nuanced guardrails, the detail is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description covers the response format, side effects, prerequisites, batching behavior, and channel scope. An agent has enough information to call the tool correctly and avoid irreversible mistakes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by explaining how to obtain listIds via list_negative_keywords_list and providing concrete use cases, though the channel parameter is already fully documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Permanently delete one or more entire Google Ads negative keyword lists.' It explicitly differentiates from remove_keywords_from_negative_list and create_negative_keywords_list, so an agent can distinguish it from siblings without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-call guidance ('ONLY CALL THIS TOOL WHEN THE USER HAS EXPLICITLY NAMED LISTS TO DELETE'), provides qualifying and non-qualifying examples, names the prerequisite lookup tool, and directs to remove_keywords_from_negative_list for partial removal. It also warns against cross-channel substitution.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
demographic_country_statsGet Demographic Country StatisticsARead-onlyInspect
Performance metrics grouped by Country.
USE FOR: Performance by country/geography, country-level spending/conversions, geographic comparison, international campaign effectiveness, regional ROI/pipeline. NOT FOR: Account-level aggregates (use account_level_stats), campaign-level details (use experiment_performance_stats), ingredient-level (use performance_metrics).
CHANNELS: FACEBOOK, LINKEDIN, GOOGLE_ADS, INSTAGRAM (comma-separated for multiple)
TIMEFRAME: Supports standard (this/last quarter/month/week/year), period-based (today, yesterday), custom ranges ("last two months", "last 20 days"). ISO 8601 format. Default: current month.
METRICS: spent, impressions, clicks, leads, mqls | ctr, cpl, cpc, cpm, conversionRate, formConversionRate, mqlRate | totalOpps, totalTriggered, oppsAmount, triggeredAmount | cpMql, cpOppInfluenced, cpOppTriggered | channel, lastConvertedDate
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Example: page=0 for the first page. | |
| size | No | Number of results per page. Default: 250; raise it (up to 10000) to pull every country in one call. | |
| sort | No | Sorting criteria. Examples: 'spend,desc' (default), 'leads,desc', 'cpl,asc', 'impressions,desc'. Format: field,direction where direction is 'asc' or 'desc'. | spend,desc |
| toMonth | No | End date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: 2025-01-31T23:59:59.999Z. Required for custom date ranges. | |
| channels | No | Comma-separated channel names (e.g., 'LINKEDIN,FACEBOOK,INSTAGRAM,GOOGLE_ADS'). Leave empty for all channels. | |
| fromMonth | No | Start date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: 2025-01-01T00:00:00.000Z. Required for custom date ranges. | |
| groupType | No | Grouping type - currently only COUNTRY is supported for geographic breakdown. | COUNTRY |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description supplements this with useful behavioral context: supported channels, timeframe shorthand and default (current month), and the full set of exposed metrics, all beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description uses compact labeled sections (USE FOR, NOT FOR, CHANNELS, TIMEFRAME, METRICS), front-loads the core grouping behavior, and contains no filler. The longer METRICS list is justified because it informs both sortable fields and expected return dimensions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only stats tool with no required parameters, this is largely complete: grouping, channels, timeframes, defaults, metrics, and sibling routing are all covered. The only notable gap is that no output schema exists and the description does not describe the exact response envelope, though the metric list substantially mitigates this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds real value by enumerating valid channels, documenting timeframe variants like 'last two months' and 'last 20 days', listing available metrics, and noting the default current month. This goes beyond the schema without contradicting it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Performance metrics grouped by Country', giving a specific verb, resource, and grouping dimension. It also explicitly distinguishes itself from sibling tools: account-level aggregates should use account_level_stats, campaign-level details use experiment_performance_stats, and ingredient-level uses performance_metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE FOR section enumerates concrete scenarios: performance by country/geography, country-level spending/conversions, geographic comparison, international campaign effectiveness, and regional ROI/pipeline. The NOT FOR section names the exact alternatives to use instead, leaving no ambiguity about when to choose a sibling tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
disconnect_channelDisconnect ChannelADestructiveInspect
Disconnect a specific advertising channel from the Metadata platform.
USAGE INSTRUCTIONS FOR LLM:
Use this tool to disconnect/remove integration connections for advertising channels.
This is useful when users need to remove a channel integration or reconnect with different credentials.
WHEN TO USE THIS TOOL:
- User asks to "disconnect [channel name]"
- User wants to "remove [channel] integration"
- User needs to "unlink [channel] account"
- User wants to "revoke [channel] access"
- User asks to "disconnect my Facebook/LinkedIn/Twitter/Reddit/Google account"
- User needs to "reset [channel] connection"
- Preparing to reconnect a channel with different credentials
SUPPORTED CHANNELS:
- facebook: Disconnect Facebook advertising account
- instagram: Disconnect Instagram advertising account
- linkedin: Disconnect LinkedIn advertising account
- twitter: Disconnect Twitter/X advertising account
- reddit: Disconnect Reddit advertising account
- google: Disconnect Google Ads account
IMPORTANT NOTES:
- This action will disconnect the channel immediately
- Any active campaigns on this channel may be affected
- The user will need to reconnect the channel to resume advertising
- Always confirm with the user before disconnecting a channel
- Check integration status first using get_integrations_status to verify the channel is connected
COMMON SCENARIOS:
Scenario 1 - Disconnect single channel: "Disconnect my LinkedIn account"
→ Call disconnect_channel with channel="linkedin"
Scenario 2 - Reconnect workflow: "I want to reconnect Facebook with a different account"
→ First call disconnect_channel with channel="facebook", then guide user to reconnect
Scenario 3 - Remove access: "Remove Google Ads integration"
→ Call disconnect_channel with channel="google"
RESPONSE FORMAT:
Returns a success/failure status indicating whether the channel was disconnected successfully.
EXAMPLE: "Disconnect Facebook" → disconnect_channel(channel="facebook")
| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | The channel to disconnect. Must be one of: reddit, facebook, linkedin, twitter, google, instagram |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses immediate disconnection, potential impact on active campaigns, and the need to reconnect. This gives the agent practical knowledge about consequences.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but well-structured with clear sections and front-loaded purpose. The scenarios section is somewhat repetitive against the usage examples, but the organization keeps it scannable and each section adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with a closed enum, the description fully covers the action, prerequisites, consequences, and expected response format ('success/failure status'). No output schema is needed for this level of simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already has 100% coverage with an enum and description. The tool description adds supplementary meaning by mapping each channel value to its corresponding advertising account (e.g., facebook -> Facebook advertising account). This exceeds the baseline while not being strictly necessary.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Disconnect a specific advertising channel from the Metadata platform.' It clearly differentiates from siblings like connect_channel by focusing on disconnection/removal of integrations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance with concrete user phrasings ('disconnect [channel name]', 'remove [channel] integration'), lists supported channels, and recommends checking integration status via get_integrations_status before acting. Also advises confirming with the user, which is strong situational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
duplicate_campaignDuplicate CampaignAInspect
Duplicate (copy) an existing campaign into a NEW DRAFT campaign.
KEYWORDS: duplicate, copy, clone, replicate, reuse, campaign, draft, copy of
WHAT IT DOES:
Creates a brand-new campaign that is a DEEP COPY of an existing one. The new
campaign is created in DRAFT status and spends no budget. This mirrors the
platform UI's "Duplicate campaign" action.
WHAT GETS COPIED (server-side, automatic — there are NO toggles to choose):
- Goal (Lead Gen / Brand Awareness)
- Optimization (budget) group / tag
- All landing pages
- Every channel that is currently ENABLED FOR THE ACCOUNT, together with that
channel's audiences, ads/creatives, keywords, offers and bid settings.
(Channels that are disabled for the account are skipped — connect/enable the
channel on the account first if you need it carried over.)
WHAT IS NOT COPIED / CHANGES:
- The new campaign starts in DRAFT (the original's live/active state is NOT copied).
- Start/end dates are not carried as a live schedule — set them on the new draft.
- Only the new name is caller-controlled.
REQUIRED PARAMETERS:
- campaign_id (integer): The wizard/campaign ID of the campaign to duplicate.
Must be in status Launched, Launching, Editing, or Draft.
OPTIONAL PARAMETERS:
- name (string): The name for the NEW campaign. Must be non-blank, <= 255 chars,
and UNIQUE across the account's campaigns. If omitted, a unique name is
auto-generated as "<original name>_copy_<UTC timestamp>" (e.g.
"Q1_2026_Campaign_copy_20260115120000"). If you pass a name that
already exists on the account, the platform rejects it — choose a unique name
or omit it to auto-generate one.
CAMPAIGN ID SOURCES:
- search_campaigns_by_names tool (recommended)
- list_wizard_campaigns tool
- get_campaign_by_wizard_id tool
WORKFLOW:
1. Find the source campaign ID (search_campaigns_by_names / list_wizard_campaigns).
2. duplicate_campaign(campaign_id=..., name="..." # name optional).
3. The response contains the NEW campaign's id and full configuration.
4. Review the new DRAFT campaign and MODIFY it with the edit tools below (it is a
normal editable draft — change anything you want).
AFTER DUPLICATING — HOW TO MODIFY THE NEW DRAFT:
The copy is a regular DRAFT campaign, so use the standard campaign-editing tools on
the NEW campaign id (NOT the original). The main ones:
- add_and_edit_campaign_elements — the primary editor: rename, change budget group,
start/end dates, enable channels, replace per-channel offers, and ADD audiences,
exclusion audiences, ads, ad groups, and keywords. (Native / N×N×N campaigns:
use add_and_edit_native_campaign_elements.)
- update_experiments_daily_budgets — adjust per-experiment daily budgets.
- update_reddit_channel_settings — Reddit-specific channel/bid/pixel settings.
- remove_channels_from_campaign / remove_audiences_from_campaign /
remove_ad_from_campaign / remove_keywords_from_campaign /
remove_offers_from_campaign / remove_target_groups_from_campaign
— remove elements from the copy.
- manage_campaign — pause/restart (lifecycle).
Tip: call get_campaign_by_wizard_id on the new id first to see what was copied,
then edit. Use search_campaigns_by_names to re-locate the copy by its new name.
EXAMPLE:
User: "Make a copy of campaign 54050 called 'Q2 Relaunch'"
Call: duplicate_campaign(campaign_id=54050, name="Q2 Relaunch")
Then: add_and_edit_campaign_elements(campaign_id=<new id>, ...) to tweak the copy.
RESPONSE FORMAT:
Returns the full configuration of the newly created DRAFT campaign — including its
new campaign id, name, status (Draft), goal, optimization group, and copied channels.
Use the returned id with get_campaign_by_wizard_id and the edit tools.
Anchor any date-derived naming to the REAL current date — call get_current_date if unsure.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Name for the new (copied) campaign. Must be unique on the account and <= 255 chars. Omit to auto-generate '<original name>_copy_<timestamp>'. | |
| campaign_id | Yes | The wizard/campaign ID of the campaign to duplicate. Must be in status Launched, Launching, Editing, or Draft. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors beyond the annotations: the new campaign is created in DRAFT status and spends no budget, the copy is a deep copy with certain elements included and others excluded (e.g., disabled channels are skipped), and there are NO toggles to choose. It also specifies that only the name is caller-controlled. This is rich, honest behavior disclosure that doesn't contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but exceptionally well-structured with clear headers, numbered workflow steps, and a concrete example. Some minor redundancy exists (the 'KEYWORDS' section and the second sentence repeating the first), but the overall organization makes it easy for an agent to consume. It uses headers and lists to break down a complex behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all necessary operational context: what is copied, what is not, parameter constraints and defaults, ID sourcing, step-by-step workflow, post-copy modification via sibling tools, an example call, and response format. It even advises calling get_current_date for name naming. Despite a complex tool with many downstream interactions, the description is fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds substantial semantic value. For campaign_id, it clarifies the acceptable statuses (Launched, Launching, Editing, or Draft). For name, it explains uniqueness requirements, auto-generation format with an example, and behavior when a duplicate name is provided. These details go beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource+outcome: 'Duplicate (copy) an existing campaign into a NEW DRAFT campaign.' It further distinguishes the tool from siblings by noting it mirrors the platform UI's 'Duplicate campaign' actionaving also explains what is copied (deep copy) and what changes (status becomes draft). An agent can unambiguously identify when to use this tool and what it does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: a 'CAMPAIGN ID SOURCES' section recommends sibling tools (search_campaigns_by_names, list_wizard_campaigns) for finding the ID, a step-by-step WORKFLOW shows when to call duplicate_campaign, and an 'AFTER DUPLICATING' section clarifies that the resulting draft should be edited using specific sibling tools. It also states what is not copied and that the campaign ID must be in a certain status.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
duplicate_negative_keywords_listDuplicate Negative Keywords List Across ChannelsAInspect
Duplicate (copy) a negative keyword list from one search channel to the other: Google Ads to Microsoft Ads (Bing), or Microsoft Ads to Google Ads.
KEYWORDS: duplicate, copy, clone, replicate, negative keywords, Bing, Microsoft Ads, Google Ads
PURPOSE:
Users who run the same campaigns on Google and Bing keep the two negative keyword
libraries in sync by hand. This tool copies an existing negative keyword list to the
other search channel in one call: the platform reads the source list's keywords,
adapts match types for the target channel, and creates a new list there.
WHAT IT DOES (server-side, automatic):
- Reads every keyword in the source list.
- Remaps match types for the target: Microsoft Ads does not support BROAD negative
keywords, so BROAD (and untyped) keywords become PHRASE when the target is
Microsoft Ads. EXACT and PHRASE are kept as-is. Google-bound copies keep all
match types unchanged.
- Creates a NEW list on the target channel. The source list is never modified.
DRY RUN (preview):
Call with dryRun=true first when the source list may contain BROAD keywords.
Nothing is created; the response reports keywordsCopied and broadRemappedToPhrase
so you can tell the user "N broad keywords will become phrase match on Microsoft"
and let them confirm. Then repeat the call with dryRun=false to actually create.
PARAMETERS:
- sourceListId: Required. The id of the negative keyword list to copy, as returned
by list_negative_keywords_list.
- sourceChannel: Channel the source list lives on. Default GOOGLE_ADS.
- targetChannel: Channel to create the copy on. Default MICROSOFT_ADS.
Must differ from sourceChannel - only cross-channel copies are supported.
- name: Optional name for the new list. When omitted the platform derives
"<source name> (<target>)", e.g. "Competitor Brands (Microsoft)".
- dryRun: Optional, default false. When true, preview without creating.
RESPONSE FORMAT:
{
"id": 456, // new list id on the target channel; null on dry run
"name": "Competitor Brands (Microsoft)",
"keywordsCopied": 32,
"broadRemappedToPhrase": 5, // 0 when target is Google Ads
"dryRun": false
}
WORKFLOW:
1. Find the source list id with list_negative_keywords_list (or ask the user).
2. Optional: duplicate_negative_keywords_list(sourceListId=..., dryRun=true) to
preview the match-type conversion and confirm with the user.
3. duplicate_negative_keywords_list(sourceListId=...) to create the copy.
4. The new list exists on the target channel; attach it to campaigns like any
other negative keyword list.
ERROR CASES:
- Source list not found (or empty) on the source channel: the platform rejects the
copy with a not-found error - re-check the id and sourceChannel.
- Same source and target channel: rejected; use the platform UI's same-channel
duplicate instead.
- Accounts are capped at 20 negative keyword lists per channel; if the target
channel is at the cap the creation fails - delete a list there first.
EXAMPLES:
- "Copy my Google negative list to Bing":
duplicate_negative_keywords_list(sourceListId=123)
- Preview first:
duplicate_negative_keywords_list(sourceListId=123, dryRun=true)
- Custom name, Microsoft to Google:
duplicate_negative_keywords_list(sourceListId=77, sourceChannel="MICROSOFT_ADS",
targetChannel="GOOGLE_ADS", name="Brand Safety (Google)")
RELATED TOOLS:
- list_negative_keywords_list / get_negative_keywords_list_details: find the source
list and inspect its keywords (currently Google Ads only).
- create_negative_keywords_list: build a brand-new list from scratch instead.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional name for the new list. Defaults to "<source name> (<target>)", e.g. "Competitor Brands (Microsoft)". | |
| dryRun | No | When true, preview the copy (keyword count + BROAD-to-PHRASE conversions) without creating the list. | |
| sourceListId | Yes | Id of the negative keyword list to copy, as returned by list_negative_keywords_list. | |
| sourceChannel | No | Channel the source list lives on. Default GOOGLE_ADS. | GOOGLE_ADS |
| targetChannel | No | Channel to create the copy on. Must differ from sourceChannel. Default MICROSOFT_ADS. | MICROSOFT_ADS |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnlyHint=false and destructiveHint=false, so the description carries the burden of behavioral disclosure. It clearly states the source list is never modified, match types are remapped (BROAD/untyped become PHRASE when targeting Microsoft Ads), a NEW list is created, the 20-list-per-channel cap can cause failure, and dry-run mode creates nothing. These details go well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well organized with headers, bullets, a response example, and a workflow list. The core purpose is front-loaded, and each section earns its place. Minor redundancy exists (e.g., the KEYWORDS line repeats terms already in the title), but the structure keeps it scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies a full response format, error cases, workflow steps, examples, and related tools. For a cross-channel mutation with match-type conversion and a dry-run mode, an agent has everything needed to call it correctly without additional research.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning by explaining the cross-channel constraint, the derived default name format, dryRun preview behavior, and worked examples mapping parameters to responses. This is useful but the schema already documents most parameter basics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Duplicate (copy) a negative keyword list from one search channel to the other') and explicitly names the supported directions: Google Ads to Microsoft Ads or vice versa. It also distinguishes this tool from related siblings like create_negative_keywords_list and duplicate_campaign by emphasizing cross-channel copying.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit workflow steps, tells the agent to find the source list with list_negative_keywords_list, recommends a dryRun first when BROAD keywords may exist, and names alternatives such as create_negative_keywords_list and the platform UI's same-channel duplicate. This is concrete, actionable when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_brand_creativeEdit Brand CreativeADestructiveInspect
Edit existing creative image using AI-powered editing while preserving brand consistency.
USE FOR: Modify headline/CTA/hero graphic, add/remove elements, adjust styling, create variations, iterate on designs.
EDITABLE: Headlines, text, CTA buttons, hero graphics, badges/icons, colors, stats, any combination in single request.
EXAMPLES:
Single: "Change headline to 'BOOST YOUR ROI'"
Multiple: "Change headline to 'DRIVE PIPELINE', update CTA to 'LEARN MORE', add +50% badge"
PRESERVES (unless asked to change): Logo position/size, brand colors, typography, composition, dimensions.
CHAINED EDITS: Use output URL as input for next edit (Edit → URL_1 → Edit → URL_2 → final).
OUTPUT: Returns the hosted image URL.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company domain for brand context. Used to fetch brand DNA for consistency. Examples: 'metadata.io', 'bloomreach.com' | |
| image_source | Yes | URL of the creative image to edit. Must be a valid accessible image URL (PNG, JPG, WebP). Can be a URL returned by a previous generation or edit. | |
| edit_instruction | Yes | Natural language description of the desired edit(s). Can include multiple changes in one request. Examples: 'Replace the robot with a dashboard', 'Change headline to BOOST ROI and make CTA say GET STARTED', 'Add a +50% ROI badge in the corner' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial context beyond the annotations: it explains preservation defaults (logo, colors, typography, composition, dimensions), documents chained edit behavior, and states the output is a hosted image URL. This aligns with destructiveHint=true and openWorldHint=true without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headings, examples, and a front-loaded purpose sentence. It is somewhat long, and USE FOR and EDITABLE partially overlap, but each section contributes useful guidance and is scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex free-form editing tool with no output schema, the description covers the main operational needs: valid inputs, preservation behavior, chained edits, and return value. It could be more complete by explicitly distinguishing when to use this tool versus generate_brand_creative or other creative siblings, but it is otherwise adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description enriches the free-form edit_instruction parameter with concrete examples and the 'any combination in a single request' guidance. The EDITABLE list also clarifies what kinds of natural-language changes the model can perform.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Edit existing creative image' and adds the distinguishing purpose of preserving brand consistency. It clearly enumerates editable elements, making it distinct from generate_* and update_brand_kit siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE FOR section explicitly lists supported editing scenarios such as modifying headlines, CTAs, and hero graphics, and examples show both single and multi-edit requests. It does not explicitly name generate_brand_creative or fix_flexible_creative as alternatives, but the 'existing creative' framing implies when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
enrich_company_domainEnrich Company DomainARead-onlyInspect
Enrich a company DOMAIN with firmographics (industry, employee range, location).
Company-level only (no contact PII). Use to enrich a lead's email domain or an account.
RETURNS: {domain, name, employee_range, industry, city, state, enriched: bool}. Returns {enriched: false} when the domain can't be enriched or targeting is not configured.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company domain, e.g. 'metadata.io'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only/non-destructive/open-world, and the description adds meaningful behavior beyond that: an exact RETURNS object, a guaranteed enriched boolean, and the explicit {enriched:false} fallback when enrichment fails or targeting is not configured. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short, front-loaded statements: action, use-case/scope, and return contract. Every sentence adds information and there is no filler, making it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, no-output-schema enrichment tool, this is complete: it defines input semantics, scope boundaries, the full success return, and the failure representation. An agent has enough to call it correctly without further investigation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the single domain parameter at 100% coverage, so the description doesn't need to compensate. It adds useful context by relating the domain to a lead's email domain or an account, which tells the agent what values are acceptable beyond the schema's bare example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with a specific verb-resource pair ('Enrich a company DOMAIN') and lists the exact firmographic attributes returned, so an agent knows exactly what this tool does and can distinguish it from audience-creation and account-stat tools. The 'Company-level only (no contact PII)' boundary further sharpens the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit use cases: 'Use to enrich a lead's email domain or an account' and states an exclusion ('Company-level only, no contact PII'). It doesn't name an alternative sibling or say when not to use it beyond the PII exclusion, so it falls just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_target_groupEstimate Target GroupARead-onlyInspect
Estimate audience size for target group criteria before creating. Supports BOTH include AND exclude rules (criteria + audiences).
USE FOR: Validate audience size before creating, "how many people will this reach?", "preview audience size", test targeting combinations, preview impact of exclusion criteria/audiences.
CHANNELS: LINKEDIN (default) and REDDIT. Pass channel="REDDIT" to size a Reddit target group before create_reddit_target_group; its criteria ids come from search_reddit_criteria rather than search_target_group_criteria, and the rest of the call is identical (PRD-31759).
PREREQUISITE: All criteria IDs MUST come from search_target_group_criteria first (search_reddit_criteria for REDDIT).
CRITICAL FOR LINKEDIN: LOCATION must be FIRST criteria in include array with isModifiable=false.
TARGETING STRUCTURE (full example with include + exclude criteria + exclude audiences): { "include": [ { "isModifiable": false, "criteria": [{"type": "NATIVE_LOCATION", "data": [{"externalId": "urn:li:geo:103644278", "name": "United States"}]}], "audiences": [] }, { "isModifiable": true, "criteria": [{"type": "AGE", "data": [{"externalId": "urn:li:ageRange:(25,34)", "name": "25 to 34"}]}], "audiences": [] } ], "exclude": { "isModifiable": true, "criteria": [ {"type": "COMPANY_NAME", "data": [{"externalId": "urn:li:organization:1090", "name": "Philips"}]} ], "audiences": [ { "mdAudienceId": 45316, "name": "ICP Pharma LifeSci Leaders", "type": "FIRMOGRAPHIC_EXCLUDE", "matchCount": 213127, "matchCountType": "FIXED_SIZE", "inactive": false, "criteria": [{"type": "NATIVE_LOCATION", "data": [{"externalId": "urn:li:geo:103644278", "name": "United States"}]}] } ] } }
INCLUDE: Array of rule blocks. Each block = AND-group of criteria; multiple blocks are AND'd together.
EXCLUDE: Single object (NOT array) with criteria and audiences. Anyone matching exclude is removed from results.
WARNING: AUDIENCES ≠ TARGET GROUPS. Both include[].audiences and exclude.audiences accept Custom Audience records ONLY (the entities returned by get_matched_audiences). Target Groups (the entities returned by list_target_groups / retrieve_target_group_by_id) are a separate entity in a separate ID space and CANNOT be attached here; the platform silently drops or rejects them. If the user names "X" and only list_target_groups matches it (not get_matched_audiences), do NOT pass the Target Group's id as mdAudienceId. Stop, tell the user "X is a Target Group, not a Custom Audience", and offer to rebuild X as a Custom Audience (e.g. via create_audiences with the same criteria) before retrying.
INCLUDE AUDIENCES: include[].audiences accepts ANY Metadata audience type — there is NO allow-list and NO restriction to specific types. The audience must be live on the channel, though: a row with inactive=true (LinkedIn segment archived, failed or still building) is refused by the platform and sized at 0, so pick an active row. Pass any audience returned by the audience listing tools (e.g. FIRMOGRAPHIC_INCLUDE, FIRMOGRAPHIC_INCLUDE_SFDC, NATIVE_LINKEDIN, NATIVE_FACEBOOK, RETARGETING, TECHNOGRAPHIC, SFDC_ACCOUNT_DYNAMIC, MA_CONTACTS_DYNAMIC, CONTACT_LIST, and any other type, including types not enumerated in any tool schema). Type-name enums seen in create_audiences / search_audiences describe how audiences are CLASSIFIED, not which can be attached here. Caveat: estimates may under-report (or return zero) when combining server-resolved audiences (e.g. SFDC dynamic, retargeting) with native LinkedIn criteria — that is an estimate-side reconciliation issue, not a creation constraint, so a zero estimate does not necessarily mean the platform will reject the create call.
EXCLUDE AUDIENCES: To exclude an existing Metadata Custom Audience, provide its full object in exclude.audiences. The tool pre-flight-rejects placeholder values — never invent ids or types when you don't know them, call get_matched_audiences (or search_audiences) first and use the real values from the response:
mdAudienceId(integer, REQUIRED): The numeric Custom Audience ID fromget_matched_audiences, itscustomAudienceId/mdAudienceIdfield (e.g. 49067, 45316), NEVER that row'sid(the channel row id). NEVER the audience name string, NEVER a placeholder like 1/2/3/4 (real Custom Audience IDs are 5-digit numbers; the tool rejects anything under 100), and NEVER a Target Group id (those come fromlist_target_groups; see the AUDIENCES ≠ TARGET GROUPS note above).name(string, required): Audience name.type(string, required): Audience type, e.g.FIRMOGRAPHIC_EXCLUDE,RETARGETING_EXCLUDE,CONTACT_LIST_EXCLUDE(must be the EXCLUDE variant). NEVER the placeholder string "AUDIENCE" — the tool rejects that pre-flight.matchCount(int),matchCountType("FIXED_SIZE"),inactive(bool): metadata fields from the audience record. The tool pre-flight-rejects entries withinactive: true(an audience still matching after creation cannot be attached yet — attach it once it is active).criteria: The audience's own criteria array (copy from the audience's definition).
CRITERIA TYPES (all IDs from search_target_group_criteria), valid in BOTH include and exclude:
NATIVE_LOCATION / LOCATION: location data — MANDATORY FIRST in include. Multi-country geo goes in ONE location criterion with one {externalId, name} entry per country (e.g. "Canada and USA" = 2 entries in the same data array). Never silently drop a country the user named.
AGE, COMPANY_CATEGORY, COMPANY_GROWTH_RATE, INDUSTRY, COMPANY_NAME, REVENUE, EMPLOYEE: Array of {externalId, name}
JOB_FUNCTION, JOB_TITLE, MEMBER_GROUP, MEMBER_INTEREST, MEMBER_SKILL, MEMBER_BEHAVIOR, SENIORITY, FOLLOWED_COMPANIES: Array of {externalId, name}
YEARS_OF_EXPERIENCE_RANGE: {"min": 4, "max": 5}
RESPONSE: {matchCount, isMatchCountTooSmall, matchCountType, allowZeroMatchCount}
WORKFLOW: search_target_group_criteria → build targeting (include + optional exclude) → estimate_target_group → adjust → create_target_group
| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | Channel to estimate for. LINKEDIN (default) takes criteria ids from search_target_group_criteria; REDDIT takes them from search_reddit_criteria and is estimated the same way (PRD-31759). Omit for LinkedIn. | |
| targeting | No | Complete targeting configuration with include/exclude rules. Structure: { "include": [ { "criteria": [{"type": str, "data": object}], "audiences": [] } ], "exclude": {"criteria": [], "audiences": []} } All criteria IDs/references must come from search_target_group_criteria tool. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description goes far beyond by disclosing platform behaviors: the LINKEDIN location-first constraint, pre-flight rejection of placeholder values and inactive audiences, silent dropping of Target Groups, and the possibility of zero estimates for server-resolved audiences. These are non-obvious behaviors that materially affect invocation success, and they are all clearly stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is exceptionally well-structured with clear uppercase section headers (USE FOR, CHANNELS, PREREQUISITE, TARGETING STRUCTURE, etc.) and front-loaded purpose. Every section contains actionable, non-redundant information. The length is appropriate for the tool's complexity, and the structure makes it easy to scan. It is not verbose for verbosity's sake.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This tool has nested objects, no output schema, and complex constraints. The description covers all of it: the response shape is explicitly given ({matchCount, isMatchCountTooSmall, matchCountType, allowZeroMatchCount}), the workflow is spelled out (search → build → estimate → adjust → create), and edge cases (Reddit, Custom Audience vs Target Group, inactive audiences) are handled. Nothing an agent needs for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds enormous semantic depth. It provides a complete JSON example of the targeting structure, explains that exclude is an object (not an array), defines the meanings of include blocks (AND-groups), documents the exact shape of audience records, enumerates criterion types, and specifies which types are valid in exclude vs include. This far exceeds the minimal schema descriptions and prevents common invocation errors.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Estimate audience size for target group criteria before creating.' It explicitly lists use cases ('Validate audience size before creating', 'how many people will this reach?') and differentiates from siblings by naming the channels (LINKEDIN vs REDDIT) and prerequisites (search_target_group_criteria, search_reddit_criteria). This clearly distinguishes it from create_target_group, update_target_group, and search tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit 'USE FOR' section and a 'PREREQUISITE' section, telling the agent exactly when to call this tool and that criteria IDs must come from search_target_group_criteria (or search_reddit_criteria for REDDIT). It also gives channel-specific instructions (pass channel='REDDIT') and warns against confusing Custom Audiences with Target Groups, directing the agent to get_matched_audiences when needed. This is textbook when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
experiment_performance_statsGet Experiment Performance StatisticsARead-onlyInspect
Experiment-level performance statistics from Metadata.io Experiments API.
USE FOR:
Experiment-level metrics (spent, leads, impressions, clicks, cpl, ctr, mql)
Campaign comparisons (A vs B, time periods)
Triggered/influenced opportunities analysis
Pipeline opportunity analysis from campaigns
Campaign ingredients (audience size, channel, audience/ad/offer used)
ROI analysis, trend analysis, top performers
Creative usage by experiments
Filtering by experiment/campaign names
Filtering by launch status via launchedExperimentStatuses (FAILED / DISCONNECTED experiments are excluded by default — see that parameter)
NOT FOR:
Experiment pacing status ("which experiments are underpacing")
Ad-level triggered opportunities
Ingredient-level analysis (use performance_metrics)
RETURNED DATA: spent, clicks, impressions, leads, mqls, cpl, cpc, cpm, ctr | opens, sends, actionClicks, costPerOpen, costPerSend (CONVO/MESSAGE ads) | adTypes (list of ad types in this experiment) | triggeredAmount, oppsAmount, cpMql, mqlRate, conversionRate | experimentName, campaignName, audienceName, offerName, adName | audienceTypes, audienceSize, channel, goal | imageLibraryName | startDate, endDate, pacing, quarterIndex
CONVO/MESSAGE AD CAVEAT: when adTypes contains CONVO or MESSAGE, success is measured by opens, sends, and actionClicks (and costPerOpen / costPerSend), NOT clicks/ctr/cpc. An experiment with $100K+ spend and 0 clicks where adTypes includes CONVO can be a top performer — assess on the right metric. To rank conversational performance explicitly, use sort='actionClicks,desc' or sort='opens,desc' instead of the lead-gen defaults.
LINK FORMAT: /hub/advertise/experiments?name={wizExperimentName}
RULES:
'cpl2Score,desc' for Lead Gen/unspecified, 'cpc2Score,desc' for Brand Awareness
'triggeredAmount,desc' for ROI/pipeline, 'oppsAmount,desc' for influenced pipeline
size=1 for 'top' singular, size=requested for 'top X', size=50 for plural, size=15 default
failed/non-launched experiments are excluded by default; pass launchedExperimentStatuses=['Failed'] ONLY when the user explicitly asks about failures
this layer returns EVERY launched experiment with delivery in the window, including zero-lead and zero-spend ones, unless you set a min* filter yourself. An empty or short result means nothing matched the filters you sent, NOT that campaign-level reporting is broken or stale; re-run without the min* filters before telling the user anything is wrong
the response is ONE page: 'totalElements' is the full match count and 'totalPages' the page count at the requested 'size'. When totalElements exceeds the rows returned, fetch the next 'page' or repeat with a larger 'size' before compiling a full list; re-issuing the identical call returns the identical page
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Experiment name filter, matched as ONE substring per request. Use 'name' field (NOT experimentName) for specific experiment questions. Can be a single string or an array of strings for multiple experiments; an array is queried one name per request and the results are merged. Do NOT add additional parameters when filtering by specific experiment name. | |
| page | No | Page number for pagination (0-based). Use it with the 'size' you already sent to reach rows beyond the first page when 'totalElements' exceeds the rows returned. | |
| size | No | Number of results per page. RULES: size=1 for 'top' singular questions, size=requested number for 'top X' questions, size=50 for plural questions (e.g. 'campaigns'), size=30+ for multiple metrics analysis, size=15 as default when not specified. Raise it freely for full-dataset analytics — there is no small ceiling. | |
| sort | No | Sorting parameter. CRITICAL RULES: 'cpl2Score,desc' for Lead Generation or unspecified campaigns, 'cpc2Score,desc' for Brand Awareness, 'triggeredAmount,desc' for ROI/pipeline questions, 'oppsAmount,desc' for influenced pipeline, 'conversionRate,desc' for conversion rate, 'internalStatus,desc' for active experiments, use specific metric,desc when asked (e.g. 'impressions,desc', 'mqls,desc'). | cpl2Score,desc |
| goals | No | Campaign goal type. RULES: 'CPL' for Lead Generation campaigns, 'CTR' for Brand Awareness campaigns. Do NOT include for unspecified campaign types. When multiple metrics involved, use only the first metric's corresponding goal. | |
| adName | No | Filter by specific ad name (e.g., 'Sifted_WorkShift_Ad5_Beige'). Use 'adName' field when question asks about specific ad names. | |
| minCpc | No | Minimum cost per click threshold (whole dollars). OPTIONAL filter: omit it unless the question needs one. Do NOT set it for Lead Generation or unspecified campaign types. | |
| minCpl | No | Minimum cost per lead threshold (whole dollars). OPTIONAL filter: omit it unless the question needs one. It excludes every zero-lead experiment, whose CPL is undefined, so never pair it with minLeads=0 and never set it for Brand Awareness. | |
| endDate | No | End date in ISO 8601 format. Must end on last hour of date (e.g., '2024-11-21T23:59:59.999Z'). CRITICAL: Do NOT include if timeFrame parameter is used. For specific campaigns/experiments without timeframe, omit this parameter. | |
| metrics | No | List of metrics for secondary ordering when question involves multiple metrics (e.g., ['cpl', 'ctr', 'leads']). Only include when analyzing more than one metric simultaneously. Do NOT include for single metric questions. | |
| channels | No | Marketing channels to include | |
| minLeads | No | Minimum leads threshold. OPTIONAL filter: omit it unless the question needs one. Useful to keep only converting experiments in a Lead Generation ranking. Do NOT set it for Brand Awareness, nor when the user asks about zero-lead or 'no results' experiments. | |
| minSpend | No | Minimum spend threshold. OPTIONAL filter: omit it unless the question needs one. Useful when ranking Lead Generation performance and non-delivering experiments would be noise. Do NOT set it when the user asks about experiments with no spend, no leads or no results. | |
| minClicks | No | Minimum clicks threshold. OPTIONAL filter: omit it unless the question needs one. Useful in a Brand Awareness ranking. Do NOT set it for Lead Generation. | |
| offerName | No | Filter by specific offer name (e.g., 'AMER_ZO_EN_HBR Reimagining Work'). Use this field when question mentions specific offers. | |
| startDate | No | Start date in ISO 8601 format (e.g., '2024-10-18T00:00:00.000Z'). CRITICAL: Do NOT include if timeFrame parameter is used. Use last year of data if period cannot be inferred from question. For specific campaigns/experiments without timeframe, omit this parameter. | |
| timeFrame | No | Timeframe aggregation. CRITICAL RULES: Use ONLY for WEEK or QUARTER questions. NEVER use 'YEAR' - use startDate/endDate instead. If timeFrame is included, DO NOT add startDate or endDate parameters under any circumstances. | |
| offerTypes | No | Offer types filter. RULES: ['LP'] for lead gen forms/landing pages questions, ['LP', 'LG'] as default when offer types mentioned. LP=Landing Pages, LG=Lead Gen forms. Should NOT be empty when included. | |
| audienceName | No | Filter by target audience name (e.g., 'WTS EMEA Jan25_EMEAPitchbook') | |
| campaignName | No | Campaign name filter. Use when question is about specific campaign(s). Can be single string or array ['campaign1', 'campaign2'] for multiple campaigns. Do NOT include additional parameters when filtering by specific campaign name. | |
| visibilities | No | Visibility status filter. The platform knows only VISIBLE (live) and ARCHIVED; there is no HIDDEN value and sending one is rejected with a 400. | |
| audienceTypes | No | Comma-separated list of audience types (e.g., 'Spotlight Retargeting Contacts (Dynamic),Technographic (Aberdeen)') | |
| minAudienceSize | No | Minimum audience size. OPTIONAL filter: omit it unless the question needs one. | |
| imageLibraryName | No | Filter by creative/image name (e.g., 'JP - Square-Ad15.png'). Use 'imageLibraryName' field when question asks about specific creative names. | |
| launchedExperimentStatuses | No | Filter experiments by launch status. DEFAULT when omitted: successfully-launched experiments only (Active, WithoutSpend, Paused, Completed) — Failed and Disconnected are EXCLUDED, because a failed/non-launched experiment has 0 leads and is a non-starter, not a 'bottom performer'. Pass values explicitly to override: ['Active'] for live only, or ['Failed'] / ['Failed','Disconnected'] when the user explicitly asks which experiments failed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is known. The description adds substantial behavioral context: it lists returned data fields, explains the CONVO/MESSAGE metric switch, warns that zero-lead experiments are returned, clarifies that empty results mean filters matched nothing rather than broken reporting, and details pagination behavior (one page, totalElements vs totalPages). This far exceeds the annotation baseline and provides essential operational understanding.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long but well-structured with clear sections (USE FOR, NOT FOR, RETURNED DATA, CONVO/MESSAGE AD CAVEAT, LINK FORMAT, RULES). It is front-loaded with purpose and each rule serves a distinct need for a 25-parameter tool. The length is justified by complexity, but it could be tightened slightly without losing value, so 4 rather than 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (25 optional parameters, no output schema), the description is remarkably complete. It lists all returned metrics, explains edge cases (CONVO/MESSAGE ads, failed experiments), provides pagination guidance, and includes the link format. An agent has everything needed to call the tool correctly and interpret results, even without an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with each parameter having a description, but the tool description adds significant rules on top: size guidelines (1/50/15), sort selections per question type, critical warnings (e.g., minCpl excludes zero-lead experiments, minLeads=0 never paired with minCpl), and when to omit parameters (e.g., do not include timeFrame with startDate/endDate). This enriches parameter meaning far beyond the schema, making it highly actionable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns experiment-level performance statistics from Metadata.io Experiments API. It enumerates specific use cases (metrics, comparisons, pipeline analysis, creative usage) and explicitly excludes pacing status and ingredient-level analysis, naming the alternative tool (performance_metrics) for that scope. This precisely distinguishes it from the many sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit 'USE FOR' and 'NOT FOR' list, plus detailed rules for sort, size, and filter usage. It names performance_metrics as the tool for ingredient-level analysis, and the CONVO/MESSAGE caveat instructs when to use specific sorts. This gives an agent unambiguous decision criteria for when to select this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
experiments_keywords_statsGet Keyword Performance Statistics from ExperimentsARead-onlyInspect
Keyword performance data from active experiments with date range filtering.
USE FOR: Keyword performance across experiments, Google Ads / Microsoft Ads keyword metrics/trends, keyword ROI and conversions, search term effectiveness.
REQUIRED: Date range in YYYY-MM-DD to YYYY-MM-DD format.
PAGING: the response is one page: 'totalElements' is the full row count for the window and 'totalPages' the number of pages at the requested 'size'. When totalElements exceeds the rows returned, request the next 'page' (or repeat with a larger 'size') before compiling a keyword list; never report the remaining rows as unavailable.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Example: page=0 for the first page, page=1 for the next one. | |
| size | No | Number of keywords per page. Default: 50; raise it (up to 10000) to pull the full keyword set in one call. | |
| sort | No | Sorting criteria as field,direction (direction 'asc' or 'desc'). Sortable fields: keyword, wizExperimentName, adGroup, matchType, status, spend, impressions, clicks, ctr, cpc, cpm, cpl, leads, mqls, cpMQL, conversions, allConversions, interactions, qualityScoreHist, totalOpps, oppsAmount, totalTriggered, triggeredAmount. Default: 'spend,desc'. | spend,desc |
| endDate | Yes | End date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: '2025-12-31T23:59:59.999Z' | |
| startDate | Yes | Start date in ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ). Example: '2025-01-01T00:00:00.000Z' | |
| keywordOrExperimentName | No | Optional substring filter matched against the keyword text and the experiment name. Omit it to get every keyword in the window. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds valuable paging behavior: it explains totalElements, totalPages, and instructs to paginate or increase size before compiling a list, warning not to report rows as unavailable. This is additional operational context beyond the annotations, so it scores well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a purpose sentence, a USE FOR list, a REQUIRED note, and a PAGING paragraph. It is front-loaded with purpose and each section is relevant. It is not overly verbose, though the PAGING section is a bit detailed. Overall, it is concise and organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description provides essential operational details: date range requirement, pagination mechanics, and the fact it covers active experiments. It does not mention the optional keywordOrExperimentName filter or sorting, but those are in the schema. The description is complete enough for an agent to call the tool correctly, though it could briefly mention the return shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description mentions date range format as YYYY-MM-DD, which slightly conflicts with the schema's ISO 8601 format with timestamps. It does not add substantial meaning for other parameters beyond what the schema already explains. It clarifies required parameters and paging, but this is marginal. Hence a 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool provides keyword performance data from active experiments with date range filtering. It lists specific use cases (Google Ads / Microsoft Ads keyword metrics, ROI, conversions) which distinguishes it from simple keyword listing tools. However, it does not explicitly name a sibling alternative, so it's clear but not maximally differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section explicitly lists when to use this tool, covering keyword performance across experiments and specific metrics. It provides clear context but does not state when not to use it or mention alternative tools like list_keywords or experiment_performance_stats. Thus it has clear context but no exclusions, matching score 4.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fetch_creative_detailsFetch Creative DetailsBRead-onlyInspect
Get detailed information for specific creative assets by their IDs. Looks up each creative ID individually.
WHEN TO USE:
- Get metadata for specific creative assets
- Lookup creative names and content types
- Verify creative asset properties before using in ads
- Audit creative asset details and status
- Validate library IDs before ad creation
RETURNED INFORMATION:
- Creative asset name and ID
- Content type (IMAGE, VIDEO, GIF, DOCUMENT)
- File properties (size, dimensions, format)
- Upload and modification timestamps
- Visibility status and permissions
- Preview URLs and download links
- Associated metadata and tags
FEATURES:
- Batch lookup of multiple creative IDs
- Individual error handling for invalid/missing IDs
- Returns None for failed lookups while continuing others
- Detailed logging of API requests and responses
- Comprehensive metadata for each valid asset| Name | Required | Description | Default |
|---|---|---|---|
| creative_id | No | creative id to be query |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the description needn't restate safety. However, it claims 'Batch lookup of multiple creative IDs' and 'Returns None for failed lookups while continuing others,' which directly contradicts the schema that accepts only a single integer creative_id. This misrepresents the tool's actual behavior and could mislead the agent. The description adds no other behavioral detail beyond what annotations cover, and the batch claim is a significant negative.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (WHEN TO USE, RETURNED INFORMATION, FEATURES) and front-loads the core purpose. It is longer than necessary, with some redundancy (e.g., 'by their IDs' and 'Looks up each creative ID individually'), but remains readable and organized. The batch claim adds noise but doesn't harm overall structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read tool, the description provides extensive information about returned fields and features. However, it overpromises batch capability and doesn't clarify that only one ID can be queried at a time. Since there is no output schema, the description's list of returned information is useful, but the misleading batch feature and missing clarification about the single-ID constraint leave gaps that could cause incorrect usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a single parameter creative_id described as 'creative id to be query.' The description adds minimal parameter insight beyond repeating that lookups are by ID. It doesn't clarify the integer format or that only one ID can be provided per call. Baseline 3 is appropriate since the schema carries the load, but the description misses the chance to correct the singular/plural confusion.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Get detailed information for specific creative assets by their IDs.' It uses a specific verb and resource, and distinguishes from siblings like search_library_creatives_by_name by focusing on ID-based lookup. However, the plural 'IDs' contradicts the singular integer parameter, causing slight ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE' section lists concrete scenarios: getting metadata, verifying properties, auditing, and validating IDs. This provides clear context for when to invoke the tool. It does not explicitly state when not to use it or mention alternatives, but the use cases are specific and helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_lookalike_companiesFind Lookalike CompaniesARead-onlyInspect
Find companies similar to one or more seed domains (for audience expansion).
Company-level only. Use to expand a target list from known-good accounts.
RETURNS: {companies: [{domain, name, employee_range, industry, city, state}, ...]}. Returns {companies: []} when none are found or targeting is not configured.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max lookalikes to return (default 10). | |
| domains | Yes | Seed company domains, e.g. ['metadata.io']. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds useful behavioral detail: it returns a specific shape, returns an empty array when nothing is found, and notes the 'targeting is not configured' edge case. This goes beyond the annotation-provided safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, followed by the usage context and return format. Every sentence adds information; there is no filler or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read-only tool with fully described schema fields, the description is complete: it explains purpose, scope, return shape, and failure behavior. Since there is no output schema, the explicit RETURNS block is especially valuable and sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The schema already documents both 'domains' and 'limit'. The description adds contextual meaning like 'seed domains' and 'known-good accounts', but does not significantly extend parameter-level semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Find') and resource ('companies similar to seed domains') with a clear use case ('audience expansion'). The 'Company-level only' qualifier helps distinguish it from person-level or audience-creation tools among the many sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context: 'Use to expand a target list from known-good accounts.' It does not explicitly name alternative tools or state when not to use it, but the purpose is specific enough that an agent can select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_offer_urlFind Offer Landing-Page URLARead-onlyInspect
Locate the BEST specific landing-page URL for a marketing offer on a given domain.
Runs three discovery strategies in parallel:
1. Direct path probe — conventional paths per offer_type (e.g. /request-demo, /case-studies, /roi-calculator)
2. Sitemap scan — <loc> entries filtered by offer-type keywords + optional topic
3. Footer/body scrape — CTA/nav links matching the offer intent
Candidates are scored by specificity. Generic hub pages (/resources/, /content/, /library/, homepages)
are HARD REJECTED — this tool exists precisely to avoid shipping them.
USE THIS BEFORE create_update_offer WHENEVER offer_type = "Landing Page"
AND the user did NOT provide an explicit URL.
Do NOT guess a URL. Do NOT rely on web_search for landing pages — this tool is more reliable.
USER-PROVIDED URL OVERRIDE (HARD RULE):
If the user already specified a landing-page URL in their request (e.g. "use
https://acme.com/demo-fintech" or "point offers at our pricing page"), DO NOT
call find_offer_url — use the user's URL verbatim in create_update_offer.
Never overwrite an explicit user-provided URL, even if it looks generic.
WHEN TO USE:
- Before every create_update_offer call with offer_type="Landing Page"
- When you need a specific demo / case-study / whitepaper / ROI calculator / guide URL
- When web_search returned only generic /resources/ or homepage URLs
FALLBACK BEHAVIOR:
- On success: use `offer_url` verbatim in create_update_offer.landingPageUrl
- On success=false: DO NOT create a Landing Page offer. Switch to offer_type="Lead Gen" instead.
RETURNS:
{
"success": true,
"domain": "snowflake.com",
"offer_type": "case_study",
"topic": "fintech",
"offer_url": "https://www.snowflake.com/customers/square/",
"source": "sitemap",
"link_text": "Square",
"score": 95,
"steps_tried": ["direct-probe", "sitemap", "footer-scrape"],
"candidate_count": 42
}
On failure: { "success": false, "suggestion": "Switch offer_type to 'Lead Gen'..." }
EXAMPLES:
- find_offer_url(domain="snowflake.com", offer_type="case_study", topic="fintech")
- find_offer_url(domain="servicenow.com", offer_type="demo")
- find_offer_url(domain="mongodb.com", offer_type="roi_calculator")| Name | Required | Description | Default |
|---|---|---|---|
| topic | No | Optional topic keywords to bias scoring (e.g., 'fintech', 'servicenow integration', 'data warehousing'). Improves hit rate when the domain has many offers of the same type. | |
| domain | Yes | Company website URL or domain. Examples: 'snowflake.com', 'www.servicenow.com' | |
| offer_type | Yes | Type of offer content to locate. Drives which paths are probed and which keywords score higher. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses the three parallel discovery strategies, scoring behavior, hard rejection of generic hubs, failure fallback, and the exact return shape. The readOnlyHint and destructiveHint annotations align with this read-only lookup, and the description adds substantial behavioral detail beyond those annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with headed sections, bullet lists, an example return payload, and clearly separated rules. There is minor redundancy—such as repeating the user-provided-URL override—but the structure keeps high-value information easy to find.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description fully explains success and failure responses, return fields, fallback behavior, and invocation examples. No critical operational detail an agent would need in order to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes all three parameters at 100% coverage, so the baseline is 3. The description adds useful examples and clarifies how offer_type and topic influence the search, but it does not add significant meaning beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Locate the BEST specific landing-page URL for a marketing offer on a given domain.' It clearly distinguishes this tool from siblings like create_update_offer and web_search by announcing that generic hub pages are hard rejected and that this is a more reliable discovery path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use and when-not-to-use guidance: use before create_update_offer for offer_type='Landing Page' when no URL is provided, and never call it when the user supplied an explicit URL. It even names web_search as an inferior alternative and explains the fallback to offer_type='Lead Gen' on failure.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_privacy_urlFind Privacy URLARead-onlyInspect
Locate the privacy-policy URL for a given website domain.
Uses a waterfall strategy for maximum reliability:
1. robots.txt → extract Sitemap directives
2. sitemap.xml → search for privacy-related URLs in <loc> entries
3. Page scrape → footer / page body links (most reliable fallback)
USE FOR:
- Find a company's privacy policy URL before creating Lead Gen offers
- Auto-populate privacyUrl field in create_update_offer
- Verify privacy URL exists for GDPR/CCPA compliance checks
- Look up privacy page for any domain
WHEN TO USE:
- User asks "find the privacy URL for example.com"
- User wants to create an offer but doesn't know the privacy URL
- Before calling create_update_offer to auto-fill privacyUrl
- User asks "does this site have a privacy policy?"
RETURNS:
{
"privacy_url": "https://example.com/privacy-policy",
"source": "footer",
"link_text": "Privacy Policy",
"steps_tried": ["robots.txt + sitemap", "playwright-footer"],
"success": true
}
EXAMPLE: find_privacy_url(domain="metadata.io")| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company website URL or domain. Examples: 'metadata.io', 'www.bloomreach.com', 'https://example.com' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/openWorldHint annotations, the description discloses the waterfall strategy (robots.txt, sitemap.xml, page scrape), the fallback ordering, and the return shape. The agent knows exactly what will happen and what kind of result to expect, including the source, link_text, steps_tried, and success fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with a clear one-line summary, numbered waterfall steps, and labeled sections for use, when-to-use, returns, and example. It is somewhat long and has mild redundancy between 'USE FOR' and 'WHEN TO USE', but every major section contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output-schema annotation, the description includes a concrete RETURNS example covering privacy_url, source, link_text, steps_tried, and success. It also explains the multi-step behavioral flow and connects to create_update_offer, making the tool effectively self-contained for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already fully documents the domain parameter. The description adds an example call and reinforces 'any domain' but does not meaningfully extend the parameter semantics beyond what the schema provides, matching the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Locate the privacy-policy URL for a given website domain.' This clearly distinguishes the tool from siblings like find_offer_url by emphasizing the privacy-policy target, and the 'USE FOR' section reinforces this exact purpose without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives rich, explicit when-to-use guidance: before creating Lead Gen offers, to auto-populate privacyUrl in create_update_offer, for GDPR/CCPA checks, and for any domain lookup. It lacks explicit when-not-to-use statements or named alternatives, so it falls just short of a 5 but is far above merely implied usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fix_flexible_creativeFix Flexible Creative ImageADestructiveInspect
Apply a free-text AI edit to a flexible creative's BACKGROUND image and return the edited image URL. Instruction-based image-to-image edit (like edit_brand_creative), scoped to the background so the crisp editable text/logo layers are never touched.
USE FOR: "remove the glare", "make the sky warmer", "clean up the left side", "swap the desk for a laptop".
OUTPUT: the edited background image URL (the editor swaps the background layer).
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company domain for brand context (e.g. 'metadata.io'). | |
| image_source | Yes | URL of the background image to edit (PNG/JPG/WebP). Typically the flexible creative's current background. | |
| edit_instruction | Yes | Natural-language description of the fix(es). Can combine several changes in one request. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and readOnlyHint=false. The description adds useful context: it clarifies the edit is instruction-based, only affects the background layer, and returns the edited URL. It also mentions 'the editor swaps the background layer', which explains the mutation behavior. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured: a core purpose sentence, a scoping note, a 'USE FOR' line with examples, and an 'OUTPUT' line. Each sentence earns its place, and the most important info (purpose and scope) is front-loaded. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (3 params, no output schema, AI edit), the description covers the core behavior, gives usage examples, and states the output format. It also differentiates from a sibling. A minor gap is that it doesn't explicitly state whether the original creative is updated or if only the URL is returned, but the 'editor swaps the background layer' hints at it. Overall, it's sufficient for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage, providing descriptions for all three parameters (domain, image_source, edit_instruction). The tool description adds some value by giving example instructions in the 'USE FOR' section and clarifying that the edit is free-text, but it doesn't add meaning beyond what the schema already states for domain or image_source. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('apply'), resource ('flexible creative's BACKGROUND image'), and outcome ('return the edited image URL'). It explicitly differentiates from the sibling edit_brand_creative by scoping to the background and mentioning that text/logo layers are never touched. This gives a clear, unambiguous purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section provides concrete example instructions, and the scoping note ('scoped to the background so the crisp editable text/logo layers are never touched') implies when to use this over edit_brand_creative. However, it doesn't explicitly state 'use edit_brand_creative for whole-image edits' or list any other exclusions, so it's slightly below a perfect score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_brand_creativeGenerate Brand CreativeAInspect
Generate branded advertising images and designs using AI and company Brand DNA.
FLAT vs EDITABLE: this is the FLAT generator — it bakes the headline + CTA into the pixels and returns one finished PNG. For a creative the user can rearrange / retype / restyle before finalizing (the DEFAULT for a standalone "make me a creative" request), use generate_flexible_brand_creative instead. Use THIS flat tool when building an ad or feeding a campaign (the image flows straight into upload_image_creative -> create_update_image_ad, with no human edit-and-save step), or when a finished flat image / a batch of quick variations is explicitly wanted.
ALSO KNOWN AS: design ad, create ad image, make creative, generate banner, create advertisement visual, design campaign image, ad design, advertising artwork
KEYWORDS: design, creative, image, banner, ad, advertisement, visual, generate, create, artwork, graphic, brand, branded, logo, campaign asset
USE FOR:
- Creating new ad images/banners/creatives for campaigns
- Generating LinkedIn/Facebook/Instagram/Display ad visuals
- Making branded advertisements that match company style
- Designing campaign creative assets
WORKFLOW CONTEXT:
- PREREQUISITE: Call get_brand_kit first to check if brand exists
- NEXT STEPS: Use upload_image_creative to add to library, then create_update_image_ad
- PART OF: Campaign creation workflow (brand → creative → upload → ad → campaign)
COMMON QUERIES THAT NEED THIS:
- "create ads for my company"
- "design advertising images"
- "make branded banners"
- "generate creative for LinkedIn campaign"
- "I need ad visuals"
KEYWORDS: ad, advertisement, creative, image, banner, design, visual, brand, generate, create, linkedin, facebook, instagram, display, campaign asset
PROCESS: Checks for existing brand kit → (Creates brand kit only if missing) → Selects top 3 aligned reference ads → Enhances prompt with brand patterns → Generates optimized image → Returns URL (must upload before use in ads).
TEXT RULES:
- Wrap text in quotes: "Your Headline Here"
- Max 25 chars per phrase, 2-3 phrases max
- Good: "Boost ROI 30%" (13 chars) | Bad: "Supercharge Your Marketing Performance Today" (44 chars)
PLATFORMS: LinkedIn (16:9, B2B) | Facebook (1:1, eye-catching) | Instagram (4:5, mobile-first) | Display (16:9, high impact)
OUTPUT: Returns image URL. ALWAYS display/link the image for user to see.| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company domain to extract brand DNA from. Examples: 'docebo.com', 'metadata.io', 'bloomreach.com'. Do not include protocol (http/https). | |
| headline | Yes | Primary headline text to display in the creative. Keep to 25 characters or fewer for optimal rendering (hard cap 40 — the image model truncates or garbles longer text). Used to select aligned reference ads and guide visual hierarchy. Examples: 'Boost ROI by 30%', 'AI-Powered Marketing', 'Drive More Pipeline' | |
| logo_url | No | Optional direct URL to a logo image (e.g. the URL of a logo the user just uploaded in chat). When set, THIS logo is overlaid for this creative instead of the brand kit's logo or the one from Brandfetch. Use it when the user says things like 'use this logo' or 'use the logo I uploaded'. The uploaded logo is automatically expanded in-memory into clean variants (transparent, high-res, and both a light and dark version when the mark is a single color) for this creative only — nothing is persisted — so the placement model can pick the best fit for the background. To change a brand's logo permanently for all future creatives, call update_brand_kit with logo_url instead of passing it here. | |
| platform | No | Target platform for the creative. Each platform has specific dimensions, text limits, and best practices that will be automatically applied. 'instagram_story' is the vertical 9:16 canvas (Stories, Reels), the one to ask for when the still will be animated into a vertical video. Default: 'linkedin' | |
| include_cta | No | Whether to render a call-to-action (button or styled text link) in the creative. Set to false for surfaces that must not contain a CTA, e.g. stills that seed video ads, where the channel's ad unit provides the real CTA. Default: true | |
| include_logo | No | Whether to include a logo overlay on the generated creative. Set to false to get the raw creative without any logo. Default: true | |
| instructions | Yes | Natural language instructions describing the desired creative. Will be enhanced with brand DNA patterns including proven layouts, CTAs, colors, and tones. Examples: 'Create a professional B2B ad with clean design', 'Generate announcement for new AI feature launch', 'Design case study visual with modern aesthetic' | |
| logo_position | No | Force a specific logo position instead of using AI-recommended placement. If not provided, an AI model analyzes the creative to find the optimal position. | |
| logo_size_percent | No | Logo width as a percentage of the image width (e.g., 15 means the logo occupies 15% of the image width). If not provided, the AI recommends an optimal size. Typical range: 10-30. | |
| use_website_background | No | Use the brand website's background color as the creative's dominant background; brand primary colors then appear as accents (CTA button, shapes, highlights). Default: true. Set false when the user wants a brand-colored or model-chosen background instead. Silently ignored when the brand kit has no resolvable website background color. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly documents the process (brand kit check, reference ads, prompt enhancement), output type (URL), the requirement to upload the image before use, and text rules (character limits, quoting). It also mentions that the logo overlay is expanded in-memory without persistence. While annotations declare readOnlyHint=false, the description clarifies that generation is not destructive but produces a new asset.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is comprehensive but quite long, with repetition (KEYWORDS appears twice) and some redundant sections. However, it is front-loaded with the critical flat vs. flexible distinction and the workflow, and the detailed examples are useful rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (10 params, 5 platforms, integration with brand kit and upload workflow), the description covers everything an agent needs: prerequisites, next steps, text rules, platform dimensions, and output handling. The output is a URL with clear instruction to display it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds essential behavioral semantics, especially for logo_url (in-memory expansion, temporary change vs. update_brand_kit) and platform (including instagram_story as 9:16 and animated video use case). It also explains headline length limits and why include_cta should be false for certain surfaces.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it generates branded flat ad images with headline and CTA baked in, explicitly distinguishing it from the flexible generator sibling. It also lists 'ALSO KNOWN AS' and keywords that help match user queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use this flat tool vs generate_flexible_brand_creative, and provides detailed USE FOR scenarios, workflow context with prerequisites and next steps, and example queries that should trigger this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_brand_kitGenerate Brand KitAInspect
Analyze a company's brand from their website and extract brand identity. Fetch brand assets (logo, colors, fonts) and create a brand DNA document for consistent advertising.
ALSO KNOWN AS: analyze brand, get brand from website, extract brand identity, brand analysis, company branding, fetch brand, brand style guide
USE THIS TOOL WHEN USER WANTS TO:
- Analyze their brand from website
- Extract brand colors, logo, fonts
- Match their existing brand style
- Get brand identity for ads
- Create brand guidelines
COMMON USER PHRASES THAT NEED THIS TOOL:
- "match my brand"
- "my company website is [URL]"
- "analyze my brand"
- "get my brand colors"
- "brand style"
- "company branding"
- "use my brand"
WORKFLOW:
1. Call this tool with company domain
2. Returns brand DNA (colors, fonts, logo, style)
3. Use brand info in generate_brand_creative
PARAMETERS:
- domain: Company website URL (e.g., "dapta.ai", "example.com")
- brand_name: Optional brand name override
- force_regenerate: Set true to refresh existing brand kit
OUTPUT:
- Logo variations and usage guidelines
- Brand colors (primary, secondary, accent)
- Typography/fonts
- Messaging framework
- Channel-specific guidelines
IMPORTANT: Automatically checks if brand kit exists. Returns existing kit if found.
RETRY SCOPE: This tool handles ONE domain per call. When the user asks to retry or
regenerate the kit for specific named domain(s), call it ONLY for those domain(s),
with force_regenerate=true, starting with the domain the user named. NEVER widen the
request: domains the user did not name stay untouched, even if their kits were
generated together as a batch earlier in the conversation.
KEYWORDS: brand, website, URL, domain, logo, colors, fonts, identity, style, company, analyze, extract, branding, guidelines| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company website URL or domain | |
| brand_name | No | Optional brand name override | |
| sample_ad_urls | No | Optional ad image URLs to analyze (max 5) | |
| force_regenerate | No | If True, regenerate brand kit even if one already exists. Default: False |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses useful behavioral traits beyond annotations: it automatically checks for an existing brand kit and returns it, supports force_regenerate to refresh, and handles exactly one domain per call. Annotations already indicate readOnly=false and destructiveHint=false, so the description adds helpful operational detail about cache behavior and retry safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with headings and front-loaded purpose, but it is unnecessarily long. The 'ALSO KNOWN AS', 'COMMON USER PHRASES', and 'KEYWORDS' sections heavily overlap and repeat the same intent, making the description bloated. It would be stronger if trimmed to the core workflow, output, and retry guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema present, the description compensates with an OUTPUT section listing logo variations, colors, typography, messaging framework, and channel-specific guidelines. It also explains the single-domain behavior, existing-kit check, force_regenerate, and downstream use with generate_brand_creative. Minor gap: sample_ad_urls isn't explained in the narrative, but the schema covers it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description's PARAMETERS section mostly restates the schema (domain, brand_name, force_regenerate) and adds a domain example, but it omits sample_ad_urls entirely. The schema already covers parameter meaning, so the description adds limited extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific action ('Analyze a company's brand from their website and extract brand identity') and names the produced artifact (brand DNA document, brand kit). It also lists concrete use cases and common user phrases. However, it doesn't explicitly distinguish itself from the sibling get_brand_kit, especially since the description notes it returns an existing kit when found.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'USE THIS TOOL WHEN USER WANTS TO' and 'COMMON USER PHRASES' sections, plus a detailed RETRY SCOPE with clear instructions about which domains to regenerate and a 'NEVER widen the request' warning. It lacks an explicit 'when not to use this tool' or direct alternative routing (e.g., get_brand_kit), so it doesn't fully earn a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
generate_flexible_brand_creativeGenerate Flexible Brand CreativeAInspect
Generate an EDITABLE, layered brand creative: a clean AI background scene (no baked text) plus AI-placed, editable text/CTA/logo layers. Returns a structured layout document (JSON), NOT a flat image — the UI renders it in an editor the user can rearrange before saving.
USE FOR:
The DEFAULT for a standalone creative the user will review, refine, or use — "make me a creative", "design an ad", "give me options", "a creative I can tweak/edit".
Any request where the user should be able to move/retype the headline, restyle the CTA, swap the logo, add layers, or regenerate the background before finalizing.
DIFFERENT FROM generate_brand_creative: PREFER THIS for standalone creative requests. generate_brand_creative bakes headline + CTA into the pixels and returns one finished PNG; use that flat tool only when building an ad / feeding a campaign inline (the flat image flows straight into an ad, with no human edit-and-save step) or when a finished flat image is explicitly requested.
COPY DISCIPLINE: fewer layers = a cleaner layout the user can actually edit. Default to headline + cta (add subheadline only when it genuinely earns its place); pass body / disclaimer ONLY when the user explicitly asked for that copy.
RETURNS: a layered document — canvas dimensions, background image URL, brand colors/logo, and an ordered list of layers (headline, subheadline, body, cta, disclaimer, logo) with normalized positions and styling.
| Name | Required | Description | Default |
|---|---|---|---|
| cta | No | Optional call-to-action button text (e.g. 'Learn more'). | |
| body | No | Optional supporting body copy. Pass ONLY when the user explicitly asked for body copy — extra layers crowd the layout. | |
| domain | Yes | Company domain for brand DNA (e.g. 'metadata.io'). No protocol. | |
| headline | No | Headline copy to place as an editable layer. | |
| platform | No | Target platform (sets the default aspect ratio). Default: 'linkedin'. | |
| disclaimer | No | Optional fine-print/disclaimer copy. Pass ONLY when the user explicitly asked for a disclaimer. | |
| subheadline | No | Optional subheadline copy. | |
| aspect_ratio | No | Canvas shape, overriding the one 'platform' implies. Pass this whenever the user names a size or shape: '1:1' for square (e.g. 1080x1080), '16:9' for wide/landscape, '9:16' for a full-height story, '4:5' for portrait. Omit to keep the platform's default shape. | |
| include_logo | No | Add a brand logo layer (resolved from the brand kit). Default: true. | |
| instructions | Yes | Natural-language direction for the background scene and overall creative (e.g. 'clean B2B scene for an AI analytics launch'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the annotations by explaining the tool's non-destructive, non-final nature: it returns an editable JSON document that the UI renders in an editor for the user to rearrange before saving. It also discloses the copy discipline (fewer layers = cleaner layout) which is a behavioral trait. However, it does not explicitly state side effects (e.g., whether it persists anything) but the description implies no saving occurs. Given annotations already provide readOnlyHint=false and destructiveHint=false, the description adds meaningful context without contradiction, earning a 4.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (core description, USE FOR, DIFFERENT FROM, COPY DISCIPLINE, RETURNS). It is front-loaded with the most important information (what it returns and how it differs from the flat alternative). Every section adds value and no redundant sentences exist. The length is justified by the tool's complexity and the need to differentiate from a sibling.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 10 parameters and a complex output structure, the description is remarkably complete. It covers the output format (JSON layered document), the workflow (UI renders for editing), the copy discipline, and the exact use cases and exclusions. Since the schema fully documents all parameters, the description's guidance on when to pass which copy parameters completes the picture. An agent can call this tool correctly with the information provided, even without an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents each parameter. The description adds extra value by providing guidance on parameter usage: 'Default to headline + cta (add subheadline only when it genuinely earns its place); pass body / disclaimer ONLY when the user explicitly asked for that copy.' This gives semantic guidance beyond the schema, particularly for optional copy parameters. It doesn't repeat schema text, so it earns a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's specific purpose: generating an editable, layered brand creative with a clean AI background and editable text/CTA/logo layers, returning a structured layout document (JSON) rather than a flat image. It also distinguishes itself from the sibling generate_brand_creative by explicitly stating the difference (baked text vs. editable layers, flat PNG vs. document). This leaves no ambiguity about what the tool does and how it differs from a close alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section explicitly enumerates when to use this tool (default for standalone creative requests, any request where the user should edit/tweak) and the 'DIFFERENT FROM' section names the exact alternative (generate_brand_creative) and the conditions for choosing that instead (building an ad inline or explicitly requesting a finished flat image). This is explicit when/when-not guidance with a named sibling, which fully resolves selection ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_abm_account_listsGet ABM Account ListsARead-onlyInspect
Get account lists from the Metadata ABM Lists library. Retrieves uploaded CSV account lists, website retargeting lists, and their metadata.
WHEN TO USE:
- List all available account lists with pagination and filtering
- Search for specific account lists by filename
- Review account list details including status, type, and account counts
- Find lists by type (CSV, WEBSITE_RETARGETING, etc.)
- Check list readiness and report status
PARAMETERS:
- filename: Filter by filename (partial matching)
- page: Page number (default: 0)
- size: Results per page (default: 100, max: 100)
- sort: Sort criteria (default: "createdDate,desc")
- status: Filter by status (READY, PROCESSING, etc.)
- type: Filter by type (CSV, WEBSITE_RETARGETING, etc.)
RESPONSE INCLUDES:
- List metadata (id, name, filename, status, type)
- Account counts and audience associations
- Creation dates and file hashes
- Native targeting status
- Account report status
EXAMPLES:
- get_abm_account_lists() - Get all account lists
- get_abm_account_lists(filename="test_acl.csv") - Find specific list
- get_abm_account_lists(type="CSV") - Get only CSV lists
- get_abm_account_lists(status="READY") - Get ready lists| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based) | |
| size | No | Number of results per page | |
| sort | No | Sort criteria (e.g., 'createdDate,desc', 'name,asc', 'accountsCount,desc') | createdDate,desc |
| type | No | Filter by list type (e.g., CSV, WEBSITE_RETARGETING) | |
| status | No | Filter by status (e.g., READY, PROCESSING, ERROR) | |
| filename | No | Filter by account list filename (supports partial matching) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds useful behavioral context by describing retrieval semantics, supported filters, and response contents such as account counts, audience associations, creation dates, and file hashes. This is valuable given there is no output schema to describe the return envelope.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections for when to use, parameters, response contents, and examples, and it front-loads the core purpose. It is somewhat long and repeats some parameter information already in the schema, but each section contributes useful decision support.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with six optional parameters and no output schema, the description covers enough context: use cases, parameter behavior, response contents, and examples for common calls. The annotations cover safety, and the description fills the output format gap since no output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds meaning by giving example values for type and status (e.g., CSV, WEBSITE_RETARGETING, READY, PROCESSING), default values, and concrete usage examples for each parameter beyond the schema's descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the specific verb 'Get account lists from the Metadata ABM Lists library' and clarifies the exact resource scope, including CSV lists, website retargeting lists, and their metadata. It also lists distinct operations such as listing, filtering by filename, and type, which distinguishes it from many sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE section clearly enumerates use cases: listing all account lists, searching by filename, reviewing details, filtering by type, and checking readiness. It provides strong context but does not explicitly name sibling tools or state when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_detailsGet Account DetailsARead-onlyInspect
Current user and account information.
USE FOR: "Which account am I using?", "Who am I logged in as?", "What's my account name/status?", "What channels are enabled?", "What's my subscription/plan?"
Returns authenticated user details and associated account information.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds value by specifying what behavior to expect: it returns authenticated user details and associated account information, including account status, enabled channels, and plan. This explains the read-only scope without repeating annotation values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with a one-sentence summary. The USE FOR list is helpful, though the final sentence slightly overlaps with the opening summary ('Current user and account information' vs. 'Returns authenticated user details and associated account information'), making it less crisp than it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter read-only getter with no output schema, the description adequately explains what the tool returns: authenticated user details, account status, channels, and plan. It does not detail exact response fields or note that no parameters are required, but the schema covers the parameter aspect and the tool is simple enough that this is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and schema description coverage is 100%, so the schema fully documents the empty parameter set. With no parameters to explain, the description does not need to add parameter meaning. The baseline of 4 applies here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns current user and account information, with specific use-case questions like 'Which account am I using?' and 'What's my account name/status?'. It is distinguishable from sibling tools such as list_user_accounts, which handles account listings, though it does not explicitly contrast itself with those siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section provides concrete example queries that signal when this tool is appropriate, such as identifying the active account or checking subscription/plan. It does not explicitly mention when not to use it or name alternatives, but the context is clear enough for an agent to route to this tool correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_opportunities_insightsGet Account Opportunities InsightsCRead-onlyInspect
Get opportunities for domain(s) with status filtering and pagination.
STATUS VALUES: NO_OPPS, OPEN, CLOSED_WON, CLOSED_LOST
SORT OPTIONS: lastTouchDate (default), status, name, amount
PAGINATION: Use small page sizes (25-50) with sequential calls.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 0-based page number. | |
| size | No | Items per page (default 25, max 10000). Raise it to pull the full set in one call. | |
| sort | No | Sort field. Default: lastTouchDate | lastTouchDate |
| status | No | Filter by status. Omit for all. | |
| domains | Yes | Domain strings. E.g., ['metadata.io'] | |
| endDate | No | ISO 8601 format. | |
| startDate | No | ISO 8601 format. E.g., '2025-01-01T00:00:00.000Z' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds pagination guidance ('Use small page sizes (25-50) with sequential calls') and default sort, which is beyond annotations. However, this guidance directly contradicts the input schema's size description ('Raise it to pull the full set in one call'), making the behavior advice misleading rather than transparent. It also omits any mention of date range handling or output format. Given the contradictory advice, the disclosure is poor.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured, with a clear purpose sentence followed by terse labeled sections (STATUS VALUES, SORT OPTIONS, PAGINATION). It front-loads the main action. However, the inclusion of the contradictory pagination guidance is a substantive error, though it does not affect the structure's efficiency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 7 parameters and no output schema, with annotations covering safety. The description covers status, sort, and pagination, but not date range parameters or return values. More critically, the pagination advice conflicts with the schema, leaving an agent uncertain whether to use small pages or raise size. This is a significant gap in actionable completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all parameters have descriptions. The description repeats enum values and sort options already in the schema. Its only unique parameter advice – pagination – conflicts with the schema's own described behavior (schema suggests raising size for one call, description advises small pages and sequential calls). This contradictory guidance undermines rather than adds semantic value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: retrieve opportunities for given domains with status filtering and pagination. The verb 'Get' and resource 'opportunities' are specific, and it mentions filtering and pagination capabilities. While it does not explicitly contrast itself with siblings like get_account_summary_insights, the 'opportunities' scope is distinct enough. No tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives operational details (status values, sort options, pagination strategy) but does not state when to choose this tool over alternatives like get_account_summary_insights or get_insights_report. Usage is implied by the resource name, but there are no explicit exclusions or alternative routing. So it's adequate but not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_summary_insightsGet Account Summary InsightsARead-onlyInspect
Get comprehensive account details for specific domain(s).
USE FOR: Quick lookup of specific company information, engagement metrics, revenue data. DO NOT USE FOR: Bulk analysis or complex filtering (use get_insights_report instead).
RETURNS: Engagement metrics (totalTouches, channels, websiteVisits), revenue data (openOppsAmount, closedWonOppsAmount), company info (name, industry, employees, engagementScore).
| Name | Required | Description | Default |
|---|---|---|---|
| domains | Yes | Domain strings. E.g., ['metadata.io'] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the agent knows this is a safe read operation. The description adds the scope constraint (specific domains, not bulk) and the return categories, which is useful context. However, it doesn't disclose behavior like whether multiple domains are processed in one call, error behavior, or rate limits. With annotations covering the safety profile, a 3 is appropriate – the description adds some value but not rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the core purpose is in the first sentence, followed by clear USE FOR / DO NOT USE FOR / RETURNS sections. Every sentence earns its place, and the structure makes it scannable for an agent. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read-only lookup tool with 100% schema coverage and annotations covering the safety profile, the description is nearly complete. It states the purpose, the alternative, and the return categories. The only minor gap is that it doesn't describe pagination or limits on the number of domains, but that is a small omission given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents the 'domains' parameter with an example. The description adds that the parameter is for 'specific domain(s)' and implies the lookup scope, but doesn't add syntax or format details beyond what the schema provides. Baseline 3 is correct when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), a specific resource ('account summary insights' for specific domains), and explicitly lists what it returns (engagement metrics, revenue data, company info). It also distinguishes itself from get_insights_report by naming the sibling and the condition that selects it. An agent can tell this apart from get_account_details and get_insights_report without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'USE FOR: Quick lookup of specific company information, engagement metrics, revenue data' and 'DO NOT USE FOR: Bulk analysis or complex filtering (use get_insights_report instead)'. This gives clear when-to-use and when-not-to-use guidance, and names the alternative tool. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_utm_defaultsGet Account UTM DefaultsARead-onlyInspect
Read the ACCOUNT-level UTM defaults - the tracking parameters every campaign channel inherits unless it stores its own.
KEYWORDS: utm, utms, utm_source, utm_medium, utm_campaign, utm_term, utm_content, tracking parameters, account default, defaults, inherited, placeholder, UPDATE ME
USE THIS TOOL WHEN THE USER ASKS:
- "What are our default UTMs?" / "What UTM settings does the account use?"
- "Which channels have customised UTM defaults?"
- As the baseline before judging whether a campaign overrides anything.
INHERITANCE RULE - READ BEFORE ANSWERING ANY UTM QUESTION:
UTMs are inherited, never blank. A campaign channel with an empty stored
mapping does NOT have "no UTMs" - it tracks with the account's UTM defaults,
and where the account set nothing it tracks with the Metadata platform default.
Roughly half of all channel rows in production are in that inherited state.
NEVER report "no UTMs configured" from an empty stored field: report the
resolved value and its origin.
ORIGIN IS PER CHANNEL, not per key: a channel with an empty stored mapping
inherits the account default whole, so a channel whose resolved mapping differs
at all from that is stored on the campaign and every one of its values is an
override. The per-key `same_as_default` flag says whether that one key happens
to match the default anyway.
ORIGIN VALUES:
- campaign_override: stored on this campaign channel, differs from what it would inherit.
- account_default: inherited from this account's UTM defaults.
- platform_default: inherited from the Metadata-wide default (account set nothing).
- not_set: the channel really has no UTM mapping (non-sponsored channels only).
HONEST LIMIT: a campaign that stores a mapping identical to the default it
would inherit is reported as inherited. The platform returns resolved values
with no provenance, so that case cannot be distinguished - say so rather than
claiming the campaign has no override.
Takes no parameters - the account comes from the caller's credentials.
There is no cross-account lookup.
RESPONSE SHAPE:
{
"channels": {
"LINKEDIN": {"origin": "account_default", "values": {"UTM_SOURCE": "Acme", ...}},
"FACEBOOK": {"origin": "platform_default", "values": {"UTM_SOURCE": "Metadata", ...}}
},
"platform_default": {"UTM_SOURCE": "Metadata", "UTM_MEDIUM": "AD_CHANNEL", ...},
"notes": ["..."]
}
A channel reported as platform_default was never customised on this account; the
values shown are the ones campaigns actually inherit, not a blank.
READ-ONLY. No tool here edits the defaults (set_campaign_utms edits ONE campaign
channel's mapping, never the account defaults).| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral context: the inheritance rule (UTMs are never blank), the three origin values (campaign_override, account_default, platform_default, not_set), the honest limit about indistinguishable identical mappings, and the explicit READ-ONLY statement. It also clarifies that there is no cross-account lookup, which is not apparent from the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headers (KEYWORDS, USE THIS TOOL WHEN, INHERITANCE RULE, ORIGIN VALUES, HONEST LIMIT, RESPONSE SHAPE, READ-ONLY). It front-loads the core purpose and then provides necessary context for correct usage. While verbose, the complexity of the inheritance semantics justifies the length. Every section adds value, though it could be trimmed slightly without losing critical information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters and no output schema, the description fully compensates by providing a concrete response shape example, detailed origin value definitions, and the inheritance rule that is essential for interpreting results. It also covers the edge case of identical mappings and clarifies that no tool edits defaults. Nothing an agent needs to call and interpret this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters, so there is no parameter detail to explain. The description explicitly states 'Takes no parameters - the account comes from the caller's credentials,' which resolves any ambiguity about how the account is identified. Since there are no params, the baseline is 4, and the description adds this clarification, meriting a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement of purpose: 'Read the ACCOUNT-level UTM defaults - the tracking parameters every campaign channel inherits unless it stores its own.' This clearly identifies the resource (account-level UTM defaults) and the action (read). It also distinguishes itself from sibling tools like get_campaign_utms and set_campaign_utms by naming them, making it easy for an agent to select the right one.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly lists when to use the tool with concrete user queries ('What are our default UTMs?', 'Which channels have customised UTM defaults?') and frames it as the baseline for judging campaign overrides. It also contrasts with set_campaign_utms ('edits ONE campaign channel's mapping, never the account defaults'), providing clear guidance on when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ad_detailsGet Ad DetailsARead-onlyInspect
Get complete details and configuration for one or more ads from the Metadata platform.
USAGE INSTRUCTIONS FOR LLM:
Use this tool when users want to:
- Get complete ad details by ad ID
- Retrieve ad configuration including content, targeting, and creative assets
- Check existing ad settings before making modifications
- Analyze ad performance data and configuration
- Get creative library information associated with ads
- Extract ad content like text, headline, CTA, links for reference
- the value returned libraryCreative labelName corresponds to the library/image name.
WHEN TO USE:
- User asks "show me ad details for ID X"
- User wants to see ad configuration: "what's in ad 182124?"
- User needs ad content: "get the text/headline/CTA from ad Y"
- User wants to check ad settings before editing
- User asks "what creative is used in ad Z?"
- User needs to analyze existing ad setup
INPUT PARAMETERS:
- ids: Flexible format for specifying ad IDs:
* Single integer: 182124
* Comma-separated string: "182124,182123,182125"
EXAMPLE CALLS:
- get_ad_details(ids=182124) (single)
- get_ad_details(ids="182124,182123,182125") (multiple)
DETAILED RESPONSE INCLUDES:
AD CONFIGURATION:
- Basic info: id, name, channelType (FACEBOOK/LINKEDIN), adType (IMAGE/VIDEO/etc.)
- Status: completionStatus, aiState, renameAllowed
AD CONTENT:
- text: Main ad copy/body text
- headline: Ad headline text
- link: Landing page URL
- description: Additional ad description
- ctaType: Call-to-action button (e.g., "Get_Demo", "Learn_More")
CREATIVE ASSET DETAILS:
- libraryId: Creative asset ID reference
- libraryCreative object with:
- id, labelName (filename)
- url: Full-size creative asset URL
- thumbnail: Thumbnail URL
- dimensions: width, height in pixels
- sizeInKb: File size
- content_type: image/png, image/jpeg, etc.
- created_date: When creative was uploaded
METADATA:
- tags: Ad tags/labels
- created/modified dates
- AI processing state
ERROR HANDLING:
- If ad ID doesn't exist, API returns empty array
- Always validate that IDs are integers before making request
- Handle both single ID and multiple ID requests
EXAMPLE USAGE:
- get_ad_details(ids=182124) - Single ad by integer
- get_ad_details(ids="182124,182123,182125") - Multiple ads by comma-separated string| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Ad ID(s) to get details for. Can be: single integer (182124) or comma-separated string ('182124,182123'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral context beyond the readOnly/non-destructive annotations: it explains that non-existent IDs return an empty array, advises validating integer IDs, and clarifies that libraryCreative labelName corresponds to the filename. This is useful operational disclosure, though it omits rate-limit or pagination details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and well-sectioned, but it is overlong and repetitive: 'USAGE INSTRUCTIONS' and 'WHEN TO USE' overlap heavily, and 'EXAMPLE CALLS' duplicates 'EXAMPLE USAGE' with identical examples. It would be stronger if these redundant sections were merged.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by thoroughly detailing the response structure: ad configuration, content fields, creative asset details, metadata, and error handling. For a one-parameter read-only tool, an agent has enough context to invoke it and interpret results confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents ids, so the baseline is 3. The description adds value through call syntax examples and the explicit instruction to validate IDs as integers, plus handling of both single and comma-separated multiple IDs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description immediately states 'Get complete details and configuration for one or more ads from the Metadata platform,' specifying a clear verb and resource. It also enumerates concrete use cases like retrieving configuration, content, creative assets, and pre-edit checks, making it distinguishable from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated 'WHEN TO USE' section gives concrete user phrasings and intents, so an agent knows when to invoke this tool. However, it never names alternatives like search_ads_by_names or fetch_creative_details and provides no explicit when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_audience_detailsGet Audience DetailsARead-onlyInspect
Custom audience information from Metadata platform: configurations, targeting criteria, size metrics, performance.
USE FOR: List audiences with pagination/filtering, get specific audience by ID/name, analyze configurations and targeting, review size and performance.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Filter by audience name (supports partial matching) | |
| page | No | Page number for pagination (0-based) | |
| size | No | Number of results per page | |
| sort | No | Sort criteria (e.g., 'creationDate,desc', 'name,asc', 'audienceSize,desc') | creationDate,desc |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, covering the safety profile. The description adds that it provides configurations, targeting, size, and performance, but does not disclose whether the response is a list or single object, nor any potential side effects. Given the annotations, this is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: the first states the core purpose, and the second (USE FOR) gives usage scenarios. It is concise, front-loaded, and contains no fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 4 parameters, 100% schema coverage, and no output schema. The description lists the categories of information returned but does not specify the exact response structure or whether it returns a list or a single item. Given the absence of an output schema and the ambiguity around 'ID/name' (only name is available), the description is adequate but could be more explicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all parameters (name, page, size, sort) are already well documented in the schema. The description adds a minor hint about pagination and filtering, but does not explain the sort parameter or clarify that 'ID' is not actually a parameter (only name is). This is a baseline score given the high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool retrieves custom audience information from the Metadata platform, listing specific aspects: configurations, targeting criteria, size metrics, and performance. It also specifies use cases: listing with pagination/filtering, getting by ID/name, analyzing configurations, and reviewing size/performance. This distinguishes it from sibling tools like create_audience or archive_audience.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a 'USE FOR' line that explicitly lists when to use the tool: listing audiences with pagination/filtering, getting by ID/name, analyzing configurations and targeting, and reviewing size/performance. This provides clear context, though it does not explicitly mention when not to use it or name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_brand_kitGet Brand KitARead-onlyInspect
Retrieve current brand kit configuration for a company.
USE FOR: Check stored brand info, review colors/fonts/logos before updating, verify brand kit exists, view brand guidelines.
RETURNS: domain, longDescription, logos[], colors[], fonts[], industries
Accepts URLs with/without protocol, normalizes to domain (e.g., "www.example.com" → "example_com.json").
Requires brand kit to exist (created via generate_brand_kit).| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company website URL or domain. Examples: 'metadata.io', 'www.bloomreach.com', 'https://example.com' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral details: URL normalization behavior ('www.example.com' → 'example_com.json') and the requirement that the brand kit exists. These go beyond the annotations and inform the agent about input handling and preconditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear sections (USE FOR, RETURNS) and is front-loaded with the purpose. It's not overly verbose; each section adds value. The main purpose is stated first, followed by useful details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one parameter, the description covers the purpose, return fields, prerequisites, and input normalization. It lacks explicit error handling or missing-brand behavior, but given the simplicity and the presence of annotations, it is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a well-described `domain` parameter including examples. The description adds the normalization behavior (accepts URLs with/without protocol, converts to domain) which is not in the schema, enhancing understanding of how the parameter is processed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Retrieve' and the resource 'brand kit configuration', making the core action explicit. The 'USE FOR' section enumerates specific use cases (check stored info, review colors/fonts/logos before updating, verify existence) which distinguish it from siblings like generate_brand_kit and update_brand_kit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit use cases and notes the prerequisite that a brand kit must exist, implying when to use this tool vs. generate_brand_kit. However, it doesn't explicitly name alternatives or state exclusions (e.g., when not to use), so it's clear but not fully explicit about routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_budget_groupGet Budget GroupARead-onlyInspect
Get configuration and settings for a budget group (NOT performance data).
KEYWORDS: budget, group, settings, configuration, details, allocation, campaigns
WHEN TO USE:
- "Show me the [group name] budget group settings/configuration"
- "What campaigns are in the [group name] budget group?"
- "What's the budget allocation for [group name]?"
- Getting budget group metadata without performance metrics
WHEN NOT TO USE:
- Performance questions (spend, CPL, leads, conversions) → use budget_group_performance instead
- Questions like "how did X perform" or "total spend for X" → use budget_group_performance instead
NOTE: If the user is asking about performance metrics (spend, leads, CPL, etc.),
use budget_group_performance directly - it accepts the name and handles ID lookup internally.
Returns complete budget group information including campaigns, budget allocation, and settings.| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The name of the budget group to search for. Example: 'Brand' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds behavioral context by clarifying the tool returns configuration and settings rather than performance data, and it specifies the output contains campaigns, budget allocation, and settings. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections, but it is somewhat verbose with multiple example phrases and a note. It is front-loaded with the core purpose and uses formatting (caps, line breaks) to aid scanning. It earns its length by providing actionable routing and examples, though a trim would not hurt.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter getter with annotations and no output schema, the description fully covers purpose, usage, exclusions, and return content. It explicitly distinguishes from the performance sibling and even notes the alternative's ID handling. No additional information is needed for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage for the single 'name' parameter, which is already described with an example. The description does not add further parameter-specific semantics; its examples are usage phrasings rather than parameter details. Baseline 3 is appropriate when the schema fully documents the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get configuration and settings for a budget group' and explicitly clarifies it is NOT performance data. It also provides keywords and example queries, making the purpose unmistakable and distinct from the sibling budget_group_performance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has dedicated 'WHEN TO USE' and 'WHEN NOT TO USE' sections with concrete example phrasings, and it explicitly names the alternative tool (budget_group_performance) for performance questions, including a note that the alternative handles ID lookup internally. This is explicit routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaign_by_wizard_idGet Campaign by Wizard IDARead-onlyInspect
Get full campaign details by its wizard campaign ID, including channels, audiences, ads, and budget configuration.
KEYWORDS: campaign, get, details, wizard, id, lookup, channels, audiences, ads, budget, configuration
WHEN TO USE:
- User wants to see full details of a specific campaign by its ID
- User needs to inspect channel configurations, audiences, ad groups, or budget settings for a campaign
- After creating a campaign, to verify its full configuration
- To retrieve the complete campaign structure including all channel details
RETURNS:
Full campaign details in a structured format including:
- Campaign ID, name, status, dates
- Optimization group / budget group details
- Per-channel configuration (enabled, daily budget, audiences, ad groups, lead gen forms, bid strategy)
- Summary statistics (total channels, enabled channels, total daily budget, goal)
PARAMETERS:
- campaign_id: The wizard campaign ID (integer, required)
CAMPAIGN ID SOURCES:
- search_campaigns_by_names tool (returns campaign IDs)
- create_campaign tool response (returns campaign_id)
- Campaign management interface URLs| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The wizard campaign ID to retrieve details for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=true and destructiveHint=false, annotations carry the safety profile; the description adds value by itemizing the response contents (Campaign ID, name, status, dates, per-channel configuration, summary statistics), which matters here because there is no output schema. It does not cover error behavior or invalid-ID cases, but nothing contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded in the first sentence and the body is organized into clearly labeled sections (WHEN TO USE, RETURNS, PARAMETERS, CAMPAIGN ID SOURCES). The KEYWORDS block is redundant filler, restating terms already present in the prose (campaign, get, details, wizard, id, channels, audiences, ads, budget) without adding agent-decision value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, read-only tool with no output schema, the description is complete: purpose, trigger conditions, return structure, parameter semantics, and ID provenance are all covered. No information an agent needs to invoke this tool correctly is missing; the only gaps (invalid-ID behavior) are marginal at this level of complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the PARAMETERS block largely restates the schema (integer, required). The CAMPAIGN ID SOURCES section goes beyond the schema by telling the agent where a valid value comes from — search_campaigns_by_names, the create_campaign response, or management UI URLs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence is specific: 'Get full campaign details by its wizard campaign ID, including channels, audiences, ads, and budget configuration' names the verb, resource, key, and scope. It distinguishes itself from siblings like get_campaign_utms and get_campaign_targeting_locations, which return only a subset, and from search_campaigns_by_names and list_wizard_campaigns, which are search/list operations rather than full-detail lookups.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated WHEN TO USE section lists concrete triggers: inspecting channel/audience/budget configuration, verifying a campaign after creation, and retrieving the full structure. The CAMPAIGN ID SOURCES section further routes the agent to companion tools (search_campaigns_by_names, create_campaign) for obtaining the required ID. It lacks explicit exclusions — e.g., which sibling to choose when only a subset of fields is needed — so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaign_targeting_locationsGet Campaign Targeting LocationsARead-onlyInspect
Where a campaign actually TARGETS, by channel, with the platform's location ids resolved to country and state names.
KEYWORDS: campaign, targeting, location, geo, country, region, where, targets, germany, dach, emea, market, geographic
WHEN TO USE:
- "Which campaigns target <country>?" / "Do we run anything in Germany?"
- "Where is this campaign targeted?" before editing or launching it
- Any question about geographic TARGETING
DO NOT ANSWER GEO TARGETING FROM demographic_country_stats. That tool reports where ads were SERVED (delivery); this one reports where they are AIMED. The two disagree routinely, and answering a targeting question from delivery data is how the agent once told an account with 68 Germany campaigns that it had none.
RETURNS:
- campaigns: [{campaignId, name, status, channels[], summary}]
- channels[]: {channel, enabled, geoSource, targeting{resolved, countries[{id,name}], states[], ...}, exclusions}
geoSource is "search_ad_location" (Google/Microsoft, held on the channel) or
"native_audience" (LinkedIn/Meta/Reddit, held on the attached audience).
- summary: {countries[], unresolvedIds[], partial}
- query: {countryFilter, scanned, matched, unreadable[]}
- limitations: []
READING THE RESULT - these three distinctions are the whole point:
- countries: [] means nothing is targeted. targeting.resolved false means it could NOT BE READ. Never report the second as the first.
- exclusions.readable is ALWAYS false: the platform offers no GET for negative locations. Never state that a campaign excludes, or does not exclude, anywhere.
- summary.partial true means this answer is incomplete. Say so rather than presenting it as a full list.
- If `limitations` mentions truncation, you have NOT seen the whole account. Re-call with a higher max_campaigns before answering "there are none".
PARAMETERS:
- campaign_ids: specific wizard campaign ids (optional)
- country_names: filter to campaigns targeting these, e.g. ["Germany"] (optional). Names must match the platform catalog; unmatched names are reported, never silently dropped.
- max_campaigns: cap when scanning the account (default 25, max 100)
With neither campaign_ids nor country_names, returns the most recent campaigns up to max_campaigns.| Name | Required | Description | Default |
|---|---|---|---|
| campaign_ids | No | Wizard campaign ids to read. Omit to scan the account. | |
| country_names | No | Filter to campaigns targeting these countries, e.g. ["Germany", "Austria"]. | |
| max_campaigns | No | Cap on campaigns read when scanning (default 25, max 100). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=true and destructiveHint=false, but the description adds critical behavioral details: exclusions.readable is ALWAYS false, summary.partial indicates incomplete results, and truncation in limitations means the account wasn't fully scanned. These go far beyond the annotation's safety hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized into keywords, when-to-use, returns, reading-the-result, and parameters. It front-loads the core purpose and uses bolded sections. Though verbose, each section carries essential caveats that an agent needs to interpret results correctly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Extremely complete for a complex read tool with no output schema. It explains the return structure in detail, covers interpretation pitfalls (empty vs unresolved, exclusions not readable, partial results, truncation), and parameter semantics. Nothing an agent needs to call and interpret correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters, so baseline is 3. The description adds value by noting that country_names must match the platform catalog and unmatched names are reported, not dropped, and explains the default scan behavior when neither filter is provided. Slightly above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: reports where campaigns target by channel, resolving platform location ids to country/state names. Clearly differentiates from demographic_country_stats, which reports delivery, not targeting.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit WHEN TO USE section with concrete example questions and a DO NOT USE directive naming the sibling tool and explaining the delivery-vs-targeting distinction. Also advises when to use before editing or launching.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaign_utmsGet Campaign UTMsARead-onlyInspect
Read ONE campaign's resolved UTM tracking parameters per channel, each value tagged with where it came from.
KEYWORDS: utm, utms, utm_source, utm_medium, utm_campaign, utm_term, utm_content, tracking parameters, final url suffix, placeholder, UPDATE ME, inherited, account default, campaign override
USE THIS TOOL WHEN THE USER ASKS:
- "What UTMs does campaign X use?" / "Show me the tracking parameters on this campaign"
- "Does this campaign override the account UTM defaults?"
- "Does campaign X still have the UPDATE ME placeholder in its UTMs?"
INHERITANCE RULE - READ BEFORE ANSWERING ANY UTM QUESTION:
UTMs are inherited, never blank. A campaign channel with an empty stored
mapping does NOT have "no UTMs" - it tracks with the account's UTM defaults,
and where the account set nothing it tracks with the Metadata platform default.
Roughly half of all channel rows in production are in that inherited state.
NEVER report "no UTMs configured" from an empty stored field: report the
resolved value and its origin.
ORIGIN IS PER CHANNEL, not per key: a channel with an empty stored mapping
inherits the account default whole, so a channel whose resolved mapping differs
at all from that is stored on the campaign and every one of its values is an
override. The per-key `same_as_default` flag says whether that one key happens
to match the default anyway.
ORIGIN VALUES:
- campaign_override: stored on this campaign channel, differs from what it would inherit.
- account_default: inherited from this account's UTM defaults.
- platform_default: inherited from the Metadata-wide default (account set nothing).
- not_set: the channel really has no UTM mapping (non-sponsored channels only).
HONEST LIMIT: a campaign that stores a mapping identical to the default it
would inherit is reported as inherited. The platform returns resolved values
with no provenance, so that case cannot be distinguished - say so rather than
claiming the campaign has no override.
INPUT: campaign_id - the WIZARD campaign id (the `id` field returned by
list_wizard_campaigns / search_campaigns_by_names). Not an experiment id.
RESPONSE SHAPE:
{
"campaign_id": 173290,
"is_editable": true,
"channels": {
"LINKEDIN": {
"origin": "campaign_override",
"inherited_from": "account_default",
"values": {
"UTM_SOURCE": {"value": "UPDATE ME", "origin": "campaign_override", "same_as_default": false, "placeholder": true},
"UTM_MEDIUM": {"value": "AD_CHANNEL", "origin": "campaign_override", "same_as_default": true, "placeholder": false}
}
}
},
"account_defaults": {"LINKEDIN": {"UTM_SOURCE": "Metadata", ...}, ...},
"platform_default": {"UTM_SOURCE": "Metadata", "UTM_MEDIUM": "AD_CHANNEL", ...},
"notes": ["..."]
}
`placeholder: true` marks a value that still carries the UPDATE ME placeholder -
that is a real tracking defect worth reporting to the user.
Values like AD_CHANNEL / OFFER_TYPE / AD_NAME are dynamic tokens the platform
substitutes at serve time, not literal text.
`platform_default` is a constant mirrored in mcp-server from the platform source;
it is not fetched from an endpoint and covers sponsored channels only.
READ-ONLY. To change a campaign channel's UTMs use set_campaign_utms; the
account defaults are edited in the Metadata UI.| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | Wizard campaign id (the `id` from list_wizard_campaigns). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though annotations declare readOnlyHint=true and destructiveHint=false, the description adds substantial behavioral context: UTM inheritance is never blank, origin is per channel, identical-to-default mappings are honestly reported as inherited, placeholder values indicate a real defect, and platform_default is a mirrored constant rather than a live fetch. No annotation contradiction exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the extra length is justified by the inheritance complexity and the risk of hallucinating 'no UTMs' answers. It is well-structured with clear sections, a response example, and prominent warnings, though the keyword list adds some redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema, the description fully compensates by showing the response shape, defining all origin values, explaining inheritance rules, noting the honest limit, and telling the agent how to edit UTMs elsewhere. An agent has everything necessary to invoke the tool and interpret its result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents campaign_id as the Wizard campaign id with 100% coverage. The description adds meaningful disambiguation beyond the schema by specifying that the id comes from either list_wizard_campaigns or search_campaigns_by_names and is explicitly 'Not an experiment id,' which reduces a likely class of agent mistakes.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read ONE campaign's resolved UTM tracking parameters per channel, each value tagged with where it came from.' This clearly distinguishes the tool from related siblings like set_campaign_utms and search_campaigns_by_utm_value by emphasizing read-only, per-campaign, resolved values with origin provenance.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes explicit 'USE THIS TOOL WHEN THE USER ASKS' examples, such as 'What UTMs does campaign X use?' It also names set_campaign_utms as the correct tool for changing UTMs and clarifies that account defaults are edited in the Metadata UI, giving an agent clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_converted_leads_summaryGet Converted Leads Summary (Smart Leads aggregates)ARead-onlyInspect
Fast aggregate summary of the account's converted leads (Smart Leads) — counts and rates only, no lead rows.
ALSO KNOWN AS: leads summary, lead totals, lead overview, MQL rate, lead-to-MQL conversion, smart leads summary.
KEYWORDS: LEAD COUNT, LEAD TOTALS, HOW MANY LEADS, LEADS SUMMARY, LEAD OVERVIEW, SMART LEADS, CONVERTED LEADS, MQL RATE, LEAD-TO-MQL, MQLS, UNIQUE LEADS, UNIQUE DOMAINS, LEAD CHANNEL MIX, LEADS BY CHANNEL, ENRICHMENT COVERAGE, SYNCED TO MARKETING AUTOMATION, LEAD QUALITY BASELINE, LEAD AUDIT BASELINE, PIPELINE FROM LEADS, TRIGGERED OPPORTUNITIES, INFLUENCED OPPORTUNITIES, LEAD SANITY CHECK
USE FOR: "How many leads do we have?", MQL rate and lead-to-MQL sanity checks, channel mix of leads (Facebook/Instagram/LinkedIn/Google Ads/display), enrichment coverage, leads synced to marketing automation, unique leads vs unique company domains, pipeline tie-back (triggered/influenced opportunities and amounts). ALWAYS call this FIRST in a lead audit to set the baseline before pulling rows with get_converted_leads.
NOT FOR: Inspecting individual leads or job-title/ICP distributions (use get_converted_leads); campaign performance metrics (use experiment_performance_stats).
RETURNED DATA: total | totalFacebook, totalInstagram, totalLinkedin, totalGoogleAds | fullyEnriched, autoEnriched, unenriched | syncedToMa | uniqueLeads, uniqueDomain | mqls, uniqueMqls, mqlRate, uniqueMqlRate | influencedOpps, triggeredOpps, influencedAmount, triggeredAmount.
RULES:
Accepts the same filters as get_converted_leads (no pagination/sort) — scope by campaignName/channels/startDate+endDate to summarize a slice.
mqlRate is a useful lead-quality indicator, but clients define MQL criteria differently and it rarely matches a true MQL — treat it as a secondary signal next to job-title/ICP fit.
uniqueDomain vs total shows lead concentration: many leads from few domains can mean a few companies dominate the results.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | Restrict the summary to specific lead IDs. | |
| No | Filter by lead email (partial match). | ||
| adName | No | Filter by the ad (library) name that captured the leads (partial match). | |
| syncMA | No | true = only leads synced to marketing automation; false = only unsynced. | |
| tagIds | No | Filter by tag IDs on the leads' experiments. | |
| endDate | No | Leads created on/before this date. ISO 8601; date-only is accepted. | |
| keyword | No | Filter by the exact search keyword that captured the leads. | |
| channels | No | Filter by acquisition channel(s). | |
| jobTitle | No | Filter by lead job title (partial match). | |
| lastName | No | Filter by lead last name (partial match). | |
| statuses | No | Lead statuses to include. The platform Leads tab defaults to ACTIVE. Omit to include all. | |
| companies | No | Filter by exact company names. | |
| countries | No | Filter by exact lead country names. | |
| firstName | No | Filter by lead first name (partial match). | |
| offerName | No | Filter by the offer name tied to the leads' experiments. | |
| startDate | No | Leads created on/after this date. ISO 8601; date-only is accepted. | |
| matchTypes | No | Filter by keyword match type (search channels). | |
| modifiedBy | No | Filter by the platform user email who last modified the leads (partial match). | |
| campaignName | No | Filter by campaign name (partial match). | |
| contentTypes | No | Data-completeness filter: only leads that HAVE this content. | |
| qualityTypes | No | Quality-signal filter (opportunities, MQL date/score). | |
| audienceTypes | No | Filter by audience type of the leads' experiments (e.g. FIRMOGRAPHIC_INCLUDE, CONTACT_LIST, BUYER_INTENT, NATIVE_LINKEDIN). | |
| isAutoUpdated | No | true = only auto-enriched leads. | |
| businessEmails | No | Filter by exact business email addresses (OR within the list). | |
| experimentName | No | Filter by experiment name (partial match). | |
| isFullyEnriched | No | true = only fully enriched leads; false = only not fully enriched. | |
| isManuallyUpdate | No | true = only manually enriched/edited leads (platform parameter name is 'isManuallyUpdate'). | |
| customAudienceName | No | Filter by targeted audience name (partial match). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only and non-destructive behavior, but the description adds meaningful context: it returns only aggregates, not lead rows; it lists the exact returned fields; it explains no pagination/sort; and it cautions that mqlRate is not a true MQL. It also adds interpretive guidance on uniqueDomain vs total concentration.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, mostly due to the alias and keyword blocks, but it is well-structured and front-loaded with the core purpose. The USE FOR, NOT FOR, RETURNED DATA, and RULES sections each add distinct value, so the length is justified even if somewhat exhaustive.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the large 28-parameter schema and no output schema, the description compensates well: it lists the returned aggregate fields, describes typical use cases, excludes unrelated use cases, and gives important interpretation caveats. An agent has enough context to call the tool correctly and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the description doesn't need to restate filter parameters. It still adds value by noting that it 'accepts the same filters as get_converted_leads (no pagination/sort)' and by naming the most useful scoping filters (campaignName/channels/startDate+endDate) for summarizing a slice.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fast aggregate summary of the account's converted leads (Smart Leads) — counts and rates only, no lead rows.' This clearly distinguishes the tool from lead-row-retrieval tools like get_converted_leads, so an agent can identify what it does and what it does not return.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE FOR section lists concrete questions the tool answers, NOT FOR names the correct alternatives, and the description explicitly says to 'ALWAYS call this FIRST in a lead audit to set the baseline before pulling rows with get_converted_leads.' This is explicit when/when-not guidance with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_credit_balanceGet AI Credit BalanceARead-onlyInspect
Get the current Metadata AI credit balance for the account this token belongs to.
USAGE INSTRUCTIONS FOR LLM:
Tool calls against this server consume AI credits. When the balance reaches zero
or goes negative, billable tools may refuse with an
OUT OF CREDITS error. This tool is how you check
the balance before that happens, and how you confirm a top-up has landed.
WHEN TO USE THIS TOOL:
- Another tool just failed with OUT OF CREDITS — check here before retrying
- The account owner says they have paid, and you need to know if it landed yet
- The user asks "how many credits do I have?" or "what's my AI balance?"
- Before starting a long batch of tool calls, to confirm there is headroom
IMPORTANT — AFTER A TOP-UP, POLL, DO NOT SPIN:
Payment settles ASYNCHRONOUSLY. A card can be charged successfully and the
balance still read as exhausted for a minute or two while the payment clears.
Poll this tool every 20-30 seconds, not continuously. Resume the work you were
doing only once `is_exhausted` is false.
EXPECTED RESPONSE FORMAT:
{
"account_id": "1234",
"balance_usd": 42.5, // may be NEGATIVE — that is a real state
"updated_at": "2026-08-07T12:00:00",
"is_exhausted": false // true means other tools will refuse
}
On failure returns {"error": "..."} — treat an unreadable balance as unknown,
not as zero, and do not tell the user they are out of credits because of it.| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only, but the description adds substantial behavioral insight: balance can be negative, payment settlement is asynchronous, and an unreadable balance should be treated as unknown rather than zero. It also explains the consequence of exhaustion—billable tools may refuse with OUT OF CREDITS. This far exceeds annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well organized with clear headers, bullet lists, and a response-format block. Every major section earns its place, though some points are slightly redundant—for example, the balance-checking purpose appears both in the opening and again in the usage bullets. Minor repetition prevents a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully compensates by providing the expected response shape, including field-level notes and the fact that balance_usd may be negative. It also covers the failure response and instructs the agent how to interpret errors. For a zero-parameter read-only tool, nothing important is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero parameters and 100% schema description coverage, so the baseline is 4. The description clarifies the implicit account binding ('the account this token belongs to'), which adds useful context even though no explicit parameters exist. No parameter documentation is needed beyond this.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get the current Metadata AI credit balance for the account this token belongs to.' It clearly differentiates this from related siblings like get_credit_transactions and get_payment_status by focusing on the current balance. The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated 'WHEN TO USE THIS TOOL' section lists concrete triggers: after an OUT OF CREDITS failure, to confirm a top-up, when the user asks about balance, and before a long batch of calls. It also gives explicit anti-guidance, telling the agent to poll every 20-30 seconds rather than spin after a top-up. This is exemplary usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_credit_transactionsGet AI Credit TransactionsARead-onlyInspect
Get recent AI credit movements for the account this token belongs to, newest first.
USAGE INSTRUCTIONS FOR LLM:
Use this to explain WHERE credit went, or to show that a purchase was recorded.
Each row is one movement: a negative `amountUsd` is a charge, a positive one is
a top-up or an adjustment. `source` says what kind of usage it was (for example
`direct_mcp` for tool calls made from an external client like this one,
`image_generation`, `opik_ai_chat`, `maxio_topup` for a purchase).
WHEN TO USE THIS TOOL:
- User asks "what have I been charged for?" or "where did my credits go?"
- User disputes a charge and wants the detail behind it
- After a payment, to show the customer the top-up on their history
- To find the `referenceId` of a purchase so you can pass it to
`get_payment_status`
EXPECTED RESPONSE FORMAT:
{
"account_id": "1234",
"transactions": [
{"amountUsd": -0.04, "source": "direct_mcp", "description": "MCP tool: ...",
"referenceId": "...", "createdAt": "...", "markup": "4.000000"}
],
"total_elements": 210, "total_pages": 9, "page": 0
}| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Zero-based page number. Defaults to 0 (most recent). | |
| size | No | Rows per page, 1-100. Defaults to 25. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds substantial behavioral context beyond that: it explains the sign convention (negative for charges, positive for top-ups), what 'source' values mean (e.g., direct_mcp, image_generation, maxio_topup), and provides an expected response format with fields like referenceId and pagination info. This is rich, useful behavioral disclosure that goes far beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, usage instructions, when-to-use, expected response format). It front-loads the core purpose and then provides actionable details. Every sentence earns its place, offering concrete guidance without redundancy. The formatting makes it easy for an agent to parse and apply.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (2 optional params, no output schema), the description is fully sufficient. It provides the expected response format explicitly, including fields and pagination details, which compensates for the lack of an output schema. It also covers the token context and interpretation of results. An agent has everything needed to call this tool correctly and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers both parameters (page and size) with descriptions, and the coverage is 100%. The description itself does not add extra meaning to these parameters beyond what the schema already states, such as default values and ranges. The description does hint at pagination via the response format (total_pages), but that is output behavior, not parameter semantics. Baseline 3 is appropriate given full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific verb and resource: 'Get recent AI credit movements for the account this token belongs to, newest first.' It also explains the meaning of each row (a movement with negative amountUsd being a charge and positive being a top-up), which distinguishes it from sibling tools like get_credit_balance and get_payment_status. The purpose is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly lists 'WHEN TO USE THIS TOOL' with concrete scenarios such as explaining charges, showing top-ups after payment, and finding referenceId for get_payment_status. It also provides 'USAGE INSTRUCTIONS FOR LLM' that clarify how to interpret the data. This leaves no doubt about when to select this tool over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_current_dateGet Current DateARead-onlyInspect
Return the REAL current date and time (UTC).
WARNING: You do NOT inherently know today's date — never guess it or
rely on training-time assumptions. Whenever a task depends on
"today" — setting campaign/budget start & end dates, interpreting
"this month" / "next quarter" / "last 30 days", validating that an
endDate is in the future, or any relative date math — you MUST
anchor to the real current date. If you are not already certain
what today is, CALL THIS TOOL FIRST and use its `current_date`
for all subsequent date calculations.
Takes no parameters.
RETURNS:
{
"current_date": "2026-09-30",
"current_datetime_utc": "2026-09-30T12:00:00.000Z",
"current_year": 2026,
"current_quarter": "Q3",
"timezone": "UTC"
}| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
While annotations already declare readOnlyHint=true and destructiveHint=false, the description adds crucial behavioral context: it warns that the agent does not inherently know today's date and must not guess, which is a key cognitive trap. It also discloses the exact return format including fields like current_date, current_datetime_utc, and timezone, providing transparency beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: it leads with the core purpose, then a critical warning, followed by use cases, a note on parameters, and the return format. Each section serves a distinct purpose without redundancy. It is thorough yet not bloated, with the most important guidance (do not guess dates) prominently placed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with no output schema, the description is exceptionally complete. It covers the purpose, usage triggers, and provides the full return JSON structure, including field names and example values. There is nothing an agent needs to know that is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the description explicitly states 'Takes no parameters.' This eliminates any ambiguity about invocation. Since schema coverage is 100% (trivially) and the description confirms the absence of parameters, it fully clarifies the interface.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Return the REAL current date and time (UTC).' It specifies the exact verb and resource, making it unambiguous. It also distinguishes itself from any potential date-related assumptions by emphasizing the 'REAL' current date, which is unique among the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance, listing concrete scenarios such as 'setting campaign/budget start & end dates,' 'interpreting this month / next quarter / last 30 days,' and 'validating that an endDate is in the future.' It even instructs the agent to 'CALL THIS TOOL FIRST' if unsure, leaving no doubt about when to invoke it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_deep_audience_detailsGet Deep Audience DetailsARead-onlyInspect
Get detailed information about audiences including criteria and advanced configuration.
This tool returns comprehensive audience data beyond the basic summary, including:
- Complete audience criteria and targeting configuration
- Segment information and settings
- Lookback window configuration
- Advanced configuration details and metadata
- Full audience structure and composition
**WHEN TO USE:**
- Retrieve complete audience criteria and configuration
- Analyze detailed targeting setup for an audience
- Export or review full audience specifications
- Understand advanced audience configuration
- Compare detailed configuration across multiple audiences
PARAMETERS:
- audience_ids: Array of audience IDs to retrieve details for (required)
Example: [42828, 42829, 42831]
AUDIENCE ID SOURCES:
Use the get_audience_details tool first to:
- List all available audiences in your account
- Find the IDs of audiences you want detailed information for
- Get the basic summary before requesting deep details
EXAMPLE WORKFLOW:
1. Call get_audience_details() to see all audiences and their IDs
2. Identify which audiences you need deep details for
3. Call get_deep_audience_details(audience_ids=[42828, 42831]) to get full configuration
RETURNS:
Detailed audience information including:
- Audience ID, name, and type
- Complete targeting criteria
- Segment configuration (if applicable)
- Lookback window settings
- Advanced metadata and configuration
- Full audience composition details
IMPORTANT NOTES:
- All provided audience IDs must exist and be valid
- IDs must be positive integers
- You can request details for multiple audiences in a single call
- Results include complete audience configuration data| Name | Required | Description | Default |
|---|---|---|---|
| audience_ids | Yes | Array of audience IDs to retrieve detailed information for. Example: [42828, 42829, 42831] |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context beyond the schema: it returns complete configuration, requires all IDs to exist, IDs must be positive integers, and multiple audiences can be requested in one call. It does not fully disclose potential size limits or error behavior, but the added detail is substantial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headings: WHEN TO USE, PARAMETERS, AUDIENCE ID SOURCES, EXAMPLE WORKFLOW, RETURNS, and IMPORTANT NOTES. It is front-loaded with the core purpose, though the RETURNS section somewhat repeats the earlier bullet list of what the tool returns, adding mild redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool with no output schema, the description is complete. It covers the full workflow from discovering audience IDs to calling the tool, lists return content in detail, documents the valid ID constraint, and notes multi-ID support. An agent has everything needed to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the sole parameter audience_ids already has a clear array description and example. The tool description reinforces this with the same example, explicitly notes that IDs must be positive integers and valid, and clarifies that multiple IDs can be requested at once, adding practical meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get detailed information about audiences including criteria and advanced configuration.' It explicitly differentiates from the basic summary and from sibling get_audience_details by framing this tool as the deep-level counterpart. The bullet list of returned configuration details makes the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE section lists concrete scenarios, and the AUDIENCE ID SOURCES and EXAMPLE WORKFLOW sections tell the agent to call get_audience_details first to obtain IDs. This is explicit guidance on the prerequisite workflow and how this tool relates to an alternative sibling, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_insights_reportGet Insights ReportARead-onlyInspect
Query account journey insights with filtering, sorting, and pagination.
USE FOR: Filtering/searching multiple accounts, bulk analysis, trends, building segments. DO NOT USE FOR: Single account lookup (use get_account_summary_insights).
TO CREATE AUDIENCE: 1) create_segment with criteria, 2) create_audience_from_segment.
CRITERIA BUILDING:
Use search_insights_criteria_fields to discover fields
Build criteria: {"operator": "AND|OR", "match": [{field, operator, type, value}, ...]}
Or use get_segment_criteria to get saved segment's criteria
OPERATORS: EQUALS, NOT_EQUAL, LIKE, NOT_LIKE, IN, NOT_IN, GREATER_THAN, GREATER_OR_EQUAL, LESS_THAN, LESS_OR_EQUAL, IN_THE_LAST, NOT_IN_THE_LAST, BETWEEN, IN_THE_NEXT
BOOLEAN FIELDS: Use without operator: {"field":"IN_CRM","operator":null,"type":"BOOLEAN","value":false}
SORT OPTIONS: timeInJourney, revenue, oppCreatedAmount, highIntentDetails, engagementScoreClassificationDelta, engagementScoreClassification, inCrm, lastTouchDate (default), totalTouches, pageViews, sessions, uniqueVisitors, companyName. Append ,desc or ,asc.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 0-based page number. | |
| sort | No | Sort format: field,direction. Default: lastTouchDate,desc | lastTouchDate,desc |
| endDate | No | ISO 8601 format or null. | |
| criteria | No | Criteria object: {"operator":"AND","match":[{field,operator,type,value}]}. Use get_segment_criteria for saved segments. | |
| startDate | No | ISO 8601 format or null. E.g., '2025-01-01T00:00:00.000Z' | |
| accountName | No | Filter by account/company name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds extensive behavioral context beyond annotations: supported operators, boolean field special-casing, criteria structure, and sort field semantics. This goes well beyond what the annotations convey and tells the agent how the query behaves and how to construct valid requests.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear labeled sections and front-loaded purpose, making it easily scannable. It is longer than minimal, but the extra sections are dense and actionable, covering use cases, exclusions, criteria construction, operators, boolean handling, and sort options without seeming padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with six optional parameters and no output schema, the description is impressively complete: it covers use case selection, alternatives, criteria building, operators, boolean fields, and sort options. The only notable gap is the absence of any description of the response shape or pagination behavior, which would help an agent consume the results, especially since no output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description goes further by explaining how to build the criteria object, listing all operators, giving a boolean field example, and describing the sort format (field,direction) with its default. This adds meaningful semantic depth beyond the raw schema, though some of the content overlaps with the schema's enum and property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Query account journey insights with filtering, sorting, and pagination.' It distinguishes itself from get_account_summary_insights by explicitly stating 'DO NOT USE FOR: Single account lookup' and naming the alternative, so an agent can tell them apart without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' and 'DO NOT USE FOR' sections give explicit positive and negative usage guidance, and directly name the sibling tool for single account lookup. It also provides a concrete multi-step workflow for creating audiences and building criteria, which clarifies exactly when and how this tool fits into a larger task flow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_integrations_statusGet Integrations StatusARead-onlyInspect
Get comprehensive integration connection status for all channels, martech platforms, and CRM systems in the Metadata platform.
USAGE INSTRUCTIONS FOR LLM:
Use this tool to identify which platforms and services are connected or disconnected from the Metadata platform.
This is essential for understanding the current state of integrations and diagnosing connectivity issues.
WHEN TO USE THIS TOOL:
- User asks "which channels are connected?"
- User wants to check "integration status"
- User asks "is [platform name] connected?" (e.g., "is LinkedIn connected?", "is Facebook connected?")
- User wants to know "what martech tools are integrated?"
- User asks about "CRM connection status" or "which CRM is connected?"
- User asks "show me all connected platforms"
- User wants to troubleshoot "why campaigns aren't running" (often related to disconnected channels)
- User needs to "check if [service] needs reconnection"
- User asks about "available ad channels" or "active advertising platforms"
EXPECTED RESPONSE FORMAT:
Returns object with three main sections: channels, martech, apps
Each integration has: connected (bool), enabled (bool), type (string), businessAccountId,
businessAccountName, currency, connectedAt (ISO timestamp), userFullName, errors (array)
CHANNELS: Array of advertising platforms (FACEBOOK, INSTAGRAM, LINKEDIN, GOOGLE_ADS, MICROSOFT_ADS, TWITTER, REDDIT)
MARTECH: Object with crm (array), marketingAutomation (array), googleAnalytics (object)
- CRM types: SALESFORCE, HUBSPOT
- Marketing Automation: HUBSPOT, PARDOT, ELOQUA, MARKETO
APPS: Array of third-party integrations (G2, SLACK with channelName/channelId)
USE CASES:
1. Audit and Compliance:
"Generate a report of all connected marketing platforms for security review"
2. Integration Health Monitoring:
"Check if any integrations need token refresh or reconnection"
3. Capability Discovery:
"What advertising channels can I use based on current connections?"
COMMON SCENARIOS:
Scenario 1 - Check channel: "Is Facebook connected?"
→ Parse response.channels, find type="FACEBOOK", check connected=true
Scenario 2 - List connected channels: "Show me all connected advertising platforms"
→ Parse response.channels, filter where connected=true
Scenario 3 - Disconnected integrations: "What needs reconnection?"
→ Check all sections for connected=false
Scenario 4 - CRM status: "Is Salesforce connected?"
→ Parse response.martech.crm, find type="SALESFORCE", check connected=true
OPTIONAL PARAMETERS: integrationType (CHANNEL/MARTECH/CRM), connectionStatus (CONNECTED/DISCONNECTED), platformName
EXAMPLE: "What's the status of my integrations?" → Present summary of connected/disconnected by category
| Name | Required | Description | Default |
|---|---|---|---|
| platformName | No | Filter by specific platform name (e.g., 'Facebook', 'LinkedIn', 'Salesforce', 'HubSpot') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, indicating a safe read-only operation. The description adds value by detailing the response structure (sections, fields, types) and explaining how to interpret the data (e.g., finding connected channels). This goes beyond annotation basics, though it doesn't mention potential rate limits or authentication requirements, which are not typically shown in metadata.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is quite long and verbose, with extensive sections (use cases, scenarios, expected response formats) that provide significant detail. However, it is well-organized with headers and bullet points, and the essential information is front-loaded. Some redundancy exists (e.g., repeated examples), but overall itearns its length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is exceptionally complete for a tool with one optional parameter and no output schema. It covers the response format in detail, including all sections and fields, provides concrete examples, and explains how to use the data. There is no missing information an agent would need to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has only one parameter (platformName) with a description provided, and schema coverage is 100%. The description adds more context by mentioning optional parameters like integrationType and connectionStatus (though these are not in the schema, possibly indicating a discrepancy), but the core platformName is well-documented. The description enhances understanding of what filtering is possible.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to get comprehensive integration connection status for channels, martech platforms, and CRM systems. It provides a detailed verb-object pair and explains what it returns, distinguishing it from tools like connect_channel or disconnect_channel.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides extensive usage instructions, including specific example queries, when-to-use cases, and a dedicated 'WHEN TO USE THIS TOOL' section with concrete scenarios. It also gives common scenarios and expected response formats, making it extremely clear when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_intent_topicsGet Intent TopicsARead-onlyInspect
Get available intent topics for BOMBOORA audience creation.
IMPORTANT:
Call this tool first before suggesting or creating any Bombora audience.
If the response returns NO topics (empty list), Bombora is NOT available for this account —
do NOT suggest Bombora audiences. Instead, recommend creating a firmographic audience
(create_firmographic_audience) as the preferred alternative.
Retrieves the list of available buyer intent topics that can be used
when creating BOMBOORA intent topic audiences. These intent topics represent different
buyer interest areas and purchasing signals that can be used for precise audience targeting.
WHEN TO USE:
- Always call this BEFORE suggesting or creating a Bombora audience to verify topic availability
- Discover available intent topics before creating a BOMBOORA intent topic audience
- Understand what buyer intent signals are available for targeting
- Build audiences based on specific buyer interests and purchasing signals
- Integrate intent topic selection into the audience creation flow
RETURNS:
List of available intent topics with their details including:
- Topic ID/name
- Topic description
- Available packages or categories
- Any additional metadata for targeting configuration
NEXT STEPS:
After retrieving intent topics, use the intent topic IDs with the audience
creation tool to create BOMBOORA intent topic based audiences.| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false, and the description adds critical behavioral context beyond that: an empty topic list means Bombora is unavailable and should suppress Bombora audience suggestions, and the tool must be called before audience creation. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The critical warning is front-loaded and the sections are clearly labeled, but the description is repetitive: the 'Retrieves' paragraph and several WHEN TO USE bullets restate the opening sentence and the IMPORTANT block. It is well-organized but not as tight as it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with no output schema, the description covers the return shape (topic ID/name, description, packages/categories, metadata), the empty-list edge case, and the next step of using topic IDs in audience creation. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters and schema description coverage is 100%, so there are no parameter semantics for the description to add. The baseline of 4 for a zero-parameter tool applies, and the description appropriately focuses on output semantics instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Get available intent topics for BOMBOORA audience creation') and clearly distinguishes the tool from creation tools like create_bombora_audience and the firmographic alternative. It is immediately obvious what resource is being fetched and why.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs agents to call this tool first before suggesting or creating any Bombora audience, defines the empty-list result as 'Bombora is NOT available for this account,' and names create_firmographic_audience as the preferred alternative. The WHEN TO USE section reinforces this routing with concrete conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_linkedin_engagement_source_typesGet LinkedIn Engagement Source TypesARead-onlyInspect
List the LinkedIn engagement source types and their triggers. STEP 1 of building a LinkedIn Engagement Retargeting audience.
WHAT THIS AUDIENCE TYPE IS:
An audience of people who ALREADY interacted with this advertiser on LinkedIn or on
their website: watched a video ad, opened a lead form, clicked a document ad, visited
the company page, or hit specific URLs. It is warm-traffic retargeting, built from
first-party engagement, and it needs no contact list and no CSV.
NOT THE SAME AS create_retargeting_audience. That tool IMPORTS an audience that
already exists inside the native ad account. This flow BUILDS a new LinkedIn DMP
segment from an engagement rule you define. If the user says "import my existing
LinkedIn audience", use the other tool. If they describe PEOPLE WHO DID SOMETHING
("watched", "clicked", "visited", "opened", "engaged with"), use this flow.
**THE THREE-STEP FLOW:**
1. get_linkedin_engagement_source_types (this tool) — choose a source type + trigger
2. search_linkedin_engagement_sources — choose which campaigns / pages to retarget
(SKIP THIS STEP for the WEBSITE source type, which uses URL rules instead)
3. create_linkedin_engagement_retargeting_audience — build it
SOURCE TYPES AND WHAT EACH RETARGETS (verified live; the response is authoritative
and may differ per account, so never assume a value that is not in it):
- VIDEO_ADS ........... viewers of the account's video ads
- SINGLE_IMAGE_ADS .... people who engaged with single-image ads
- DOCUMENT_ADS ........ people who engaged with or downloaded document ads
- CONVERSATION_ADS .... people who opened or clicked a conversation ad
- LEAD_GEN_FORMS ...... people who opened or submitted a lead gen form
- ORGANIZATION_PAGES .. visitors to the LinkedIn company page
- WEBSITE ............. visitors to specific URLs on the advertiser's own site
TRIGGERS DEFINE INTENT DEPTH, and each source type has its own set:
- VIDEO_ADS: FIRST_QUARTILE (>=25% viewed, the default) · MIDPOINT (>=50%) ·
THIRD_QUARTILE (>=75%) · FULL_COMPLETE (>=97%). Deeper means smaller and warmer.
- SINGLE_IMAGE_ADS / DOCUMENT_ADS: ENGAGEMENT (any interaction, default) ·
CLICK (chargeable clicks only). DOCUMENT_ADS adds DOWNLOAD_CLICK (downloaded it).
- CONVERSATION_ADS: OPEN (default) · ANY_CTA_CLICK (clicked a call-to-action).
- LEAD_GEN_FORMS: VIEW_FORM (opened it, includes submitters, default) ·
LEAD_FORM_SUBMIT (submitted only — the hottest signal available).
- ORGANIZATION_PAGES: VIEW (visited the page, default) · CTA_CLICK (clicked the
page header CTA).
- WEBSITE: VISIT.
CHOOSING FOR THE USER'S INTENT:
- "warm up a broad audience" / top of funnel → a shallow trigger (ENGAGEMENT, VIEW,
FIRST_QUARTILE, VIEW_FORM) and a long lookback.
- "high intent" / "ready to buy" / bottom of funnel → a deep trigger
(LEAD_FORM_SUBMIT, FULL_COMPLETE, DOWNLOAD_CLICK, ANY_CTA_CLICK) and a short one.
- When the user does not say, prefer the trigger marked `default` — it is LinkedIn's
own recommended choice for that source type.
- **Only ever use a trigger from the source type you picked.** The pairing is not
validated anywhere downstream, so a trigger borrowed from another source type
builds a permanently empty audience with no error to warn you.
LOOKBACK WINDOW is both how far back engagement counts AND how long someone stays in
the audience. Longer means bigger and colder; shorter means smaller and warmer.
30 / 60 / 90 / 180 / 365 days, except WEBSITE which LinkedIn caps at 180.
90 is a reasonable default when the user does not say.
WHEN TO USE:
- "Create an engagement retargeting audience"
- "Retarget people who watched my LinkedIn video ads"
- "Build an audience of people who opened / submitted my lead gen form"
- "Retarget visitors to our pricing page" (WEBSITE)
- "Who visited our LinkedIn company page?" (ORGANIZATION_PAGES)
- "Retarget everyone who engaged with our ads last quarter"
- Any request to retarget people by something they DID, on LinkedIn or the site
PARAMETERS: none. It always reports the whole catalog for the caller's account.
RETURNS:
- sourceTypes[]: `engagementSourceType`, a human `description`, and the `triggers`
valid for it (`engagementTrigger`, `description`, `default`). Only entries
LinkedIn reports as ACTIVE are returned; inactive ones are filtered out.
- lookbackWindowDays: the windows the platform accepts, with WEBSITE listed
separately because of its 180-day cap.
- next_step: which tool to call next.
IMPORTANT NOTES:
- Requires a connected LinkedIn channel. With none connected this returns nothing
useful, and the fix is to connect LinkedIn (connect_channel), not to retry.
- The catalog is LinkedIn's own and is read live, so it can change. Treat the
response as the only source of truth and never pass a value absent from it.
- EVENT_PAGES is deliberately not offered. LinkedIn advertises it but returns no
sources for it, so an audience cannot be built from it.
- A source type may come back with `triggersError` instead of `triggers` if its
trigger list could not be read. The other source types are still usable; either
retry or choose one of them.| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnlyHint=true and destructiveHint=false; the description adds substantial context beyond that: the catalog is read live and can change per account, the response is the sole source of truth, EVENT_PAGES is deliberately omitted, triggersError is a possible partial-failure mode, and a connected LinkedIn channel is a prerequisite (with the fix being connect_channel, not retry). This far exceeds what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely structured with headers (WHAT THIS AUDIENCE TYPE IS, SOURCE TYPES, TRIGGERS, CHOOSING, WHEN TO USE, RETURNS, NOTES) and is front-loaded with the purpose. Given there is no output schema, the length is largely justified. Minor redundancy exists — the 'response is authoritative' warning appears twice and the three-step flow is restated in prose — so slightly over-stuffed, but each section adds real value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the full burden of explaining return values, and it does so thoroughly: it documents sourceTypes[] with engagementSourceType/description/triggers, lookbackWindowDays including the WEBSITE 180-day exception, next_step, the triggering defaults per source type, lookback semantics, and the channel prerequisite. An agent has everything needed to call it and correctly chain the flow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters with 100% schema coverage, so the baseline is 4. The description goes further by explicitly stating 'PARAMETERS: none' and explaining the behavioral consequence ('It always reports the whole catalog for the caller's account'), which adds meaning beyond the empty schema — there is no ambiguity about whether a parameter was omitted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('List the LinkedIn engagement source types and their triggers') and immediately frames the tool as 'STEP 1 of building a LinkedIn Engagement Retargeting audience.' It explicitly differentiates from create_retargeting_audience and names its position in a three-tool flow, so an agent can distinguish it from all siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is explicit: it names the alternative (create_retargeting_audience), states the exact user phrasing that should route to the other tool ('import my existing LinkedIn audience') vs. this flow ('watched', 'clicked', 'visited'), and provides a WHEN TO USE list with concrete example requests. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_matched_audiencesGet Matched AudiencesARead-onlyInspect
Get matched audiences (custom audiences) from the Campaign Wizard based on audience type and targeting options.
Retrieves custom audiences that match specific targeting configurations.
Use this to find available audiences for campaign targeting on a given advertising channel.
This is the canonical tool to call when you need an audience id to attach to a campaign or a target group's include[].audiences / exclude.audiences arrays. Each row is a CHANNEL row: its `id` is the row id, and `customAudienceId` (mirrored as `mdAudienceId`) is the Custom Audience id. For a target group copy `mdAudienceId`, `name`, `type`, `matchCount`, `matchCountType` and `inactive` from the row; NEVER put the row `id` into `mdAudienceId` (the platform cannot resolve it and answers 'Targeting group is too small'). Rows with inactive=true have no live segment on the channel and are refused by the platform; pick an active row or wait for matching to finish. It draws on the same source the main UI's target-group audience-chooser uses, so what this tool returns is what the platform considers attachable.
AUDIENCE TARGETING TYPES AVAILABLE:
• FIRMOGRAPHIC_INCLUDE: Firmographic inclusion filters (company size, industry, location)
• FIRMOGRAPHIC_EXCLUDE: Firmographic exclusion filters
• FIRMOGRAPHIC_EXCLUDE_BASIC: Basic firmographic exclusions
• FIRMOGRAPHIC_INCLUDE_SFDC: Salesforce firmographic inclusions
• NATIVE_TARGETING_CSV: CSV-based native targeting
• NATIVE_TARGETING_DYNAMIC: Dynamic native targeting lists
• NATIVE_TARGETING_STATIC: Static native targeting lists
• CONTACT_LIST: Custom contact list targeting
• STORELEADS: Store leads targeting
• DYNAMIC_G2: Dynamic G2 crowd data
• DYNAMIC_G2_CONTACT: Dynamic G2 contact data
• G2_ABM_CONTACT: G2 ABM contact targeting
• LEADSIFT: LeadSift intent data targeting
• BUYER_INTENT: Buyer intent data targeting
• MA_ACCOUNTS_STATIC: Marketing automation static accounts
• MA_ACCOUNTS_DYNAMIC: Marketing automation dynamic accounts
• MA_CONTACTS_STATIC: Marketing automation static contacts
• MA_CONTACTS_DYNAMIC: Marketing automation dynamic contacts
• NATIVE_LINKEDIN: Native LinkedIn targeting options
• LINKEDIN_RETARGETING: LinkedIn retargeting audiences
• SFDC_CONTACTS_DYNAMIC: Salesforce dynamic contacts
• SFDC_CONTACTS_STATIC: Salesforce static contacts
• SFDC_ACCOUNT_DYNAMIC: Salesforce dynamic accounts
• WEBSITE_RETARGETING: Website visitor retargeting
• WEBSITE_ACCOUNT_RETARGETING: Website account-based retargeting
• TECHNOLOGY: Technology stack targeting
• SLINTEL_TECHNOLOGY: Slintel technology targeting
COMMON USE CASES:
- Find all LinkedIn audiences using firmographic targeting
- Get audiences with website retargeting enabled
- List audiences using G2 intent data
- Search for audiences with Salesforce integration
- Identify audiences using specific MA platforms
- Find dynamic vs static audience configurations
- Discover available contact lists and store leads
PARAMETERS:
- type: Array of targeting types to match (defaults to all types if not specified)
- channel: Advertising channel (LINKEDIN, FACEBOOK, GOOGLE_ADS, INSTAGRAM, TWITTER, YOUTUBE, REDDIT, MICROSOFT_ADS)
- page: Page number for pagination (0-indexed)
- sort: Sort field and direction (e.g., 'createdDate,desc', 'name,asc')
- size: Number of results per page (1-200)
RETURNS:
Paginated list of custom audiences matching the specified targeting criteria.
Each audience includes:
- id: Audience ID
- name: Audience name
- matchCount: Number of matches in the audience
- type: Targeting type (e.g., FIRMOGRAPHIC_INCLUDE, MA_CONTACTS_DYNAMIC)
- channel: Channel the audience is for
- createdDate: When the audience was created
- inactive: Whether the audience is active or inactive
- tags: Associated tags| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-indexed) | |
| size | No | Number of results per page | |
| sort | No | Sort field and direction in format 'field,direction'. Common fields: createdDate. Direction: asc or desc. | createdDate,desc |
| type | Yes | Array of audience targeting types to filter by. If omitted, searches all targeting types. | |
| channel | No | The advertising channel to filter campaigns by |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with readOnlyHint=true, the description adds substantial behavioral detail: each row is a CHANNEL row, row id must not be copied into mdAudienceId, inactive=true rows are refused by the platform, and the data comes from the same source as the UI audience chooser. This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is heavily redundant: the full enum list and parameter details duplicate the input schema, and the 'COMMON USE CASES' section adds little. It is organized with headings and front-loaded with the key purpose, but it is far longer than needed and not every section earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Without an output schema, the description compensates by listing returned fields and explaining critical row semantics, inactive handling, and the canonical use case. However, the description's claim that type can be omitted conflicts with the required array in the schema, leaving an inconsistency an agent could trip on.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all parameters. The description mostly duplicates the schema and adds little accurate new parameter meaning. In fact, it says 'type... defaults to all types if not specified' while the schema marks type as required, which is misleading and could cause incorrect calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Get matched audiences... Retrieves custom audiences that match specific targeting configurations') and explicitly declares this is 'the canonical tool to call when you need an audience id to attach to a campaign or a target group's include[].audiences / exclude.audiences arrays.' This clearly distinguishes it from sibling audience-related tools and states its role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use it: to find available audiences for campaign targeting on a given channel and to obtain an audience id for inclusion/exclusion arrays. It does not explicitly name alternatives or say when not to use it, but the 'canonical tool' phrasing and use-case list provide adequate guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_negative_keywords_list_detailsGet Negative Keywords List DetailsARead-onlyInspect
Fetch the keywords inside a single Google Ads negative keyword list.
PURPOSE:
List_negative_keywords_list only returns each list's name + id; it does NOT
expose the individual keywords inside. Use this tool to see what's actually
in a given list (text, match type, resourceName) before deciding to add or
remove entries.
WHEN TO USE:
- Inspect what's already excluded before adding more negatives
- Filter by substring with the 'text' query parameter
- Look up an entry to confirm it exists before calling
remove_keywords_from_negative_list (which matches by text internally)
RESPONSE FORMAT:
Returns the list payload:
{
"id": 43256533,
"name": "Keywords we don't wanna spend money",
"totalKeywords": 87,
"totalPages": 4,
"keywords": [
{
"resourceName": "customers/123/sharedCriteria/456~789",
"text": "free download",
"keywordMatchType": "PHRASE"
},
...
]
}
PARAMETERS:
- listId (integer, required): the id from list_negative_keywords_list.
- text (string, optional): substring filter on keyword text.
- page (integer, optional): 0-based page index. Default 0.
- size (integer, optional): rows per page. Default 25, max 100.
- sort (string, optional): "<field>,<direction>". Default "text,asc".
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
lists, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 0-based page index. Default 0. | |
| size | No | Rows per page. Default 25, max 100. | |
| sort | No | Sort criteria in format '<field>,<direction>'. Default 'text,asc'. | text,asc |
| text | No | Optional substring filter on keyword text. | |
| listId | Yes | ID of the negative keyword list (from list_negative_keywords_list). | |
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds significant behavioral context: the exact response payload, pagination fields, and a warning that GOOGLE_ADS and MICROSOFT_ADS lists are per-channel and separate. It also clarifies that this tool exposes the individual keywords, which the sibling list tool does not. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear one-line summary and organized into PURPOSE, WHEN TO USE, RESPONSE FORMAT, PARAMETERS, and CHANNEL SCOPE sections. It is longer than minimal, but the length is largely justified by the missing output schema and the channel caveat; the PARAMETERS section does duplicate schema descriptions, preventing a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the RESPONSE FORMAT example fills the return-value gap with a concrete JSON structure. Combined with fully described parameters, pagination details, and channel separation warnings, nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 even without parameter details in the description. The PARAMETERS section re-states the same defaults, formats, and meanings already present in the input schema, adding no new semantic value beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names the exact resource ('keywords inside a single Google Ads negative keyword list') with a specific verb ('Fetch'), and the PURPOSE section contrasts it with list_negative_keywords_list, which only returns name+id. An agent can distinguish this tool from siblings immediately without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE section lists concrete use cases (inspect exclusions, substring filter, confirm existence before removal) and names remove_keywords_from_negative_list as the operation that follows. It also adds an explicit channel-scope caution: the two channels hold separate lists and must not be substituted. This is clear when-to-use and when-not-to guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_offerGet OfferARead-onlyInspect
Get offer information by name or list all offers.
USE FOR: "Show me the [offer name] offer", "What's in [offer name]?", "Find offer called [name]", "List all offers"
If name provided: returns detailed offer info (name, description, assets, configuration). If no name: returns list of all available offers.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | The name of the offer to search for. Example: 'AI Marketing Audit Demo'. If omitted, returns a list of all available offers. | |
| offer_id | No | Exact offer id. PREFER THIS over `name` whenever you have an id: a name lookup returns the first search match, so offers sharing a prefix (a template name plus a random suffix, which is how offers get named here) can resolve to the wrong one silently. Takes precedence when both are given. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the description's safety disclosure is redundant. However, it adds significant behavioral context beyond annotations: the silent risk of name lookup resolving to the wrong offer due to prefix matching, the precedence of offer_id, and the exact return content for each mode. This is valuable and not contained in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose, followed by concise usage examples and a clear behavioral breakdown. Every sentence contributes value—no filler or repetition. It is well-structured for quick agent parsing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With two optional parameters, no output schema, and annotations covering safety, the description sufficiently explains both invocation modes and the return contents ('detailed offer info' vs. 'list of all available offers'). It does not detail pagination or error cases, but for a read-only lookup tool this is acceptable and unlikely to confuse an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage for both parameters, including descriptions of behavior and precedence for offer_id. The tool description repeats these points but adds no new parameter-specific meaning beyond what the schema already documents. Thus, it meets the baseline of 3 for high schema coverage, but does not elevate further.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get offer information by name or list all offers.' It clearly distinguishes two modes based on whether a name is provided, and the usage examples make the purpose unambiguous. It is differentiated from sibling tools like create_update_offer (write operation) and find_offer_url (different resource) by the focus on retrieving offer details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'USE FOR' examples and conditional behavior: if name provided vs. if not. It also advises preferring offer_id over name and explains why, which is actionable guidance. It does not explicitly mention alternatives like find_offer_url, but the purpose is distinct enough that the agent can infer when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_payment_statusGet Payment StatusARead-onlyInspect
Check whether a specific credit payment has settled onto the account's ledger.
USAGE INSTRUCTIONS FOR LLM:
A credit purchase is charged immediately but CREDITED asynchronously — the money
settles at the billing provider, whose webhook then reaches Metadata and records
the credit. So "the card was charged" and "the balance is usable" are separate
moments, usually seconds to a couple of minutes apart. This tool tells them
apart for one specific payment.
WHEN TO USE THIS TOOL:
- The account owner has paid and given you a payment/transaction reference
- You want to confirm a specific purchase landed, rather than just seeing that
the balance moved
IF YOU DO NOT HAVE A REFERENCE, USE `get_credit_balance` INSTEAD. That is the
normal way to wait for a top-up — you rarely need the reference.
Poll every 20-30 seconds, not continuously. `status` is "pending" until it
lands and "settled" after.
EXPECTED RESPONSE FORMAT:
{
"reference_id": "maxio:txn:987654",
"status": "settled", // or "pending"
"settled": true,
"amount_usd": 50.0, // null while pending
"settled_at": "2026-08-07T12:01:00",
"balance_usd": 37.5, // the balance right now
"is_exhausted": false // false means you can resume work
}| Name | Required | Description | Default |
|---|---|---|---|
| reference_id | Yes | The payment's reference, as reported when the purchase was made (e.g. 'maxio:txn:987654'). Found on the transaction row in get_credit_transactions. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare read-only and non-destructive behavior, so the description carries the burden of explaining behavior. It clearly describes the asynchronous settlement model, pending vs settled status, recommended polling interval, and expected response format including null fields while pending.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but it is well-structured into clear sections and every section serves a purpose: clarifying the async model, giving usage conditions, routing to an alternative, and providing the response format. It earns its length given the lack of an output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description's expected response format is essential and fully covers return values, status values, nullable fields, and current balance semantics. The tool is simple (one parameter), and the description leaves no operational gap: when to call it, how to call it, what to expect, and how often to poll.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents `reference_id` fully with an example and source location. The description adds further value by framing the reference in context, explaining it comes from a purchase, and showing it in the expected response format. This goes beyond the schema's description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: checking whether a specific credit payment settled onto the account's ledger. It also differentiates this tool from the sibling get_credit_balance by emphasizing a specific payment/reference, making the distinction clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: when the account owner has paid and provided a reference, and when you want to confirm a specific purchase landed. It also explicitly directs the agent to use `get_credit_balance` instead when no reference exists, which is strong alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_retargeting_audiencesGet Retargeting AudiencesARead-onlyInspect
Get all available retargeting audiences for a specific advertising channel.
This tool retrieves all retargeting audiences and native audiences available for the specified
advertising channel (GOOGLE_ADS, LINKEDIN, or FACEBOOK) that can be used to create new retargeting
audiences. This is useful when you need to discover existing audiences before creating or targeting them.
SUPPORTED CHANNELS:
- GOOGLE_ADS: Google Ads retargeting audiences
- LINKEDIN: LinkedIn retargeting audiences
- FACEBOOK: Facebook retargeting audiences
WHEN TO USE:
- Discover all available retargeting audiences for a specific channel
- View native audiences that can be used for targeting on a channel
- Find audience IDs and details for audience creation or targeting
- Review audience names, sizes (matchCount), and other metadata
- Understand what audiences are available before building campaigns
- Compare audiences across different advertising channels
PARAMETERS:
- channel: The advertising channel to fetch retargeting audiences for (required)
Options: GOOGLE_ADS, LINKEDIN, FACEBOOK
Note: Channel names are case-insensitive and will be converted to uppercase
RETURNS:
List of available retargeting and native audiences with details including:
- id: Unique audience ID
- name: Audience name
- type: Audience type (e.g., GoogleAdsAudience, LinkedInAudience, FacebookAudience)
- subtype: Audience subtype (e.g., GOOGLE_ADS_RETARGETING, LINKEDIN_RETARGETING)
- channel: Channel type identifier
- matchCount: Number of matches/members in the audience
- externalAccountId: Associated account ID on the advertising platform
- seedSourcePlatform: Source platform for the audience seed
AUDIENCE DETAILS:
Each audience record provides comprehensive information about:
- Audience identification and naming
- Type and subtype classification
- Match count to understand audience size
- External platform integration details
- Account associations
COMMON USE CASES:
- Get all LinkedIn retargeting audiences (including Marketing Automation, Bulk, Retargeting, and Business Objective Based Audience)
- Find Google Ads audiences suitable for retargeting campaigns
- Identify Facebook retargeting audiences| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | The advertising channel to fetch retargeting audiences for |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the description doesn't need to restate that. It adds valuable behavioral context by detailing the return fields (id, name, type, subtype, channel, matchCount, etc.) and clarifying that it retrieves both retargeting and native audiences. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very verbose, with multiple sections (SUPPORTED CHANNELS, WHEN TO USE, PARAMETERS, RETURNS, AUDIENCE DETAILS, COMMON USE CASES). Some redundancy exists: 'AUDIENCE DETAILS' largely restates the RETURNS list, and 'COMMON USE CASES' overlaps with 'WHEN TO USE'. While well-structured, it could be trimmed significantly without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that there is no output schema, the description fully compensates by detailing the exact return fields and their meanings. It covers every aspect an agent needs: how to call (channel parameter), what it returns, and common use cases. No missing information that would hinder correct usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single 'channel' parameter is fully described in the schema (enum + description), but the tool description adds critical extra semantics: it explains that channel names are case-insensitive and will be converted to uppercase. This goes beyond the schema and provides practical guidance for invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Get all available retargeting audiences for a specific advertising channel.' It specifies the resource (retargeting audiences) and the scope (per channel), distinguishing it from creation tools like create_retargeting_audience or other retrieval tools like get_audience_details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit 'WHEN TO USE' section listing concrete scenarios (discover audiences, view native audiences, find IDs, etc.), which gives strong contextual guidance. However, it does not explicitly mention when not to use it or name alternatives, though the use cases imply this is for read-only discovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_segment_criteriaGet Segment CriteriaARead-onlyInspect
Read one saved Insights segment by id or name: its criteria, status, and how many accounts it matches. Pass lookback_window to count inside the window an audience would use.
RETURNS {found: true, id, name, status, last_updated_date, lookback_window, accounts, criteria}, or {found: false, available_segments: [...]} when nothing matches: pick from that list or create_segment, never invent an id.
STATUS: READY (usable), PENDING (a CRM field is still being extracted: wait and re-check), FAILED.
accounts is the number of companies matching right now (all time when lookback_window is omitted). 0 with the window you plan to use means create_audience_from_segment would build an empty audience: loosen the criteria (a new create_segment) or widen the window first.
Pass the returned criteria object (not the id) to get_insights_report to list the accounts.
| Name | Required | Description | Default |
|---|---|---|---|
| segment_id | No | Segment ID (fastest lookup). | |
| segment_name | No | Segment name (fuzzy matching, case-insensitive). | |
| lookback_window | No | Days to evaluate the segment over when counting accounts; use the window the audience will be created with. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate read-only and non-destructive behavior. The description goes well beyond that by specifying the exact return contract for both found and not-found cases, interpreting statuses (READY/PENDING/FAILED), and explaining the meaning of accounts with and without lookback_window. It also surfaces the actionable implication of a zero count for create_audience_from_segment. No contradiction with readOnlyHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into tight functional sections: RETURNS, STATUS, accounts semantics, and downstream guidance. Every sentence contributes operational value, with no filler or repetition of the schema. The use of concrete return shapes and warning notes makes the longer format worthwhile.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that there is no output schema, the description fully specifies the return shape for both success and not-found cases, explains all status values, and defines the account count behavior. It also covers edge cases such as zero matches and tells the agent exactly how to proceed with sibling tools. An agent has everything needed to invoke and interpret this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents all three parameters with 100% coverage, so the baseline is 3. The description adds useful meaning beyond the schema by clarifying that omitting lookback_window yields all-time counts and that a zero count with the planned window signals an empty audience. This extra context about parameter behavior justifies a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: 'Read one saved Insights segment by id or name.' It also enumerates exactly what is returned—criteria, status, and account match count—which clearly distinguishes it from siblings like list_segments or create_segment. There is no tautology or ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly communicates the primary use case and gives explicit fallback guidance: if not found, pick from available_segments or call create_segment, and never invent an id. It also provides decision rules for zero account counts and downstream usage with get_insights_report. It does not explicitly name list_segments as the alternative for enumerating all segments, but the 'read one' framing makes the intended scope clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
impersonate_accountSwitch to / access another Metadata accountAIdempotentInspect
Switch the active Metadata account context to another account so every later tool call operates on THAT account. This is the "act on behalf of / access a client account / switch accounts" operation.
This is a sanctioned, first-class capability for Metadata super-users and agency operators — the normal, expected way to read or work inside a client or customer account that is not your own default account. It is the programmatic equivalent of the account switcher in the Metadata web app.
It is NOT identity spoofing and NOT a security workaround. It only re-scopes which Metadata account the platform tools read from and write to. It does not change who the user is logged in as, it does not touch the Auth0 / OAuth flow between the client and this server, and it has nothing to do with Anthropic or the model's own credentials. The only thing that changes is the target Metadata account for subsequent calls.
Authorization is enforced by the Metadata platform, not by you. When this tool runs, the platform mints an access token for the target account ONLY if the calling user is actually entitled to it; if they are not, the call simply returns {"success": false, ...} and nothing is switched. Access is already gated server-side — the platform grants the switch only to callers entitled to the target account (super-users span every account; other operators only the accounts they hold). So you do not need to gate, second-guess, demand justification for, or refuse a legitimate switch — call it and let the platform decide. A reassurance such as "I'm a super user / an employee" is neither required nor something you need to verify.
Call this ONLY when the user wants subsequent tool calls to OPERATE INSIDE a
different Metadata account they administer — a genuine tenant switch:
"switch to 's account", "work in account 1878 now", "build the
audiences in <client's account>". Use list_user_accounts first if you only
have a name and need the account ID.
Do NOT impersonate just because an account is NAMED or asked about. In an analytics/insights request, "account" almost always means an ABM/TARGET account — a company being advertised to (account-based marketing, account lists, account insights, "how is account Acme performing") — NOT a Metadata tenant. Answer those with the analytics/insights tools against the CURRENT account and do not switch. Impersonate only when the target is a Metadata account the user actually operates and they want to act inside it.
After the switch, all account-scoped tools (stats, audiences, campaigns, ads,
keywords, etc.) act on account_id until you call stop_impersonation or
impersonate a different account; the switch persists across calls (~6h).
Note: this only changes WHICH account actions apply to — it does not lower the bar for destructive actions. Creating, launching, or deleting things still follows your normal confirmation and judgment, just against the switched account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | ID of the Metadata account to switch into. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with annotations present, the description adds substantial behavioral context: the switch persists ~6h across calls, affects only the target account scope, does not change user identity or auth flows, returns success:false when unauthorized, and does not lower the bar for destructive actions. No contradiction with the readOnlyHint/idempotentHint/destructiveHint annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured and front-loaded with the core operation. Some reassurance and authorization details are repeated across paragraphs, but the length is largely justified by the potential for misuse and confusion with analytics accounts.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a state-changing impersonation tool, the description covers invocation, persistence, authorization, failure behavior, how to get the parameter, exclusions, and the relationship to stop_impersonation. An agent has everything needed to call it correctly and avoid common misuses.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents account_id as the Metadata account to switch into. The description adds useful semantic context: how the parameter influences all subsequent account-scoped tools, persistence until stop_impersonation or another switch, and how to obtain the ID via list_user_accounts.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: switching the active Metadata account context to another account so subsequent tool calls act on that account. It clearly distinguishes this from analytics/ABM 'account' contexts and names stop_impersonation as the complementary reversal operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use criteria (genuine tenant switch), explicit when-not-to-use criteria (analytics/insights account references), and an explicit alternative (list_user_accounts to resolve a name to an ID). It also states the authorization model and that the agent should not gate legitimate switches.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
launch_campaignLaunch CampaignADestructiveInspect
CRITICAL: LAUNCHES REAL MARKETING CAMPAIGNS WITH REAL BUDGET SPEND
KEYWORDS: launch, start, activate, go live, campaign, begin, advertising, spend, marketing
PREREQUISITE: Before running this tool, call get_integrations_status and verify at least one advertising channel is connected (FACEBOOK, INSTAGRAM, LINKEDIN, GOOGLE_ADS). If none are connected, tell the user to connect at least one channel before proceeding and stop.
This tool takes a draft campaign and launches it as a LIVE, ACTIVE marketing campaign.
Once launched, the campaign will immediately start:
- SPENDING REAL MONEY from your marketing budget
- SERVING ADS to real audiences across platforms (LinkedIn, Facebook, Instagram, Google)
- GENERATING ACTUAL IMPRESSIONS, CLICKS, AND CONVERSIONS
- COMPETING in real ad auctions with real bid amounts
CRITICAL SAFETY REQUIREMENTS
This tool will ALWAYS require explicit user confirmation before launching any campaign.
The user must understand they are launching a real campaign with real budget implications.
WHEN TO USE:
- Launch a draft campaign to start real advertising and budget spend
- Activate a campaign after final review, approval, and budget confirmation
- Begin live ad serving across configured channels
- Transition from campaign testing/setup phase to live marketing execution
REQUIRED PARAMETERS:
- campaign_id: The unique identifier of the draft campaign to launch (integer, required)
MANDATORY CONFIRMATION PROCESS:
Before launching any real campaign, this tool MUST:
1. Display the campaign ID and retrieve campaign details if possible
2. Show estimated daily/total budget that will be spent
3. List all channels where ads will go live (LinkedIn, Facebook, Instagram, Google)
4. Warn that this starts REAL BUDGET SPENDING immediately
5. Require explicit "YES, LAUNCH REAL CAMPAIGN" confirmation
6. Confirm the user understands this is not a test or simulation
7. Only proceed after receiving unambiguous user approval
8. Provide immediate launch status and live campaign monitoring URL
CAMPAIGN ID SOURCES:
Campaign IDs can be obtained from:
- search_campaigns_by_names tool (recommended)
- create_campaign tool response (returns campaign_id)
- Campaign management interface URLs
EXAMPLE CONFIRMATION FLOW:
User: launch_campaign(campaign_id=159490)
System Response:
"CRITICAL: REAL CAMPAIGN LAUNCH REQUEST
Campaign ID: 159490
Campaign Name: 'Q1_2026_Multi_Channel_Campaign'
Channels: LinkedIn, Facebook, Instagram, Google Ads
Budget Group: 'BoFu'
Estimated Daily Spend: $500-800
Total Budget Allocation: $15,000
WARNING: This will launch a REAL marketing campaign
- Real money will be spent immediately
- Ads will serve to real audiences
- This is NOT a test or simulation
Type 'YES, LAUNCH REAL CAMPAIGN' to confirm you want to proceed with live campaign launch:"
Only after explicit confirmation will the campaign launch proceed.
RESPONSE FORMAT:
Success Response (launched — ONLY when "waitingAudiencesToLaunch" is false or absent):
{
"success": true,
"campaign_id": 159490,
"status": "LIVE - ACTIVELY SPENDING BUDGET",
"campaign_url": "https://platform.metadata.io/hub/advertise/campaigns/159490",
"launch_timestamp": "2026-01-15T12:00:00Z",
"message": "REAL CAMPAIGN IS NOW LIVE - Budget spending has begun",
"live_channels": ["LinkedIn", "Facebook", "Instagram", "Google Ads"],
"budget_status": "Active - Real spend initiated",
"immediate_actions_required": [
"CRITICAL: MONITOR SPEND IMMEDIATELY - Real money is being spent",
"Check live ad performance in dashboard",
"Set up budget alerts if not already configured",
"Monitor audience engagement in first 2 hours",
"Prepare to pause campaign if performance issues arise"
]
}
DEFERRED LAUNCH — CHECK THIS BEFORE YOU REPORT A LAUNCH:
A 202 does NOT always mean the campaign went live. When the response carries
"waitingAudiencesToLaunch": true (it comes back with "status": "Draft", not
"Launching"), the platform has QUEUED the campaign rather than launched it. It is
NOT live, it is NOT serving ads, and it is NOT spending budget. The response also
carries a "context" block that states this in plain language.
Deferred Response:
{
"id": 159490,
"status": "Draft",
"waitingAudiencesToLaunch": true,
"context": {
"waitingAudiencesToLaunch": true,
"description": "This campaign will be launched only after its audiences
finish uploading and matching on the native channels. That happens
automatically when the match completes, so nothing further is needed
from the user. The campaign is NOT live and is NOT spending budget
yet, and it stays editable until it launches. Some channels can take
up to 72 hours to finish the match flow."
}
}
When you get this response, tell the user plainly:
- The campaign is queued, not live, and no budget is being spent yet.
- It will launch on its own once the audiences finish syncing to the channels.
Nothing more is required from them.
- They can keep editing the campaign until it launches.
- Some channels take up to 72 hours to finish matching, so it may not be today.
NEVER describe this outcome as live, launched, active, or spending. Do not tell the
user to monitor spend, and do not hand them the live-campaign monitoring checklist
from the success case above; none of it applies until the campaign actually launches.
Error Response:
{
"success": false,
"campaign_id": 159490,
"error": "Campaign not found or already launched",
"details": "The specified campaign ID does not exist or is already in active status"
}
User Cancellation Response:
{
"success": false,
"campaign_id": 159490,
"status": "Cancelled",
"message": "Campaign launch cancelled by user. Campaign remains in Draft."
}
BUDGET IMPLICATIONS — REAL MONEY:
Launching a campaign will IMMEDIATELY:
- Deduct REAL DOLLARS from your marketing budget
- Serve ads that cost money per impression/click
- Compete in live ad auctions with actual bid amounts
- Impact budget availability for other campaigns in the same budget group
POST-LAUNCH MONITORING (CRITICAL):
After launch, IMMEDIATE monitoring is required:
- Check spend within the first 30 minutes
- Monitor CPCs, impression delivery, and budget burn rate
- Review audience engagement and conversion tracking
- Be prepared to pause or adjust bids if needed
Anchor all date-related decisions to the REAL current date — call get_current_date if you are not already certain what today is.| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The unique identifier of the draft campaign to launch |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate destructiveHint=true and readOnlyHint=false, consistent with the description's emphasis on real budget spend and irreversible launch. The description goes far beyond annotations by detailing the confirmation flow, the possibility of deferred launch (waitingAudiencesToLaunch), and the exact response formats including success, error, and cancellation. This is exceptionally transparent about side effects and edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely long and contains extensive examples and response JSON blobs. While the content is valuable, it suffers from redundancy and over-verbosity, repeating 'CRITICAL' warnings and budget implications multiple times. The structure is somewhat organized but not front-loaded; the core purpose and usage appear mid-way, and the massive length makes it less scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (mutating, destructive, with real-world consequences), the description is exceptionally complete. It covers prerequisites, confirmation process, expected responses, error handling, deferred launch scenario, and post-launch monitoring. It even instructs to anchor dates with get_current_date. There is no output schema, so the detailed response examples are necessary and well-provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the description reiterates the required campaign_id with a brief explanation, but adds little beyond the schema's own description. The description does not provide additional parameter semantics such as format or constraints beyond what is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('launches') and resource ('draft campaign') with clear distinction: it transitions a draft to live, spending real budget. It is distinct from siblings like 'check_campaign_launch_readiness' and 'manage_campaign', and the description clarifies it is for launching, not creating or managing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides a prerequisite (call get_integrations_status to verify channels), gives a 'WHEN TO USE' list, and mentions alternative sources for campaign IDs. It clearly differentiates from related tools by focusing on the launch action and the required confirmation process.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_budget_groupsList All Budget GroupsARead-onlyInspect
Browse and list all available budget groups in the Metadata platform with customizable sorting.
KEYWORDS: budget, group, list, all, browse, spending, allocation, optimization, overview
**DIFFERENCE FROM get_budget_group:**
- get_budget_group: Searches for ONE specific group BY NAME (requires group name input)
- list_budget_groups: Returns ALL groups at once (supports flexible sorting)
USE THIS TOOL WHEN THE USER ASKS:
- "Show me all budget groups" or "List all budget groups"
- "What budget groups do we have?"
- "Display all available groups"
- "Show groups sorted by [metric]"
- "Which groups have the highest budget?"
- "Show groups by leads generated"
- "List groups sorted by CPL"
- "Order groups by spending"
DO NOT USE if the user:
- Asks for details about a SPECIFIC group by name → use get_budget_group instead
- Wants to find a group by name → use get_budget_group instead
- Says "Find the [specific name] group" → use get_budget_group instead
SORTING OPTIONS:
You can sort by any of these fields (default: totalActiveExperiments descending):
- totalActiveExperiments, monthlyCap, averageDailyBudgetPerExperiment
- spent, totalBudget, endDate, startDate, leads, cpl
SORT ORDER:
- asc: Ascending order (lowest to highest, oldest to newest)
- desc: Descending order (highest to lowest, newest to oldest) [DEFAULT]| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Default: 0 | |
| size | No | Number of results per page. Default: 10 | |
| sort_by | No | Field to sort budget groups by. Default: totalActiveExperiments | |
| sort_order | No | Sort order - 'asc' (ascending) or 'desc' (descending). Default: desc |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful behavior about sorting and returning all groups, but the claim 'Returns ALL groups at once' conflicts with the paginated page/size parameters, and pagination behavior is not disclosed. This is a meaningful transparency gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with clear sections, examples, and exclusions. The front-loaded summary and explicit formatting make it scannable, though the keyword block and repeated examples add some redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, selection criteria, and sorting well, and annotations cover safety. However, the pagination mismatch is unresolved: the text says all groups are returned 'at once' while the schema indicates paged results, and no output/return behavior is described. Since there is no output schema, this leaves an agent uncertain about the actual response shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already documents each parameter. The description adds extra value by enumerating valid sort fields, explaining asc/desc semantics, and stating defaults in user-facing terms, going beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool lists all budget groups with customizable sorting, using a specific verb and resource. It explicitly contrasts itself with get_budget_group, so an agent can immediately distinguish it from the closest sibling tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'USE THIS TOOL WHEN' examples, including natural-language user requests, and a 'DO NOT USE' section that names the alternative tool for specific group lookup. This gives unambiguous guidance for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_experiment_keywordsList Experiment KeywordsARead-onlyInspect
Search and browse keywords running in experiments with simplified response data.
PURPOSE:
Retrieve a paginated list of keywords that are currently running in experiments,
with optional filtering by keyword or experiment name. Returns only essential fields
for quick identification: keyword name, keywordExternalId, wizExperimentId, wizExperimentName, and status.
WHEN TO USE:
- Find keywords running in a specific experiment
- Search for a keyword across all experiments
- Look up keywordExternalId and wizExperimentId before pausing a keyword
- Browse experiment keywords with pagination
- Verify the status of a keyword after calling pause_experiment_keyword
(note: pausing is an async flow, so the status may take some time to update)
RESPONSE FORMAT:
Returns a simplified paginated response:
{
"totalElements": 50,
"totalPages": 5,
"data": [
{
"keyword": "digital marketing",
"keywordExternalId": 12345,
"wizExperimentId": 678,
"wizExperimentName": "Q1 Campaign Test",
"status": "ACTIVE",
"primaryStatus": "NOT_ELIGIBLE",
"primaryStatusReasons": ["CAMPAIGN_PAUSED", "CAMPAIGN_PENDING"]
}
]
}
COMMON USE CASES:
1. Search by experiment name:
list_experiment_keywords(keywordOrExperimentName="Q1 Campaign")
2. Search by keyword:
list_experiment_keywords(keywordOrExperimentName="marketing")
3. Paginate through results:
list_experiment_keywords(keywordOrExperimentName="test", page=0, size=20)
list_experiment_keywords(keywordOrExperimentName="test", page=1, size=20)
PARAMETERS:
- keywordOrExperimentName: Required. Search term to filter by keyword or experiment name.
- page: Page number for pagination (0-based, default: 0)
- size: Number of items per page (default: 10)
TIP: Use this tool first to find the keywordExternalId and wizExperimentId needed
by the pause_experiment_keyword tool.| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Default is 0. | |
| size | No | Number of items per page. Default is 10. | |
| keywordOrExperimentName | Yes | Search term to filter results by keyword name or experiment name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is known. The description adds valuable behavioral context: it details the simplified response fields, pagination structure, and the async nature of status updates after pausing. This goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (PURPOSE, WHEN TO USE, RESPONSE FORMAT, COMMON USE CASES, PARAMETERS, TIP) and front-loaded with the purpose. It is relatively long but each section earns its place with examples and operational guidance. No fluff, though it could be slightly condensed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of an output schema, the description fully compensates by providing the exact response format with example fields. It covers pagination parameters, common use cases with code examples, and even the async status update behavior. An agent has everything needed to call this tool correctly without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so each parameter is already documented in the schema. The description repeats parameter details but adds value through concrete usage examples (e.g., searching by experiment name or keyword, pagination with page and size). These examples clarify semantics but do not add meaning beyond what the schema provides, hence the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Search and browse keywords running in experiments with simplified response data.' It specifies the resource (experiment keywords), the action (search/browse), and the output simplification, distinguishing it from general keyword listing tools. The purpose is unambiguous and specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE' section lists five concrete scenarios, including searching by experiment, looking up IDs before pausing, and verifying status after pause_experiment_keyword. It also provides a tip to use this tool before pausing. However, it does not explicitly mention when not to use it or name alternative sibling tools like list_keywords, though the context strongly implies the differentiator.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_extensionsList Search Ad ExtensionsARead-onlyInspect
List the account's Google Ads / Microsoft Ads library extensions (sitelinks, callouts, snippets, etc.) with their internal ids.
ALSO KNOWN AS: list extensions, show extensions, find sitelink, which extensions do we have, extension library, browse extensions
KEYWORDS: list, show, find, browse, extensions, sitelink, callout, library, google ads, microsoft ads, bing, id
WHEN TO USE:
- "What sitelinks do we have?" / "Show our Google Ads extensions"
- ALWAYS before add_extensions_to_native_campaign or remove_extensions_from_native_campaign — those need internal ids, and this is the only tool that returns them. The create_*_extension tools return an empty body and cannot tell you the new id.
WHEN NOT TO USE:
- Creating a new extension → use the relevant create_*_extension tool
- Non-search channels (Facebook / LinkedIn / Reddit) — extensions do not exist there
INPUTS:
- channel (required): GOOGLE_ADS or MICROSOFT_ADS
- types (optional): filter, e.g. ["SITELINK"]
- name (optional): name filter. Extension names are AUTO-DERIVED, not user-chosen — a sitelink's name is its link text and both description lines joined by newlines, truncated to 50 chars. Filter by `types` and match on the returned fields instead of guessing a name.
- page / size (optional): pagination, defaults 0 / 50
Returns {totalElements, totalPages, data:[{id, name, type, createdDate, ...}]}. Only campaign-attachable extensions are listed (account-level ones are excluded by the platform).| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional name filter. Names are auto-derived by the platform, not user-chosen, so prefer filtering by `types`. | |
| page | No | 0-based page index. Defaults to 0. | |
| size | No | Page size. Defaults to 50. | |
| types | No | Optional extension-type filter, e.g. ["SITELINK"]. | |
| channel | Yes | Search channel. Ad extensions are a search-channel-only concept. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds substantial behavior: it returns only campaign-attachable extensions, excludes account-level ones, explains auto-derived names, and discloses pagination defaults. It also warns that create_*_extension tools return an empty body and cannot supply the new id.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: aliases, keywords, explicit when-to-use, parameter guidance, and return shape. The structure is scannable and front-loaded with the core purpose before details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, but the description supplies the return shape ({totalElements, totalPages, data}) and critical caveats about account-level extensions being excluded. Combined with the parameter guidance and sibling routing, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaningful semantics beyond the schema: it clarifies that names are auto-derived and should not be guessed, recommends filtering by `types`, and documents pagination defaults. This directly prevents a common misuse of the name parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action ('List'), the resource ('Google Ads / Microsoft Ads library extensions'), and the specific deliverable ('internal ids'). It distinguishes itself from the many create_*_extension tools and add_extensions_to_native_campaign / remove_extensions_from_native_campaign siblings by stating this is the only tool that returns ids.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'WHEN TO USE' and 'WHEN NOT TO USE' sections give concrete invocation triggers and exclusions. It names the alternatives (create_*_extension for new extensions) and states that extensions do not exist on non-search channels.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_keywordsList KeywordsARead-onlyInspect
List and search keywords with filtering, sorting, and pagination options.
PURPOSE:
Retrieve a paginated list of keywords from the Metadata platform with advanced
sorting and filtering capabilities. Optionally search by keyword name. Use this tool
to discover, analyze, and export keyword data for campaign planning and optimization.
WHEN TO USE:
- Browse all available keywords in the account
- Search for specific keywords by name
- Find keyword variations and similar terms
- Export keyword data with custom sorting
- Analyze keyword metrics (search volume, bid prices)
- Build keyword lists for campaign creation
- Filter keywords by archived status
- Compare keyword performance metrics
KEY FEATURES:
- NAME SEARCH: Filter by keyword name for targeted searches (optional)
- PAGINATION: Use page and size parameters to navigate large datasets
- SORTING: Sort by search volume, bid prices, name, or modification date
- FILTERING: Include or exclude archived keywords
- PERFORMANCE DATA: Get avgMonthlySearches, lowerPageBid, higherPageBid metrics
NAME SEARCH:
The optional 'name' parameter supports:
1. Single name (string): Searches for one keyword name
- "marketing" → Finds "digital marketing", "email marketing", "marketing automation"
- "seo" → Finds "SEO services", "SEO tools", "SEO analytics"
- "ppc" → Finds "PPC advertising", "PPC campaigns"
2. Multiple names (array of strings): Searches for multiple keywords at once
- ["marketing", "seo", "ppc"] → Aggregates results from all three searches
- Makes separate API requests for each name and combines results
- Automatically deduplicates keywords by ID
- Returns all unique keywords matching any of the provided names
- Omit 'name' parameter to list all keywords without filtering
- Both single and multiple searches support partial matching
PAGINATION STRATEGY:
The API returns paginated results. Use these parameters to navigate:
- page: 0-based page number (default: 0, meaning first page)
- size: Number of results per page (default: 25, recommended: 25-100)
To get the next page of results, increment the 'page' parameter.
Example:
- page=0, size=25 → Returns items 0-24
- page=1, size=25 → Returns items 25-49
- page=2, size=25 → Returns items 50-74
SORT OPTIONS (use format: field,direction):
Available fields for sorting:
- avgMonthlySearches,desc/asc: Sort by average monthly search volume
- lowerPageBid,desc/asc: Sort by lower page bid (CPC floor price)
- higherPageBid,desc/asc: Sort by higher page bid (CPC ceiling price)
- name,desc/asc: Sort by keyword name alphabetically
- modifiedDate,desc/asc: Sort by Modification/Update date (default)
Direction options:
- desc: Descending order (highest to lowest)
- asc: Ascending order (lowest to highest)
SORT EXAMPLES:
- sort="avgMonthlySearches,desc": Keywords with highest search volume first
- sort="avgMonthlySearches,asc": Keywords with lowest search volume first
- sort="lowerPageBid,desc": Keywords with highest CPC floor first
- sort="higherPageBid,asc": Keywords with lowest CPC ceiling first
- sort="name,asc": Keywords in alphabetical order (A-Z)
- sort="name,desc": Keywords in reverse alphabetical order (Z-A)
FILTERING:
- archived: Filter by archived status (true/false, default: false)
Set to true to include archived keywords
Set to false to show only active keywords (recommended)
PAGINATION WORKFLOW:
1. Start with page=0 to get the first set of keywords
2. Check the response metadata to see if more results exist
3. If needed, increment page number and fetch again
4. Continue until all desired results are retrieved
RESPONSE FORMAT:
Returns a paginated response with:
{
"totalElements": 2,
"totalPages": 1,
"data": [
{
"name": "product match",
"avgMonthlySearches": 260,
"competition": "LOW",
"lowerPageBid": 0.00,
"higherPageBid": 0.00,
"id": 18330,
"archived": false,
"createdDate": "2025-09-15T20:35:50.000Z",
"modifiedDate": "2025-09-30T21:14:59.000Z"
},
{
"name": "keyword match",
"avgMonthlySearches": 140,
"competition": "LOW",
"lowerPageBid": 0.00,
"higherPageBid": 0.00,
"id": 18339,
"archived": false,
"createdDate": "2025-09-15T20:35:50.000Z",
"modifiedDate": "2025-09-30T21:14:59.000Z"
}
]
}
COMMON USE CASES:
1. List all active keywords:
list_keywords()
2. Search for "marketing" keywords:
list_keywords(name="marketing")
3. Get top 50 keywords by search volume:
list_keywords(page=0, size=50, sort="avgMonthlySearches,desc")
4. Find expensive keywords (highest CPC) with name search:
list_keywords(name="analytics", sort="higherPageBid,desc")
5. Find affordable keywords (lowest CPC):
list_keywords(sort="lowerPageBid,asc")
6. Get alphabetically sorted active keywords:
list_keywords(page=0, size=100, sort="name,asc", archived=false)
7. Export all keywords (paginate through results):
list_keywords(page=0, size=100)
list_keywords(page=1, size=100)
list_keywords(page=2, size=100)
... (repeat for all pages shown in totalPages)
8. Get recently modified keywords:
list_keywords(page=0, size=25, sort="modifiedDate,desc")
9. Search with pagination:
list_keywords(name="marketing", page=0, size=50)
list_keywords(name="marketing", page=1, size=50)
10. Search for multiple keyword names at once:
list_keywords(name=["marketing", "seo", "ppc"])
11. Search multiple names with sorting:
list_keywords(name=["analytics", "ads"], sort="avgMonthlySearches,desc")
12. Search multiple names and exclude archived:
list_keywords(name=["social", "media"], archived=false)
PARAMETERS:
- name: Optional keyword name or partial name to search for. Can be a string or array of strings.
Supports partial matching. Omit to list all keywords. (optional)
- archived: Filter by archived status (default: false)
- page: Page number for pagination (0-based, default: 0)
- size: Number of items per page (default: 25, max recommended: 100)
- sort: Sort criteria in format: field,direction (default: modifiedDate,desc)
PERFORMANCE TIPS:
- Use size=100 for bulk exports to reduce API calls
- Use page number to efficiently navigate large datasets
- Filter by archived=false to exclude inactive keywords
- Sort by modifiedDate,desc to see recent changes
- Use name parameter for targeted searches to reduce result set
- When searching multiple names, each name triggers a separate API call
Use reasonable list sizes to avoid excessive API calls
EXAMPLES:
- list_keywords() - Get first 25 active keywords
- list_keywords(name="marketing") - Search for marketing keywords
- list_keywords(name=["marketing", "seo"]) - Search multiple keywords
- list_keywords(page=0, size=50, sort="avgMonthlySearches,desc") - Top 50 by search volume
- list_keywords(name="seo", sort="avgMonthlySearches,desc") - SEO keywords by search volume
- list_keywords(name=["ads", "analytics"], sort="higherPageBid,desc") - Multiple names by bid price
- list_keywords(page=1, size=100, archived=false, sort="name,asc") - Page 2 of keywords A-Z
- list_keywords(page=0, size=25, sort="lowerPageBid,desc") - Most expensive keywords| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional keyword name(s) to search for. Can be a single string or array of strings. Supports partial matching. Omit to list all keywords. | |
| page | No | Page number for pagination (0-based indexing). Default is 0 for the first page. | |
| size | No | Number of items per page (default: 25, recommended: 25-100). | |
| sort | No | Sort criteria in format: field,direction. Options: avgMonthlySearches, lowerPageBid, higherPageBid, name, modifiedDate. Direction: desc (descending) or asc (ascending). Default: modifiedDate,desc | modifiedDate,desc |
| archived | No | Filter by archived status. Set to false to show active keywords (default), true to include archived keywords. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even though readOnlyHint=true and destructiveHint=false already cover safety, the description adds important behavioral detail: multiple name searches trigger separate API requests and deduplicate by ID, partial matching is supported, pagination is 0-based, and archived defaults to false. This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long and somewhat repetitive, with overlapping 'COMMON USE CASES', 'EXAMPLES', and 'PARAMETERS' sections. However, it is well-organized with clear headers, front-loaded purpose, and examples that make behavior concrete, so the length is mostly justified for a complex listing tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description compensates by including a full response format example, a pagination workflow, sorting options, filtering semantics, and performance tips. Everything an agent needs to call this tool correctly and interpret its results is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description still adds substantial value: it explains partial matching with concrete examples, describes aggregation and deduplication for array inputs, documents the sort format and available fields, and clarifies default pagination behavior. This is far more than the schema alone provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'List and search keywords with filtering, sorting, and pagination options,' which names a specific verb, resource, and core capabilities. It clearly distinguishes this tool from siblings like list_negative_keywords_list by focusing on the Metadata platform's keyword dataset rather than negative keyword lists.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
A dedicated 'WHEN TO USE' section lists concrete scenarios such as browsing keywords, searching by name, exporting with sorting, and analyzing metrics. However, it does not explicitly name alternative tools or state when NOT to use this tool, so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_linkedin_conversionsList LinkedIn ConversionsARead-onlyInspect
List the LinkedIn conversion actions (Insight Tag conversions) available on the connected LinkedIn ad account, with id, name, type and whether each is enabled.
Use it to pick the ids for update_linkedin_channel_settings.conversion_action_ids
(which conversions a campaign optimizes toward and reports on), and to answer
"which LinkedIn conversions do we track?" or "is the /pricing page conversion set up?".
KEYWORDS: linkedin, conversions, conversion actions, conversion tracking, insight tag,
website visit conversion, lead gen form conversion, url conversion, page visit, pixel
Requires a connected LinkedIn channel (check get_integrations_status). Conversion
actions are created in LinkedIn Campaign Manager, not here: when the one the user
needs (for example a URL rule for /pricing) is missing, say so and point them at
Campaign Manager instead of inventing an id.
RESPONSE: {success, count, conversions:[{id, name, type, enabled, last_received_at}]}
`enabled: false` conversions cannot be attached to a campaign (launch validation
rejects them). `last_received_at` is when LinkedIn last recorded a hit; null means
the conversion has never fired.| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description adds valuable behavioral details: requires a connected LinkedIn channel, notes that conversions are created in Campaign Manager (not here), explains that enabled:false conversions cannot be attached, and clarifies the meaning of last_received_at null. This goes well beyond what annotations alone convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat long but every sentence adds meaningful information, including response format and edge cases. It is front-loaded with the core purpose and then provides necessary context. The inclusion of keywords is a minor addition but not overly wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter read-only list tool, the description is fully complete. It covers prerequisites, use cases, response structure, and critical behavioral constraints. Nothing an agent needs to invoke or interpret this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema already covers everything (100% coverage). Per the rubric, a baseline of 4 applies. The description adds no parameter-specific semantics because none exist, but it does explain the response structure which aids in interpreting the result.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists LinkedIn conversion actions with id, name, type, and enabled status. The verb 'List' and specific resource 'LinkedIn conversion actions' leave no ambiguity, and it is distinct from other list tools by naming its specific domain.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this tool to pick ids for update_linkedin_channel_settings.conversion_action_ids and to answer specific user questions. It also mentions the prerequisite of a connected channel and directs users to check get_integrations_status, providing clear when-to-use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_marketing_automation_listsList Marketing-Automation ListsARead-onlyInspect
List a Marketing-Automation provider's contact library lists — the selectable source for creating a Marketing-Automation-contacts audience.
PREREQUISITE:
• The provider MUST be connected. Only HUBSPOT and MARKETO expose library lists.
WHEN TO USE:
• Before create_marketing_automation_contacts_audience, to find the library_list_id.
• "list my HubSpot lists", "which Marketo lists can I use for an audience".
PARAMETERS:
• provider (required): HUBSPOT or MARKETO.
• list_type (optional): SMART_LIST | STATIC_LIST | ACTIVE_LIST. If omitted, the provider's own list types are queried and merged (HubSpot: STATIC_LIST + ACTIVE_LIST; Marketo: all three).
• name (optional): filter by list name (partial).
RETURNS: { lists: [ { library_list_id, name, status, listType, objectsCount } ] }. Use `library_list_id` for create. For HubSpot a list is usable only when status is DONE; for Marketo when READY.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional list-name filter (partial match). | |
| provider | Yes | The Marketing-Automation provider to list lists for. | |
| list_type | No | Optional list-type filter. If omitted, the provider's own list types are queried and merged (HubSpot: STATIC_LIST + ACTIVE_LIST; Marketo: all three). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds substantial behavioral context beyond that: the default merge behavior when list_type is omitted (HubSpot merges STATIC_LIST + ACTIVE_LIST; Marketo merges all three), the usability gating by status (HubSpot DONE, Marketo READY), and the return shape including library_list_id for downstream use. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized into labeled sections (PREREQUISITE, WHEN TO USE, PARAMETERS, RETURNS) that are each concise and scannable. The core purpose is front-loaded in the first sentence, and every subsequent section adds operational value — no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description fully discloses the return format ({ lists: [ { library_list_id, name, status, listType, objectsCount } ] }) and how to use it ('Use library_list_id for create'). Combined with prerequisites, usage guidance, parameter semantics, and provider-specific status rules, nothing an agent needs to correctly invoke and apply the result is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters including the enum values and the merge semantics for list_type. The PARAMETERS section in the description restates this information without adding meaning beyond the schema, so the baseline 3 applies — it does not compensate or extend, but it also loses no information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — 'List a Marketing-Automation provider's contact library lists' — and anchors it to the workflow purpose: 'the selectable source for creating a Marketing-Automation-contacts audience.' The WHEN TO USE section names the downstream sibling (create_marketing_automation_contacts_audience) and provides concrete example utterances, making differentiation from the many audit/list tools unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use it ('Before create_marketing_automation_contacts_audience, to find the library_list_id'), gives natural-language triggers ('list my HubSpot lists'), and states the prerequisite that the provider MUST be connected, warning that only HUBSPOT and MARKETO expose library lists. This tells an agent both when to invoke it and when it will fail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_negative_keywords_listList Negative Keywords ListsARead-onlyInspect
List and search negative keywords lists by name filter.
PURPOSE:
Retrieve a list of negative keywords lists from the Metadata platform with optional name filtering.
Use this tool to discover and search for specific negative keywords lists for campaign management and optimization.
ACCOUNT LIMIT:
WARNING: MAXIMUM 20 NEGATIVE KEYWORDS LISTS PER ACCOUNT
Each account can have a maximum of 20 negative keyword lists. Use this tool to check your current list count
and manage your existing lists. If you need to create a new list but have reached the limit, you'll need to
delete or archive existing lists first.
WHEN TO USE:
- Browse all available negative keywords lists in the account
- Search for specific negative keywords lists by name
- Find negative keywords lists by partial name matching
- Get all negative keywords lists data
- Discover available negative keywords lists for campaign use
- Check current list count to manage the 20-list limit
KEY FEATURES:
- NAME SEARCH: Filter by negative keywords list name for targeted searches (optional)
- MULTIPLE SEARCH: Search for multiple list names at once with automatic deduplication
- SIMPLE INTERFACE: Only name-based filtering, no pagination or sorting needed
- LIST COUNTING: Use to verify your current count against the 20-list maximum
NAME SEARCH:
The optional 'name' parameter supports:
1. Single name (string): Searches for one negative keywords list name
- "branded" → Finds negative keywords list named "Branded"
- "competitor" → Finds negative keywords list named "Competitor"
- "generic" → Finds negative keywords list named "Generic"
2. Multiple names (array of strings): Searches for multiple negative keywords lists at once
- ["branded", "competitor", "generic"] → Aggregates results from all three searches
- Makes separate API requests for each name and combines results
- Automatically deduplicates lists by ID
- Returns all unique negative keywords lists matching any of the provided names
- Omit 'name' parameter to list all negative keywords lists without filtering
- Both single and multiple searches support partial matching
RESPONSE FORMAT:
Returns a response with:
{
"data": [
{
"name": "BRanded",
"id": 123
},
{
"name": "Competitor",
"id": 124
}
]
}
COMMON USE CASES:
1. List all negative keywords lists:
list_negative_keywords_list()
2. Search for "branded" negative keywords list:
list_negative_keywords_list(name="branded")
3. Find specific negative keywords list:
list_negative_keywords_list(name="BRanded")
4. Search for multiple negative keywords list names at once:
list_negative_keywords_list(name=["branded", "competitor", "generic"])
5. Search multiple negative keywords list names:
list_negative_keywords_list(name=["competitor", "generic"])
PARAMETERS:
- name: Optional negative keywords list name or partial name to search for. Can be a string or array of strings.
Supports partial matching. Omit to list all negative keywords lists. (optional)
PERFORMANCE TIPS:
- Use name parameter for targeted searches to reduce result set
- When searching multiple names, each name triggers a separate API request
Use reasonable list sizes to avoid excessive API calls
- Results are automatically deduplicated when searching multiple names
EXAMPLES:
- list_negative_keywords_list() - Get all negative keywords lists
- list_negative_keywords_list(name="branded") - Search for branded negative keywords list
- list_negative_keywords_list(name=["branded", "competitor"]) - Search multiple negative keywords lists
- list_negative_keywords_list(name="competitor") - Find competitor negative keywords list
- list_negative_keywords_list(name=["branded", "generic"]) - Multiple list names search
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
lists, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional negative keywords list name(s) to search for. Can be a single string or array of strings. Supports partial matching. Omit to list all negative keywords lists. | |
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds valuable context: the 20-list per-account limit, that multiple names trigger separate API requests, automatic deduplication, and the per-channel separation of lists. These are meaningful behavioral details beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is excessively long and repetitive. It repeats examples multiple times (e.g., list_negative_keywords_list(name="branded") appears in COMMON USE CASES, EXAMPLES, and NAME SEARCH). The sections overlap (PURPOSE, WHEN TO USE, KEY FEATURES all say similar things). It is not front-loaded; the critical channel warning is buried at the end. A more concise version would be far more effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the verbosity, it covers everything an agent needs: parameter semantics, response format with a JSON example, common use cases, performance tips, and channel scope. There is no output schema, but the response example fills that gap. The description is complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for both parameters, so baseline is 3. The description adds substantial extra value: it explains the array behavior (separate requests, deduplication), gives concrete examples of single vs. multiple name searches, and emphasizes the channel parameter's per-channel separation with an explicit warning. This goes beyond schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists and searches negative keywords lists by name filter. It explicitly distinguishes itself from sibling tools like get_negative_keywords_list_details, create_negative_keywords_list, and delete_negative_keyword_lists. The purpose is unambiguous and specific to the resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use scenarios (browse all lists, search by name, partial matching, count check) and notes the channel scope with a warning not to substitute channels. It also implies when not to use it (e.g., for details, use get_negative_keywords_list_details). This is highly actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_salesforce_mixed_criteriaList Salesforce Mixed-CriteriaARead-onlyInspect
List the account's saved Salesforce "mixed criteria" (contact-list criteria) — the selectable source for creating a Salesforce-contacts audience.
PREREQUISITE:
• Salesforce integration MUST be connected. If it is not, tell the user to connect Salesforce first (connect_crm with crm="salesforce").
WHEN TO USE:
• Before create_salesforce_contacts_audience, to find the criteria_id.
• "list my Salesforce contact criteria", "which Salesforce lists can I use for an audience".
PARAMETERS:
• qualified (optional): when true, keep only criteria whose generated filter matches qualified-signal fields.
RETURNS: a list of { id, name, description }. Use `id` as the criteria_id for create_salesforce_contacts_audience. Note: this does NOT include a contacts count.| Name | Required | Description | Default |
|---|---|---|---|
| qualified | No | When true, keep only criteria whose generated filter matches qualified-signal fields. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses the return format (list of { id, name, description }) and explicitly notes that it does NOT include a contacts count. It also mentions the prerequisite of a connected Salesforce integration, adding behavioral context not captured by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (PREREQUISITE, WHEN TO USE, PARAMETERS, RETURNS) and is front-loaded with the core purpose. Every sentence contributes value, and there is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one optional parameter, the description covers all necessary context: prerequisite, usage guidance, parameter meaning, return format, and a notable absence (no contacts count). Since there is no output schema, the description fully explains what the agent can expect, making it complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter 'qualified' is already fully described in the input schema with identical wording. The description's PARAMETERS section repeats this but adds no new meaning or usage nuance beyond the schema. With 100% schema coverage, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'List' and the resource 'the account's saved Salesforce mixed criteria', and explains its purpose as the selectable source for creating a Salesforce-contacts audience. This differentiates it from sibling tools like create_salesforce_contacts_audience, which creates an audience rather than listing criteria.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly specifies when to use the tool: before create_salesforce_contacts_audience to find the criteria_id, and provides example user queries. It also states a prerequisite (Salesforce integration must be connected) and instructs the agent to guide the user to connect via connect_crm if not, leaving no ambiguity about the correct usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_search_termsList Search TermsARead-onlyInspect
Review the Google Ads search terms report with filtering, sorting, and pagination.
PURPOSE:
List the actual search queries that triggered the account's Google Ads, so you can
review wasteful or off-target terms and decide which ones to add to a negative
keywords list. Mirrors the "Search Terms" library page in the Metadata UI.
WHEN TO USE:
- Investigate which queries are costing money without producing clicks or conversions
- Find queries to add to a negative keywords list (pair with add_keywords_to_negative_lists)
- Inspect search terms tied to a specific experiment or matched keyword
- Sort by cost / clicks / conversions to surface the worst offenders
FILTERS (all optional):
- searchTerm: substring match on the search term text
- experiment: experiment name substring match
- keyword: matched keyword substring
- matchType: array subset of [PHRASE, BROAD, EXACT, NEAR_EXACT, NEAR_PHRASE]
- startDate / endDate: ISO-8601 timestamps (e.g. 2026-06-01T00:00:00.000Z).
The UI defaults to the last 30 days when both are omitted.
PAGINATION & SORT:
- page: 0-based (default 0)
- size: rows per page (default 12, max 100)
- sort: "<field>,<direction>". Sortable fields include searchTerm, matchType,
experiment, addedExcluded, keyword, impressions, clicks, ctr, averageCpc,
spent, conversions, costPerConversion. Direction is asc or desc.
Default: "clicks,desc".
RESPONSE FORMAT:
Returns a paginated response:
{
"totalElements": 123,
"totalPages": 5,
"data": [
{
"id": "bGVhZCBnZW5lcmF0aW9uIGNhbmFkYQ",
"searchTerm": "lead generation canada",
"experiment": "MD_Experiment",
"experimentId": "179908",
"matchType": "PHRASE",
"keyword": "lead generation",
"addedExcluded": "Added",
"impressions": 200,
"clicks": 11,
"ctr": 5.5,
"averageCpc": 2.3,
"spent": 25.30,
"conversions": 0,
"costPerConversion": null
},
...
]
}
COMMON USE CASES:
1. Top spenders with zero conversions in the last 30 days:
list_search_terms(sort="spent,desc")
then filter the response client-side for conversions == 0.
2. Worst CTR among phrase matches:
list_search_terms(matchType=["PHRASE"], sort="ctr,asc")
3. Search terms tied to a specific experiment:
list_search_terms(experiment="Q2 Brand Test")
4. Date-bounded review:
list_search_terms(
startDate="2026-05-01T00:00:00.000Z",
endDate="2026-05-31T23:59:59.999Z",
sort="spent,desc"
)
PARAMETERS:
- searchTerm (string, optional): substring filter on the search term text.
- experiment (string, optional): experiment name substring filter.
- keyword (string, optional): matched keyword substring filter.
- matchType (array of strings, optional): subset of
[PHRASE, BROAD, EXACT, NEAR_EXACT, NEAR_PHRASE].
- startDate (string, optional): ISO-8601 timestamp lower bound.
- endDate (string, optional): ISO-8601 timestamp upper bound.
- page (integer, optional): 0-based page index (default 0).
- size (integer, optional): rows per page (default 12).
- sort (string, optional): "<field>,<direction>" (default "clicks,desc").
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
reports, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| page | No | 0-based page index. Default 0. | |
| size | No | Rows per page. Default 12 (kept small to limit chat-context tokens), max 100. | |
| sort | No | Sort criteria in format '<field>,<direction>'. Default 'clicks,desc'. Sortable fields: searchTerm, matchType, experiment, addedExcluded, keyword, impressions, clicks, ctr, averageCpc, spent, conversions, costPerConversion. | clicks,desc |
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
| endDate | No | Optional ISO-8601 timestamp upper bound (e.g. 2026-06-30T23:59:59.999Z). | |
| keyword | No | Optional matched-keyword substring filter. | |
| matchType | No | Optional subset of match types to include. | |
| startDate | No | Optional ISO-8601 timestamp lower bound (e.g. 2026-06-01T00:00:00.000Z). | |
| experiment | No | Optional experiment name substring filter. | |
| searchTerm | No | Optional substring filter on the search term text. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds substantial behavioral context: default 30-day date window, page/size/sort defaults, a detailed response format with field examples and null handling, and a strong warning that GOOGLE_ADS and MICROSOFT_ADS channels are separate and must not be substituted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded with purpose, and the use cases and response example are valuable. However, it is long and repetitive: FILTERS/PAGINATION and CHANNEL SCOPE largely restate the schema, and the full PARAMETERS section duplicates the input schema almost verbatim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the RESPONSE FORMAT section provides the needed return-shape context, and the description fully covers defaults, filters, sorting, date formats, channel scope, and practical usage via worked examples. Nothing an agent needs to correctly select and invoke this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining the implicit date-window default, the token-saving rationale for size=12, the channel separation warning, and worked sort examples. Much of the PARAMETERS section duplicates the schema, but the extra behavioral context justifies a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: it lists/reviews the Google Ads search terms report, showing actual queries that triggered ads and supporting negative-keyword decisions. It also anchors the tool as mirroring the 'Search Terms' library page, making it clearly distinguishable from broader keyword or reporting tools in the sibling set.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit 'WHEN TO USE' section with concrete scenarios, including pairing with add_keywords_to_negative_lists and sorting to surface wasteful terms. It lacks explicit 'when not to use' guidance or named alternatives for keyword-level reporting, so it falls just short of full routing clarity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_segmentsList SegmentsARead-onlyInspect
List the account's saved Insights (Spotlight) account-journey segments: {id, name, status, last_update_date}.
Segments are shared with the SaaS UI (Spotlight > Journey), so a marketer may already have the one you need: check here BEFORE create_segment and reuse instead of creating a near duplicate.
name filters fuzzily (case-insensitive contains or a close match). An empty list means the account has no segments yet, not an error: create one with create_segment when the ask needs it. Creating needs an ACTIVE Insights (Spotlight) subscription on the account: create_segment checks it first and refuses with the subscription state when it is expired or missing. Relay that to the user instead of retrying; existing segments stay usable either way.
STATUS: READY can be used; PENDING is still extracting a CRM field (re-check later); FAILED cannot back an audience.
NEXT: get_segment_criteria(segment_id, lookback_window) to read a segment's filter and how many accounts it matches in a window; create_audience_from_segment to turn it into an audience; get_insights_report(criteria=...) to browse its accounts.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional fuzzy search by name. | |
| sort | No | Sort format: field,direction. Default: name,asc | name,asc |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark readOnlyHint=true and destructiveHint=false, but the description goes well beyond them by disclosing empty-list semantics ('not an error'), the meaning of PENDING/FAILED/READY statuses, that segments are shared with the SaaS UI, and that existing segments remain usable regardless of subscription state. This gives the agent accurate expectations about behavior and non-error outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, then flows naturally into usage, parameter semantics, status meanings, and next-step tool references. It is dense but every sentence earns its place; the STATUS and NEXT sections are clearly delineated, making the text scannable and efficient for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though there is no output schema, the description enumerates the return shape ({id, name, status, last_update_date}) and interprets all status values. It also covers the empty-result case, the fuzzy filter behavior, and the correct downstream calls, so an agent has everything needed to invoke the tool correctly and act on the results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for both optional parameters, so the baseline is 3. The description adds meaningful specificity for the name parameter by defining fuzzy as 'case-insensitive contains or a close match', which goes beyond the schema's terse 'Optional fuzzy search by name'. The sort parameter is already fully described by the schema, so no further description is needed there.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb plus resource: 'List the account's saved Insights (Spotlight) account-journey segments' and enumerates the exact fields returned. It also positions the tool against siblings by explicitly naming create_segment and the downstream NEXT tools, so an agent can distinguish it without opening other definitions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'check here BEFORE create_segment and reuse instead of creating a near duplicate', and explains that an empty result means no segments exist, prompting creation via create_segment when needed. It also lays out the subscribe-state precondition for creating segments and recommends relaying refusal to the user, making the decision boundary between list_segments and create_segment unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_target_groupsList Target GroupsARead-onlyInspect
List and search target groups in Metadata platform.
USE FOR: "list all target groups", "show available target groups", "search target groups with name X", "find target groups containing 'engineer'", "get target group IDs by name", "what target groups do I have?"
WORKFLOW: list_target_groups(name="X") → get ID → retrieve_target_group_by_id(target_group_id=ID) for full details.
RESPONSE: Paginated {content: [{id, name, channel, audienceSize, createdDate, modifiedDate, status}], totalElements, totalPages}
SEARCH: Partial matching, case-insensitive. name="engineer" matches "Engineers EMEA", "Senior Engineers", etc.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional name filter for searching target groups (partial matching, case-insensitive). Example: 'engineer' matches 'Engineers EMEA', 'Senior Engineers', etc. | |
| sort | No | Sort criteria. Options: 'createdDate,desc' (newest first), 'createdDate,asc' (oldest first), 'name,asc' (A-Z), 'name,desc' (Z-A). Default: 'createdDate,desc' | createdDate,desc |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: paginated response shape, partial case-insensitive matching, and the fact that the name filter is optional. It doesn't disclose rate limits or auth requirements, but for a read-only list tool the added context is solid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (USE FOR, WORKFLOW, RESPONSE, SEARCH) and every sentence adds value. It front-loads the core purpose and then provides actionable details without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list/search tool with 2 optional parameters, 100% schema coverage, and readOnlyHint=true, the description covers everything an agent needs: what it does, when to use it, how search behaves, and what the response looks like. The workflow reference to retrieve_target_group_by_id completes the context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters thoroughly, including the name filter's partial matching behavior and sort options. The description reinforces the search semantics and response shape but doesn't add meaning beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List and search') and resource ('target groups in Metadata platform'), and the USE FOR section enumerates concrete natural-language queries that map to this tool. It is clearly distinguishable from siblings like retrieve_target_group_by_id and create_target_group.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit WORKFLOW showing when to use this tool first (list/search to get an ID) and when to switch to retrieve_target_group_by_id for full details. It also gives search behavior (partial, case-insensitive) and example queries, which is strong usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_user_accountsList User AccountsARead-onlyInspect
List accounts the current user has access to, with optional name filtering.
USE FOR: "which accounts do I have access to?", "show me my accounts", "what accounts can I manage?", "what is my account ID?", "which account am I logged into?", "what role do I have?", "show me account named X", "do you have an account called X?"
AUTH METHODS: JWT tokens (OAuth) | PAT tokens (prefix "pat-")
ARGS:
- name (optional for regular users, REQUIRED for super users unless `account_id` is given): partial account name to search for. Super users span the whole platform and would otherwise return an unbounded list, so a search term is mandatory for them. If a super user calls this with neither `name` nor `account_id`, the tool returns an error asking for one — re-call with the user's intended search term.
- account_id (optional): exact account id to look up. Use this instead of `name` when the search term is a number ("account 4368", "switch to 12057"), since account names are not ids and a numeric name search finds nothing. It satisfies the super-user search requirement on its own; supplying both narrows to accounts matching BOTH.
RESPONSE FORMAT (identical for JWT and PAT — the token format does not change the result):
Regular users: user_id, email, default_account_id, is_super_user, token_type, accounts[{account_id, name, role}]
Super users with neither argument: error response — supply `name` or `account_id` and retry.
Super users with name: matching accounts platform-wide (paged at 20).
Super users with account_id: the single matching account, or an empty list when no account carries that id.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Partial account name to search for. Optional for regular users (acts as a filter); required for super users unless `account_id` is given (acts as the search query against the whole platform). | |
| account_id | No | Exact account id to look up. Use instead of `name` when the search term is numeric; it satisfies the super-user search requirement on its own. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description documents auth token types, the super-user mandatory search-term rule, the exact error path when neither name nor account_id is supplied, response shape variants, and 20-item paging. This is extensive behavioral disclosure that an agent cannot get from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured into USE FOR, AUTH METHODS, ARGS, and RESPONSE FORMAT sections with a front-loaded one-sentence summary. Despite its length, every block conveys non-obvious information and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Because there is no output schema, the description supplies the full response object shapes for regular users, super-user errors, name searches, and account_id searches, along with auth and argument requirements. Nothing an agent needs to decide when or how to call the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already documents both parameters well, the description adds material meaning: why the super-user search is required, why numeric name searches fail, that supplying both parameters narrows with AND semantics, and the re-call-on-error behavior. These details significantly improve correct invocation beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names the specific operation (list) and resource (accounts the current user has access to), plus optional name filtering. The USE FOR examples also pin down account ID, role, and login-state queries, making the tool's purpose unmistakable and distinct from detail-fetch or impersonation siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE FOR block provides explicit natural-language triggers such as 'which accounts do I have access to?' and 'what is my account ID?', which makes when-to-use very clear. However, it does not name alternatives or exclusions, such as using get_account_details for a single account's full details, so it stops short of full when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_wizard_campaignsList Wizard CampaignsARead-onlyInspect
List wizard (Metadata-native) campaigns for the current account with pagination, sorting, and experiment-status filtering.
KEYWORDS: campaigns, list, browse, wizard, native, all campaigns, campaign list, launched campaigns, paused campaigns, active campaigns
USE THIS TOOL WHEN THE USER ASKS:
- "Show me all campaigns" / "List campaigns" / "What campaigns do we have?"
- "Show active campaigns" / "List paused campaigns" / "Show completed campaigns"
- "Show recent campaigns" / "Last N campaigns"
- "Campaigns sorted by spend / leads / CPL / created date"
- Page-by-page campaign browsing for the campaigns UI
DO NOT USE if the user:
- Wants details on ONE SPECIFIC campaign by name → use search_campaigns_by_names
- Wants budget group info (not campaigns) → use list_budget_groups / get_budget_group
- Wants per-experiment performance → use experiment_performance_stats / search_experiments
TWO INDEPENDENT FILTERS (COMBINE TO MATCH UI TABS):
1) status — filters by CAMPAIGN status. Accepts a comma-separated subset of: Draft, Launched, Finished.
- Draft: the campaign exists but has never been launched.
- Launched: the campaign has been launched (experiments may be Active, Paused, or idle).
- Finished: the campaign has reached its end date.
- Omit to include all three.
2) experiment_statuses — filters by EXPERIMENT status inside each campaign. Accepts a comma-separated subset of:
Active, WithoutSpend, Paused, Completed, Failed. Omit to include all five.
HOW TO MIX THEM (mirrors the UI tabs on /campaigns):
- "All" tab: omit both → API returns everything.
- "Active" tab: status="Launched", experiment_statuses="Active,WithoutSpend" (launched campaigns with live or not-yet-spending experiments).
- "Paused" tab: status="Launched", experiment_statuses="Paused" (launched campaigns whose experiments are paused).
- "Draft" tab: status="Draft" (campaign hasn't been launched yet — experiment status doesn't apply).
- "Finished" tab: status="Finished".
SORTING:
- sort_by: createdDate (default), startDate, endDate, name, budget, spent, leads, cpl, cpc, ctr, impressions, clicks, status
- sort_order: asc | desc (default: desc)
PAGINATION:
- page: 0-based page index (default 0)
- size: results per page (default 25; the UI campaign list fetches 25–50)
RESPONSE SHAPE:
{
"totalElements": 435,
"totalPages": 18,
"data": [
{
"id": 173290,
"accountId": 1455,
"name": "2026_Q2_NA_Builder_Content_...",
"createdDate": "2026-01-15T12:00:00Z",
"visibility": "VISIBLE" | "ARCHIVED",
"budget": 25,
"startDate": "...",
"endDate": "...",
"status": "Launched" | "Draft" | ...,
"activeExperiments": 9, "pausedExperiments": 0, "totalExperiments": 9,
"leads": 0, "spent": 0, "impressions": 48, "clicks": 0,
"cpc": 0, "cpl": 0, "ctr": 0.0,
"goal": "CTR" | "CPL",
"campaignGroup": "TOF - AO - Social - Billing - BA",
"tags": [...]
}, ...
]
}
WORKFLOW (UI-style): list_wizard_campaigns(page=0, size=25) → render list → user clicks campaign → search_campaigns_by_names / get_campaign_by_wizard_id for details.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional: server-side name substring filter. | |
| page | No | 0-based page index. Default: 0 | |
| size | No | Results per page. Default: 25 | |
| status | No | Campaign-level status filter. Comma-separated subset of Draft, Launched, Finished. Omit to include all three. Combine with experiment_statuses to mirror the UI tabs (e.g. Active tab = status=Launched + experiment_statuses=Active,WithoutSpend). | |
| sort_by | No | Field to sort by. Default: createdDate | |
| sort_order | No | Sort order. Default: desc | |
| visibility | No | Optional: filter by campaign visibility. Omit to include all. | |
| experiment_statuses | No | Experiment-level status filter. Comma-separated subset of Active, WithoutSpend, Paused, Completed, Failed. Omit to include all five. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and non-destructive; the description adds rich context beyond that: the semantic meaning of each status value (Draft = never launched, Launched = launched, Finished = end date), the independence of the two filters, pagination defaults (0-based page, size 25), and a full response-shape example. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is tightly structured with clear headers (KEYWORDS, USE WHEN, DO NOT USE, filters, SORTING, PAGINATION, RESPONSE SHAPE, WORKFLOW) and scannable bullets. Minor redundancy exists—the KEYWORDS section largely restates the intent examples—but overall each section earns its place given the tool has 8 parameters and no output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description supplies a complete response-shape example covering all returned fields, pagination envelope, and a workflow showing the UI-style call sequence and follow-up tools. For a complex 8-parameter listing tool with three enums, nothing an agent needs to select and invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline baseline is 3, but the description goes well beyond: it explains what each status value means, how status and experiment_statuses interact to mirror UI tabs, default values for sort_by/sort_order/page/size, and the full sortable field list. The description actually carries more parameter nuance than the schema's own descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb, resource, and scope: 'List wizard (Metadata-native) campaigns for the current account' with pagination, sorting, and experiment-status filtering. The 'DO NOT USE' section explicitly names sibling tools (search_campaigns_by_names, list_budget_groups, experiment_performance_stats) that handle different but related intents, so an agent can distinguish this tool without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit trigger phrases ('Show me all campaigns', 'Show active campaigns', 'Campaigns sorted by spend') and a 'DO NOT USE' section that routes specific intents to named alternatives. The UI-tab mapping (All/Active/Paused/Draft/Finished) further tells the agent exactly which parameter combinations to choose for each user request.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_campaignManage CampaignADestructiveInspect
Manage a campaign by pausing or restarting it.
KEYWORDS: pause, stop, restart, resume, unpause, campaign, control, manage, halt
WHEN TO USE:
- User asks to "pause campaign X"
- User wants to "stop campaign Y"
- User requests to "restart campaign Z"
- User wants to "resume campaign A"
- User asks to "unpause campaign B"
ACTIONS:
- pause: Temporarily pause an active campaign to stop ad serving and budget spend
- restart: Resume a paused campaign to continue ad serving and budget spend
REQUIRED PARAMETERS:
- campaign_id: The unique identifier of the campaign to manage (integer, required)
- action: The action to perform - "pause" or "restart" (string, required)
CAMPAIGN ID SOURCES:
Campaign IDs can be obtained from:
- search_campaigns_by_names tool
- create_campaign tool response
- Campaign management interface URLs
IMPORTANT VALIDATION REQUIREMENTS:
- **CRITICAL**: You can ONLY pause campaigns that are currently "Active"
- **CRITICAL**: You can ONLY restart campaigns that are currently "Paused"
- Before attempting to pause or restart, use search_campaigns_by_names to verify the current campaign status| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | The action to perform: 'pause' to stop the campaign, 'restart' to resume it | |
| campaign_id | Yes | The unique identifier of the campaign to manage |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (destructiveHint=true, readOnlyHint=false), the description explains that pausing stops ad serving and budget spend while restart resumes them. It also discloses the critical state validation requirement, giving the agent actionable behavioral context without contradicting any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear sections and a front-loaded summary. Some redundancy exists—KEYWORDS overlaps WHEN TO USE and REQUIRED PARAMETERS restates the schema—but the structure remains scannable and useful for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation tool with no output schema, the description covers purpose, when to use, action semantics, parameter sources, and validation preconditions. Nothing material is missing for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers both parameters with descriptions and an enum, so the baseline is 3. The description adds meaning by explaining the operational effect of each action and listing concrete sources for campaign_id, though some of this repeats what the schema already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action-resource pairing: 'Manage a campaign by pausing or restarting it.' It then enumerates exactly two supported actions, pause and restart, which distinguishes it from sibling campaign tools like create_campaign, launch_campaign, and duplicate_campaign.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE' section lists concrete user intents: pause, stop, restart, resume, and unpause. It also gives hard preconditions—only Active campaigns can be paused and only Paused campaigns can be restarted—and instructs the agent to verify status with search_campaigns_by_names before acting.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
manage_experimentManage ExperimentADestructiveInspect
Pause or restart a whole experiment (a launched channel campaign inside a wizard campaign).
KEYWORDS: pause, stop, restart, resume, unpause, experiment, control, manage, halt
WHEN TO USE:
- User asks to "pause experiment X"
- User wants to "stop the LinkedIn experiment"
- User requests to "restart experiment Y"
- User wants to "resume/unpause a paused experiment"
SCOPE - DO NOT CONFUSE WITH SIMILAR TOOLS:
- manage_experiment (this tool) acts on ONE WHOLE EXPERIMENT.
- pause_experiment_keyword / restart_experiment_keyword act on ONE
KEYWORD inside an experiment - they never pause the experiment itself.
- manage_campaign acts on the whole wizard campaign, which can span
several experiments/channels.
ACTIONS:
- pause: Stop ad serving and budget spend for the experiment
- restart: Resume a paused experiment so it serves ads and spends again
WORKFLOW:
1. Find the experiment: search_experiments(search_name="my experiment")
and note experimentId and statusLabel from the results
2. Pause it: manage_experiment(experiment_id=123, action="pause")
3. Or restart it: manage_experiment(experiment_id=123, action="restart")
IMPORTANT VALIDATION REQUIREMENTS:
- **CRITICAL**: You can ONLY pause experiments that are currently active
- **CRITICAL**: You can ONLY restart experiments that are currently Paused
- Use search_experiments first to verify the current experiment status
RESTART BUDGET CONFIRMATION FLOW:
Restarting first estimates the impact on budget groups (the same check
the main UI runs). If any budget group is impacted, the tool does NOT
restart: it returns status="requires_confirmation" with the impacted
groups in budgetImpact. Present the impact to the user, and only after
they explicitly confirm, call again with confirm_budget_impact=true.
WARNING: This changes the live state of the experiment on the ad channel.
WARNING: ASYNC FLOW: The channel-side status change may take a moment to
propagate. Verify later with search_experiments.| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | The action to perform: 'pause' to stop the experiment, 'restart' to resume it | |
| experiment_id | Yes | The experiment ID to pause or restart (experimentId from search_experiments). | |
| confirm_budget_impact | No | Restart only. Set true ONLY after the user explicitly confirmed the budget-group impact returned by a previous manage_experiment call with status='requires_confirmation'. | |
| auto_pause_ignore_historical_data | No | Restart only. When the experiment was auto-paused for low performance, true tells the optimizer to ignore the historical performance data that caused the pause. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only convey readOnlyHint=false, openWorldHint=true, destructiveHint=true. The description adds substantial behavioral context beyond that: it mutates live channel state (WARNING), which validates destructiveHint; it discloses the async propagation delay and instructs verification via search_experiments; it reveals the conditional requires_confirmation flow for budget-group impact; and it states preconditions (only pause active experiments, only restart paused ones). No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized into labeled sections (KEYWORDS, WHEN TO USE, SCOPE, ACTIONS, WORKFLOW, VALIDATION, CONFIRMATION FLOW, WARNINGS), and the core purpose is front-loaded in the first sentence. The KEYWORDS list is somewhat redundant with the WHEN TO USE section, and the WORKFLOW partially restates ACTIONS, but these repetitions serve reinforcement and are not filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive 4-parameter tool with no output schema, the description covers preconditions, side effects, async behavior, the confirmation sub-flow, and how to verify results. The only notable gap is the precise success response shape (e.g., what status values a successful pause returns), though the requires_confirmation status and budgetImpact field are already disclosed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantic value: the ACTIONs section defines what 'pause' and 'restart' actually do (stop ad serving/budget spend vs. resume), the RESTART BUDGET CONFIRMATION FLOW explains when and how confirm_budget_impact must be set, and the workflow maps experiment_id to the experimentId field returned by search_experiments. Only auto_pause_ignore_historical_data gets light treatment, though its schema description is adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence uses a specific verb+resource pair ('Pause or restart a whole experiment') and defines the resource precisely ('a launched channel campaign inside a wizard campaign'). The SCOPE section explicitly distinguishes this tool from pause_experiment_keyword/restart_experiment_keyword (keyword-level) and manage_campaign (wizard-campaign-level), so an agent can disambiguate without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE section lists concrete user-query patterns ('pause experiment X', 'stop the LinkedIn experiment'), and SCOPE names the alternatives with exact conditions for when they apply. The WORKFLOW section gives an explicit call sequence via search_experiments first, which is actionable guidance an agent can follow directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pause_experiment_keywordPause Experiment KeywordADestructiveInspect
Pause a specific keyword running in an experiment.
PURPOSE:
Pause a keyword that is currently active in an experiment. This stops the keyword
from being used in the experiment without removing it entirely.
SCOPE - THIS TOOL ACTS ON ONE KEYWORD, NOT ON THE EXPERIMENT:
It pauses a SINGLE keyword INSIDE an experiment. The experiment itself keeps
running with its other keywords. To pause or restart a WHOLE experiment,
use manage_experiment instead.
WHEN TO USE:
- Pause an underperforming keyword in an experiment
- Temporarily stop a keyword from running in a specific experiment
- Manage keyword performance within experiments
PREREQUISITE:
Use list_experiment_keywords first to find the keywordExternalId and wizExperimentId
for the keyword you want to pause. Both come from that tool's results:
keywordExternalId identifies the keyword on the ad channel, and wizExperimentId
is the experiment's ID (the same ID search_experiments returns as experimentId).
WORKFLOW:
1. Search for the keyword: list_experiment_keywords(keywordOrExperimentName="my keyword")
2. Note the keywordExternalId and wizExperimentId from the results
3. Pause it: pause_experiment_keyword(keywordExternalId=12345, wizExperimentId=678)
4. (Optional) Verify later: list_experiment_keywords(keywordOrExperimentName="my keyword")
to check the status has changed
PARAMETERS:
- keywordExternalId: Required. The external ID of the keyword to pause (from list_experiment_keywords).
- wizExperimentId: Required. The experiment ID where the keyword is running (from list_experiment_keywords).
WARNING: This action changes the state of the keyword in the experiment.
The keyword will stop running in the specified experiment.
WARNING: ASYNC FLOW: Pausing a keyword is an asynchronous operation. The status change
may not be immediately reflected. Use list_experiment_keywords after some time
to verify the keyword status has been updated.| Name | Required | Description | Default |
|---|---|---|---|
| wizExperimentId | Yes | The experiment ID where the keyword is running. | |
| keywordExternalId | Yes | The external ID of the keyword to pause. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds significant behavioral context: it warns that the action changes state, is asynchronous, and that the status may not update immediately, advising verification via list_experiment_keywords. It also explains that the keyword is paused but not removed. This goes well beyond what annotations provide and gives the agent a clear expectation of side effects and timing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (PURPOSE, SCOPE, WHEN TO USE, PREREQUISITE, WORKFLOW, PARAMETERS, WARNING). It is longer than strictly necessary for a two-parameter tool, but every section adds operational value, especially the async warning and workflow. The front-loading of purpose and scope is effective, and the warnings are appropriately placed. It earns a 4 rather than a 5 due to slight redundancy (e.g., the PARAMETERS section largely repeats the schema) but remains efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with only two parameters and no output schema, the description covers everything an agent needs: how to obtain the IDs, the exact workflow, the asynchronous nature, and how to verify success. It even addresses the relationship to sibling tools (manage_experiment, restart_experiment_keyword). The description is fully self-contained and leaves no critical operational gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents both parameters with descriptions (100% coverage), so the baseline is 3. The description adds value by explaining that both IDs come from list_experiment_keywords and clarifying the mapping: keywordExternalId identifies the keyword on the ad channel and wizExperimentId is the experiment's ID (same as experimentId from search_experiments). This provenance information is not in the schema and helps the agent source the values correctly, justifying a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Pause a specific keyword running in an experiment') and immediately distinguishes its scope from manage_experiment, which pauses a whole experiment. It clearly states it acts on one keyword inside an experiment, not the experiment itself, and names the sibling restart_experiment_keyword implicitly. This leaves no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a dedicated WHEN TO USE section with concrete scenarios (pause underperforming keyword, temporarily stop a keyword) and explicitly says to use manage_experiment for whole-experiment pauses. It also provides a PREREQUISITE and WORKFLOW that tell the agent exactly when and how to call it, including which sibling (list_experiment_keywords) to use first and how to verify afterward. No inference is left to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
performance_metricsGet Performance MetricsARead-onlyInspect
Granular performance metrics for ads, audiences, creatives, offers, target groups, keywords. IMPORTANT: Always specify endpoint parameter. Always use ISO 8601 for dates.
USE FOR: Best performing ads/audiences/creatives/offers/target groups, ingredient comparisons, ad type analysis (IMAGE, VIDEO, CAROUSEL), lead gen forms vs landing pages, pipeline by ingredient, creative previews, keyword performance. NOT FOR: Account-level stats, experiment-level analysis without ingredient focus.
ENDPOINT LOGIC:
'target group' → customAudience/group
'audience' → customAudience
'offer'/'lead gen'/'landing page' → offer
'creative' → creative
'keyword' → keywords
'ad'/'ads' or default → ads
AD TYPES: IMAGE, VIDEO, CAROUSEL, DOCUMENT, CONVO, SPOTLIGHT, SEARCH, MESSAGE
The
adFormatfield on each response row identifies the ad type.
METRICS: spend, impressions, clicks, leads, mqls | opens, sends, actionClicks, costPerOpen, costPerSend (CONVO/MESSAGE ads) | cpl, cpc, cpm, ctr, conversionRate, formConversionRate, mqlRate | totalOpps, totalTriggered, oppsAmount, triggeredAmount | cpMql, cpOppInfluenced, cpOppTriggered | channel, goal, adFormat, audienceSize, statusLabel | previewUrl
CONVO/MESSAGE AD CAVEAT: when adFormat is CONVO or MESSAGE (LinkedIn message ads), success is measured by opens, sends, and actionClicks (and costPerOpen / costPerSend), NOT clicks/ctr/cpc. Do not rank these ads by CTR or dismiss them when clicks=0. Use sort='actionClicks,desc' or sort='opens,desc' for conversational performance ranking.
RULES: Field 'id' corresponds to endpoint queried. Exclude $0 CPL experiments from calculations.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | Set of IDs to filter by | |
| page | No | Page number to retrieve (0-based indexing) | |
| size | No | Number of results per page. Default 100; raise it freely (up to 10000) for comprehensive full-dataset analysis. | |
| sort | No | Sorting criteria (e.g., 'spent,desc', 'cpl,asc', 'experimentId,spent,desc') | |
| tags | No | Set of tag IDs to filter by | |
| goals | No | Filter by campaign goals | |
| adName | No | Filter by specific ad name | |
| maxCpl | No | Maximum cost per lead threshold | |
| minCpl | No | Minimum cost per lead threshold | |
| endDate | No | endDate in ISO 8601 format (YYYY-MM-DDThh:mm:ssZ), e.g., `startDate=2025-06-12T14:30:00.123Z`). | |
| keyword | No | Filter by specific keyword | |
| channels | No | Filter by marketing channels | |
| endpoint | No | Specific endpoint to query. If not specified, will be auto-determined from query context. Use 'customAudience/group' for target groups. | |
| maxLeads | No | Maximum number of leads threshold | |
| maxSpend | No | Maximum spend threshold | |
| minLeads | No | Minimum number of leads threshold | |
| minSpend | No | Minimum spend threshold | |
| adFormats | No | Filter by ad format types. Applied to ads endpoint automatically. | |
| offerName | No | Filter by specific offer name | |
| startDate | No | startDate in ISO 8601 format (YYYY-MM-DDThh:mm:ssZ), e.g., `startDate=2025-06-12T14:30:00.123Z`). | |
| offerTypes | No | Filter by offer types. LG=Lead Gen forms, LP=Landing Pages | |
| oppsEndDate | No | End date for opportunities data in ISO 8601 format | |
| campaignName | No | Filter by specific campaign name | |
| creativeName | No | Filter by specific creative name | |
| visibilities | No | Filter by visibility status. The platform knows only VISIBLE (live) and ARCHIVED; there is no HIDDEN value and sending one is rejected with a 400. | |
| accountTagIds | No | Set of account tag IDs to filter by | |
| audienceTypes | No | Filter by audience types | |
| experimentIds | No | Set of experiment IDs to filter by | |
| oppsStartDate | No | Start date for opportunities data in ISO 8601 format | |
| showWithSpend | No | Show only experiments/ingredients with spend data | |
| customFieldIds | No | Custom field IDs to include | |
| experimentList | No | Experiment list filter | |
| experimentName | No | Filter by specific experiment name | |
| budgetGroupName | No | Filter by specific budget group name | |
| maxAudienceSize | No | Maximum audience size threshold | |
| minAudienceSize | No | Minimum audience size threshold | |
| skipCustomFields | No | Skip custom fields in response | |
| customAudienceName | No | Filter by specific custom audience name | |
| usedInActiveExperiments | No | Filter for ingredients used in active experiments only | |
| launchedExperimentStatuses | No | Filter Performance Metrics by experiment launch statuses only. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only and non-destructive; the description adds substantial behavioral context: endpoint auto-logic, ad-type caveats, response row fields, metric semantics, and the exclusion of $0 CPL experiments. It also warns against ranking CONVO/MESSAGE ads by CTR and clarifies when to use actionClicks/opens instead, behavior not inferable from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although lengthy, the description is densely structured with bolded section headers (IMPORTANT, USE FOR, NOT FOR, ENDPOINT LOGIC, AD TYPES, METRICS, RULES), front-loading the most critical instructions first. Each section earns its place by covering a distinct operational concern for a 40-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by listing all relevant metric fields, endpoint choices, response row elements, and ad-type caveats. It also states rules like excluding $0 CPL experiments and the endpoint/id correspondence, covering everything an agent needs to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful parameter-level guidance beyond schema: it explains the endpoint parameter mapping, recommends raising the size parameter for full-dataset analysis, and gives sorting advice for conversational ads. It does not explain every filter parameter, but the schema already documents those clearly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it retrieves granular performance metrics for ads, audiences, creatives, offers, target groups, and keywords. It also distinguishes itself from account-level and experiment-level analytics via the explicit USE FOR/NOT FOR sections, making it clear this is the ingredient-focused metrics tool among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes explicit USE FOR and NOT FOR lists, giving clear context for when to invoke this tool versus account-level or experiment-level tools. It also provides endpoint mapping logic and a CONVO/MESSAGE ad caveat with specific sort recommendations, so an agent knows exactly when and how to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_metadata_analytics_accountQuery Account AnalyticsARead-onlyInspect
Query the caller's own account CONTEXT from the Metadata.io knowledge base — a rolled-up summary (firmographic, recent 90-day campaign history, open drafts, per-experiment performance) refreshed overnight. Use it to GROUND a recommendation or plan in the account's own history before you suggest or generate something.
USE FOR: firmographic (industry, size, revenue, country) and high-level recent-history context to back a decision — e.g. "given our recent LinkedIn performance, what should we try next quarter?".
NOT FOR the account's CURRENT LIVE STATE. This is a periodic roll-up,
not the live platform — it can miss or misreport granular state (e.g.
answer "nothing runs in Germany" while many live campaigns target
Germany). For "what's running / what's live", "which campaigns target
<country/segment>", "list our campaigns / audiences / offers", or
real-time spend / pacing, use the live platform analytics tools instead
(account_level_stats, performance_metrics, demographic_country_stats,
search_campaigns_by_names, etc.). Also NOT FOR industry benchmarks
(use query_metadata_analytics_benchmarks) or a different company
(cross-tenant queries are rejected).
The caller's account_id is resolved server-side from the caller's own
credentials and reflects any active account switch. It cannot be supplied
or overridden by the caller.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes | Natural-language question about the caller's account. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds critical behavioral context: data is refreshed overnight and may miss or misreport granular live state, account_id is resolved server-side and cannot be overridden, and cross-tenant queries are rejected. This goes well beyond the annotations and clarifies limitations an agent must know.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Despite being long, every section earns its place. The core purpose is front-loaded, followed by structured use cases and exclusions. The text is organized with clear labels (USE FOR, NOT FOR) and specific examples, making it easy for an agent to parse and apply. No fluff or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of this tool (many siblings, need to know when to use vs not), the description is thorough. It covers usage, limitations, alternatives, server-side behavior, and cross-tenant restrictions. An output schema exists, so return values are not the description's responsibility. Everything an agent needs to call it correctly is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers the single parameter 'question' with a clear description, so schema coverage is 100%. The description reinforces the natural-language nature but does not add much beyond what the schema already provides. Baseline 3 is appropriate given the schema carries the meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Query the caller's own account CONTEXT from the Metadata.io knowledge base'. It clearly defines the scope as a rolled-up summary of firmographic, campaign history, and experiment performance. It distinguishes itself from siblings by emphasizing this is a periodic roll-up, not live state, and names alternatives like account_level_stats and performance_metrics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'USE FOR' and 'NOT FOR' sections with concrete examples and named alternative tools. It tells the agent when to use this tool (grounding recommendations in account history) and when not to (live state, benchmarks, cross-tenant queries). It even provides a sample question to illustrate the intended use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_metadata_analytics_benchmarksQuery Advertising BenchmarksARead-onlyInspect
Query the Metadata.io marketing knowledge base for cross-account industry benchmarks and priors.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes | Natural-language question. Should describe a COHORT (industry × size × channel × format / audience), not a specific company. | |
| conversation_id | No | Optional. Pass the value returned from a prior `_benchmarks` call to keep the query context warm. The two knowledge-base tools never share conversation_ids — pass only IDs returned by `_benchmarks` here. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is established outside the description. The description adds context about the data domain (cross-account benchmarks/priors), but no additional behavioral behaviors such as rate limits, latency, or response behavior are disclosed. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, dense sentence that front-loads the verb and resource with no wasted words. It does not restate the title or replicate schema content, and the detailed parameter guidance lives where it belongs in the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema, full parameter documentation, and read-only annotations, the tool is nearly complete as defined. The only notable gap is the lack of an explicit pointer to query_metadata_analytics_account for account-specific analytics, which would make routing between the two knowledge-base tools fully unambiguous.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already thoroughly explains the 'question' cohort semantics and the conversation_id context-warming rule, including the caution about never sharing IDs between the two knowledge-base tools. The description itself adds little over the schema, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Query'), a specific resource (the Metadata.io marketing knowledge base), and a clear scope (cross-account industry benchmarks and priors). This clearly distinguishes it from the account-specific analytics sibling (query_metadata_analytics_account) and other campaign/account tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description establishes clear context: use this for cross-account industry benchmarks and priors, not for a specific company or account. It does not explicitly name the alternative sibling or state when not to use it, but the 'cross-account' phrasing and the sibling list make the intended use fairly evident. It lacks an explicit exclusion statement, so it does not reach a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
regenerate_flexible_backgroundRegenerate Flexible Creative BackgroundADestructiveInspect
Regenerate ONLY the background scene of a flexible creative, keeping the editable text/logo layers untouched. Returns the new background image URL so the editor swaps just the background layer.
USE FOR: "regenerate the background", "try a different scene", "new background, same text".
Accepts an optional image_source (the current background) to guide a same-style regeneration; omit it for a fresh scene.
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Company domain for brand DNA (e.g. 'metadata.io'). No protocol. | |
| platform | No | Target platform (sets the default aspect ratio). Default: 'linkedin'. | |
| aspect_ratio | No | Pass the creative's own canvas.aspect_ratio so the new background keeps its shape. Omitting it on a non-default canvas reshapes the creative and the existing layers no longer fit. | |
| image_source | No | Optional URL of the current background to guide a same-style regeneration (image-to-image). Omit for a fresh scene. | |
| instructions | Yes | Direction for the new background scene. | |
| background_hex | No | Optional 6-digit hex to pin the dominant background color (e.g. '#0A2540'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description adds meaningful behavioral context: it returns a URL, keeps text/logo layers untouched, and explains the background-swapping outcome. It does not contradict the destructiveHint annotation because it describes replacing the old background while preserving other layers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core behavior, and every sentence contributes: scope, return value, usage triggers, and optional input semantics. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no output schema, the description covers the essential return value and the non-obvious preservation behavior. The schema carries parameter details well. A small gap is the lack of any mention of how this relates to sibling tools like generate_flexible_brand_creative or render_flexible_creative, but that is more a usage-guideline nuance than a completeness failure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline applies. The description's image_source guidance ('guide a same-style regeneration; omit it for a fresh scene') mostly restates the schema's existing parameter description, adding little semantic value. Other parameters are adequately documented in the schema itself.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource: 'Regenerate ONLY the background scene of a flexible creative' and explicitly carves out what is preserved ('editable text/logo layers untouched'). This clearly distinguishes the tool from sibling generation/editing tools that would modify the whole creative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE FOR' section gives concrete user-intent triggers ('regenerate the background', 'try a different scene', 'new background, same text'), and the 'ONLY' wording sets a boundary against full-creative regeneration. However, it never names an alternative sibling tool or an explicit 'do not use when' case, so it falls short of full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_ad_from_campaignRemove Ad from CampaignADestructiveInspect
Remove specific ads (ad groups) from one or more channels in an existing campaign.
Use this tool when you need to detach a named ad from a particular channel
(e.g. remove "Pixel Ads in Minutes_v2_LI" from LINKEDIN).
Channel and ad group IDs are resolved internally — you only need the
human-readable channel type and ad name.
Works on both campaign structures. On a Channel-First / Native (N×N×N) campaign the
ad is removed from its WizNativeAdContainer's native ads (resolved by ad name via the
ads library); any container then left with no asset at all is dropped.
KEYWORDS: remove, delete, ad, creative, ad group, channel, campaign
WHEN TO USE:
- User wants to remove a specific ad from a channel
- User wants to clean up ad groups from one or more channels
- Multiple ads across multiple channels can be removed in a single call
RESPONSE:
- Returns the refreshed campaign state plus a removal_results list with one
entry per requested removal recording its success or error. ALWAYS check
removal_results — a partial failure (e.g. one of two names not found) still
returns normally, so report only what actually came back successful.
REQUIRED PARAMETERS:
- campaign_id: Campaign ID (numeric identifier)
- channel_ads: Object mapping channel type → list of ad names to remove
CHANNEL TYPES: FACEBOOK, INSTAGRAM, GOOGLE_ADS, LINKEDIN, MICROSOFT_ADS, REDDIT, TWITTER
EXAMPLES:
Remove one ad from LINKEDIN:
remove_ad_from_campaign({
"campaign_id": 42546,
"channel_ads": {
"LINKEDIN": ["Pixel Ads in Minutes_v2_LI"]
}
})
Remove ads from multiple channels at once:
remove_ad_from_campaign({
"campaign_id": 42546,
"channel_ads": {
"LINKEDIN": ["Ad A", "Ad B"],
"FACEBOOK": ["Ad C"]
}
})
INTEGRATION WITH OTHER TOOLS:
- Use get_campaign_by_wizard_id to inspect current ads per channel before removing
- Use search_campaigns_by_names to find the campaign ID| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The unique identifier of the campaign | |
| channel_ads | Yes | Map of channel type to list of ad names to remove. Example: {"LINKEDIN": ["Ad A"], "FACEBOOK": ["Ad B"]} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true, and the description reinforces and expands on this by explaining internally resolved IDs, the dropping of empty containers on Channel-First campaigns, and the removal_results list with per-attempt success or error. It also warns that partial failures return normally and advises checking results. This is valuable behavioral context beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then uses clearly labeled sections for usage, response, parameters, examples, and integration. It is longer than average, but the complexity of partial failures and campaign-structure nuances justifies the length. The KEYWORDS block is mildly redundant, but most content earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the nested parameter, two campaign structures, partial-failure behavior, and absence of an output schema, the description covers all necessary ground. The RESPONSE section clearly explains what is returned and how to interpret removal_results. Channel type enumeration and integration guidance make the tool callable correctly without additional lookups.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaning by listing required parameters, enumerating supported channel types, and clarifying that ad names are human-readable while IDs are resolved internally. The two examples also clarify the exact shape of the nested channel_ads object, which helps an agent construct valid calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: remove specific ads (ad groups) from one or more channels in an existing campaign. It clearly distinguishes this from siblings like remove_channels_from_campaign and remove_audiences_from_campaign by naming the exact target. The first sentence alone is enough for an agent to know what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a dedicated WHEN TO USE section with concrete scenarios: removing a specific ad from a channel, cleaning up ad groups, and removing multiple ads across channels in one call. It also names companion tools like get_campaign_by_wizard_id and search_campaigns_by_names. However, it does not explicitly contrast with archive_ad/unarchive_ad or other remove_* tools, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_audiences_from_campaignRemove Audiences from CampaignADestructiveInspect
Remove specific audiences from one or more channels in an existing campaign.
Use this tool when you need to detach a named audience/group from a particular
channel (e.g. remove "European Digital Nomad Investors" from FACEBOOK).
Channel and audience IDs are resolved internally — you only need the human-readable
channel type and audience name.
Works on both campaign structures. On a Channel-First / Native (N×N×N) campaign the
audience is cleared from its WizNativeAdContainer(s); any container then left with no
asset at all (no audience, target group, keyword, ad or offer) is dropped.
KEYWORDS: remove, delete, audience, group, channel, campaign, targeting
WHEN TO USE:
- User wants to remove a specific audience from a channel
- User wants to clean up targeting groups from one or more channels
- Multiple audiences across multiple channels can be removed in a single call
RESPONSE:
- Returns the refreshed campaign state plus a removal_results list with one
entry per requested removal recording its success or error. ALWAYS check
removal_results — a partial failure (e.g. one of two names not found) still
returns normally, so report only what actually came back successful.
REQUIRED PARAMETERS:
- campaign_id: Campaign ID (numeric identifier)
- channel_audiences: Object mapping channel type → list of audience names to remove
CHANNEL TYPES: FACEBOOK, INSTAGRAM, GOOGLE_ADS, LINKEDIN, MICROSOFT_ADS, REDDIT, TWITTER
EXAMPLES:
Remove one audience from FACEBOOK:
remove_audiences_from_campaign({
"campaign_id": 42545,
"channel_audiences": {
"FACEBOOK": ["European Digital Nomad Investors_p2w8"]
}
})
Remove audiences from multiple channels at once:
remove_audiences_from_campaign({
"campaign_id": 42545,
"channel_audiences": {
"FACEBOOK": ["Audience A", "Audience B"],
"LINKEDIN": ["Audience C"]
}
})
INTEGRATION WITH OTHER TOOLS:
- Use get_campaign_by_wizard_id to inspect current audiences per channel before removing
- Use search_campaigns_by_names to find the campaign ID| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The unique identifier of the campaign | |
| channel_audiences | Yes | Map of channel type to list of audience names to remove. Example: {"FACEBOOK": ["Audience A"], "LINKEDIN": ["Audience B"]} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=true, so the agent already knows this is a destructive operation. The description adds significant detail beyond that: it explains the behavior on Channel-First/Native campaigns (dropping empty containers), and—critically—discloses that partial failures occur and the agent must check the removal_results list because a normal return does not mean all removals succeeded. This is a crucial behavioral nuance that is not in the annotations, and it is clearly articulated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-structured with clear sections (intro, when to use, response, required parameters, channel types, examples, integration). It is front-loaded with the core purpose, and every section adds meaningful information—especially the response-handling note and examples. While it could be trimmed slightly, the organization prevents it from feeling bloated, and the length is justified by the tool's destructive nature and the need to convey partial-failure behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description fully explains the response format (refreshed campaign state + removal_results) and the critical behavior that partial failures return normally. It also covers both campaign structures, lists all supported channel types, and provides integration suggestions with related tools. An agent has everything needed to call this tool correctly and interpret the results, making it contextually complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes both parameters (campaign_id and channel_audiences) with 100% coverage, so the baseline is 3. The description adds extra value by listing the supported channel types (FACEBOOK, INSTAGRAM, GOOGLE_ADS, etc.), clarifying that audience IDs are resolved internally (so only names are needed), and providing two concrete examples that illustrate the expected JSON structure. This goes beyond the schema's minimal descriptions, earning a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement: 'Remove specific audiences from one or more channels in an existing campaign.' This clearly identifies the verb (remove), the resource (audiences), and the scope (channels within a campaign). It distinguishes itself from sibling removal tools by focusing on audiences (e.g., remove_ad_from_campaign, remove_keywords_from_campaign, remove_target_groups_from_campaign) and even names the exact scenario with a concrete example. The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes an explicit 'WHEN TO USE' section listing three specific conditions, and states the tool should be used when detaching a named audience/group from a channel. It also provides integration guidance by recommending get_campaign_by_wizard_id to inspect current audiences and search_campaigns_by_names to find the campaign ID. While it does not explicitly say when not to use it, the contrast with other remove tools is clear, and the guidance is actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_channels_from_campaignRemove Channels from CampaignADestructiveInspect
Disable one or more entire channels from an existing campaign.
Use this tool when the goal is to turn off a whole channel (e.g. stop running
ads on FACEBOOK entirely). To remove a specific audience from a channel instead,
use remove_audiences_from_campaign.
KEYWORDS: remove, delete, disable, channel, campaign
WHEN TO USE:
- Disable/remove an entire channel from a campaign (e.g. remove FACEBOOK or GOOGLE_ADS)
- Multiple channels can be disabled in a single call
- Returns the campaign state before and after the change
RESPONSE:
- Returns the refreshed campaign state plus a removal_results list with one
entry per requested removal recording its success or error. ALWAYS check
removal_results — a partial failure (e.g. one of two names not found) still
returns normally, so report only what actually came back successful.
REQUIRED PARAMETERS:
- campaign_id: Campaign ID (numeric identifier)
- channels: Array of channel types to disable
CHANNEL TYPES: FACEBOOK, INSTAGRAM, GOOGLE_ADS, LINKEDIN, MICROSOFT_ADS, REDDIT
EXAMPLES:
Disable a single channel:
remove_channels_from_campaign({
"campaign_id": 12345,
"channels": ["FACEBOOK"]
})
Disable multiple channels at once:
remove_channels_from_campaign({
"campaign_id": 12345,
"channels": ["FACEBOOK", "GOOGLE_ADS", "INSTAGRAM"]
})
INTEGRATION WITH OTHER TOOLS:
- Use search_campaigns_by_names to find the campaign ID
- Use get_campaign_by_wizard_id to inspect active channels before removal
- Use remove_audiences_from_campaign to remove a specific audience from a channel| Name | Required | Description | Default |
|---|---|---|---|
| channels | Yes | List of channels to disable from the campaign. Example: ["FACEBOOK", "GOOGLE_ADS"] | |
| campaign_id | Yes | The unique identifier of the campaign |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already set destructiveHint=true and readOnlyHint=false, but the description adds valuable behavioral detail: it notes that the response includes the campaign state before and after the change, and warns about partial failures (removal_results must be checked because a failed name still returns normally). This goes beyond the annotations and clarifies the operational behavior, though it could mention idempotency or side effects explicitly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear sections (purpose, WHEN TO USE, RESPONSE, REQUIRED PARAMETERS, CHANNEL TYPES, EXAMPLES, INTEGRATION). It is front-loaded with the core purpose and each section earns its place. No fluff or redundancy; the examples and notes are directly useful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with only two parameters and no output schema, the description is remarkably complete. It explains the response structure, partial-failure handling, valid channel enum values, and how to find campaign IDs via search_campaigns_by_names or inspect channels via get_campaign_by_wizard_id. An agent has everything needed to call it correctly and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers both parameters with descriptions and an enum for channels. The description reinforces the meaning by explaining that 'entire channels' are disabled and provides concrete examples of valid channel values. It also clarifies the difference between channel removal and audience removal, which adds semantic depth beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and resource: 'Disable one or more entire channels from an existing campaign.' It immediately distinguishes itself from the sibling remove_audiences_from_campaign by clarifying the scope (entire channel vs. specific audience). This leaves no ambiguity about what the tool does and how it differs from alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool: 'Use this tool when the goal is to turn off a whole channel...' and contrasts it with remove_audiences_from_campaign. It also includes a 'WHEN TO USE' section and an 'INTEGRATION WITH OTHER TOOLS' section that names specific alternatives and companion tools, providing clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_extensions_from_native_campaignRemove Extensions from Native-Structure CampaignADestructiveInspect
Detach extensions from a native-structure Google Ads / Microsoft Ads campaign. The extension stays in the account library — only the campaign binding is removed.
ALSO KNOWN AS: remove extension from campaign, detach sitelink, unlink extension, take sitelink off campaign
KEYWORDS: remove, detach, unlink, unbind, extension, sitelink, callout, campaign, native, native structure, google ads, microsoft ads, bing
WHEN TO USE:
- "Remove that sitelink from campaign X"
- "Take the old promotion extension off the native search campaign"
- Undoing a wrong add_extensions_to_native_campaign call
WHEN NOT TO USE:
- Deleting the extension from the library entirely — this only unbinds it from one campaign
- The campaign uses the Precision / METADATA structure — native-structure campaigns only
INPUTS (all required):
- campaign_id: wizard campaign id
- channel: GOOGLE_ADS or MICROSOFT_ADS
- extension_ids: internal ids from list_extensions
BEHAVIOUR: only the named ids are detached; other attachments are preserved. Safe to re-run.
EXAMPLE:
remove_extensions_from_native_campaign(campaign_id=8421, channel="GOOGLE_ADS", extension_ids=[551])| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | Search channel. Ad extensions are a search-channel-only concept. | |
| campaign_id | Yes | The wizard campaign id. | |
| extension_ids | Yes | Internal library extension ids from list_extensions. These are the `id` field, NOT `externalId` (the ad platform's own id). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true, readOnlyHint=false, and openWorldHint=true. The description goes further by explaining that the extension remains in the library, only the campaign binding is removed, only the named IDs are detached, other attachments are preserved, and the operation is safe to re-run. This provides important context beyond the raw annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections: summary, aliases, keywords, usage guidance, inputs, behavior, and example. The key facts are front-loaded, and the example illustrates a realistic call. While lengthy, every section earns its place and improves agent matching and invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With three fully documented parameters, clear behavior notes, explicit exclusions, and an example call, the description gives an agent everything needed to select and invoke the tool correctly. No output schema exists, but for a detachment operation the behavioral guarantees provided are sufficient for confident use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents campaign_id, channel, and extension_ids thoroughly, including the crucial warning that extension_ids are internal ids and not externalId. The description mostly repeats these facts rather than adding substantially new semantics. This is an acceptable baseline given full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource ('Detach extensions from a native-structure campaign') and clearly distinguishes this from deleting the extension entirely and from precision/METADATA-structure campaigns. The 'ALSO KNOWN AS' list and examples further anchor the tool's purpose, and sibling tools like add_extensions_to_native_campaign make the differentiation obvious.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description contains explicit WHEN TO USE and WHEN NOT TO USE sections, with concrete natural-language examples and the inverse operation (add_extensions_to_native_campaign) mentioned. It also explicitly excludes the precision/METADATA structure, leaving no ambiguity about when this tool applies versus a sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_keywords_from_campaignRemove Keywords from CampaignADestructiveInspect
Remove Google Ads keyword groups and/or negative keyword list attachments from a campaign's GOOGLE_ADS channel.
Use this tool to clear keywords/negative lists from a DRAFT campaign so the
user can replace them with new ones (e.g. "I don't like these keywords, use
these instead" — call this tool to remove the old set, then call
add_and_edit_campaign_elements with the new google.keywords / google.negative_keyword_lists).
Works on both campaign structures. On a Channel-First / Native (N×N×N) campaign a
positive keyword group is also unlinked from its WizNativeAdContainer (keywordGroupId);
negative-list detach is channel-level and unchanged.
KEYWORDS: remove, delete, keyword, keywords, negative, group, google, campaign
PLATFORM CONSTRAINT:
- Only the Draft state allows keyword removal; the platform rejects DELETE on launched/launching campaigns.
CHANNEL: GOOGLE_ADS only (other channels do not have keyword groups).
RESPONSE:
- Returns the refreshed campaign state plus a removal_results list with one
{channel, keyword_group|negative_keyword_list, success, message|error} entry per
requested removal. ALWAYS check removal_results — a partial failure (e.g. one of
two group names not found) still returns normally.
- If EVERY requested removal failed, the tool errors instead of returning.
REQUIRED:
- campaign_id: Campaign ID (numeric identifier)
- At least one of channel_keywords OR channel_negative_keyword_lists must be provided.
OPTIONAL FAST PATH:
- channel_id: When you already have the GOOGLE_ADS channel id in context (e.g. from a recent get_campaign_by_wizard_id call), pass it to skip the full-campaign lookup. The tool will fetch only that single channel.
EXAMPLES:
Remove one keyword group:
remove_keywords_from_campaign({
"campaign_id": 42546,
"channel_keywords": {
"GOOGLE_ADS": ["CRM Keywords"]
}
})
Remove a negative keyword list attachment:
remove_keywords_from_campaign({
"campaign_id": 42546,
"channel_negative_keyword_lists": {
"GOOGLE_ADS": ["Competitor Brands"]
}
})
Remove both at once:
remove_keywords_from_campaign({
"campaign_id": 42546,
"channel_keywords": {"GOOGLE_ADS": ["CRM Keywords", "Demo Keywords"]},
"channel_negative_keyword_lists": {"GOOGLE_ADS": ["Competitor Brands"]}
})
Remove with known channel id (skips campaign lookup):
remove_keywords_from_campaign({
"campaign_id": 42546,
"channel_id": 88123,
"channel_keywords": {"GOOGLE_ADS": ["CRM Keywords"]}
})
INTEGRATION WITH OTHER TOOLS:
- Use get_campaign_by_wizard_id to inspect current keyword groups on a channel before removing.
- After removal, use add_and_edit_campaign_elements with google.keywords / google.negative_keyword_lists to add replacements.| Name | Required | Description | Default |
|---|---|---|---|
| channel_id | No | Optional fast-path: numeric id of the GOOGLE_ADS channel on this campaign. When provided, the tool skips the full-campaign GET and fetches only this channel's keyword list. Use it when you already have the id from a recent campaign read; omit it and the tool resolves the channel by type. | |
| campaign_id | Yes | The unique identifier of the campaign | |
| channel_keywords | No | Map of channel type to list of positive keyword group names to remove. Only GOOGLE_ADS is supported. Example: {"GOOGLE_ADS": ["CRM Keywords"]} | |
| channel_negative_keyword_lists | No | Map of channel type to list of negative keyword list names to detach from the channel. Only GOOGLE_ADS is supported. Example: {"GOOGLE_ADS": ["Competitor Brands"]} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the destructiveHint annotation by disclosing partial-failure behavior via removal_results, the error condition when every removal fails, the Draft-state platform rejection, and the Channel-First/Native campaign structure nuance. These are exactly the behavioral details an agent needs before invoking a destructive tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections, a front-loaded summary, and concrete examples. The KEYWORDS line adds little for an agent, and the length is substantial, but the substantive sections each earn their place for a destructive, multi-behavior tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully covers the response shape (refreshed campaign state plus removal_results entries), partial and total failure semantics, required parameters, optional fast path, platform constraints, and integration with related tools. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description adds the critical at-least-one-of constraint between channel_keywords and channel_negative_keyword_lists, explains the channel_id fast-path semantics, and provides complete JSON examples for each parameter combination. This is meaningful added value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Remove Google Ads keyword groups and/or negative keyword list attachments from a campaign's GOOGLE_ADS channel.' This clearly differentiates from siblings like remove_keywords_from_negative_list, which operates on a negative list itself rather than on a campaign's channel.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit use case ('clear keywords/negative lists from a DRAFT campaign so the user can replace them') and clear constraints (Draft state only, GOOGLE_ADS only). It also names companion tools for inspection and replacement. It does not explicitly call out sibling alternatives to avoid, but the usage context is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_keywords_from_negative_listRemove Keywords from Negative ListADestructiveInspect
Remove keywords from a single existing Google Ads negative keyword list, matched by text.
PURPOSE:
Drop keywords that no longer belong in a negative keyword list (e.g. a search
term that turned out to convert after all, or an over-eager exclusion). The
tool fetches the list internally, finds entries whose text matches what you
pass, and removes every match.
MATCHING:
- Comparison is case-sensitive and exact (whole-text equality).
- If the same text appears under multiple match types (e.g. "free" as PHRASE
AND as EXACT), all of them are removed.
- Inputs that don't match anything are reported back in 'notFound' without
failing the call.
WHEN TO USE:
- Undo a previous add_keywords_to_negative_lists mistake
- Clean up a list during the day-to-day review loop
- For full-list wipe use the platform's deleteAll endpoint instead
(not currently wrapped here)
NOT FOR:
- Detaching the list from a campaign (use remove_keywords_from_campaign).
- Deleting the list itself.
COMMON USE CASES:
1. Remove a single keyword:
remove_keywords_from_negative_list(
listId=43256533,
keywords=["free download"],
)
2. Remove several at once:
remove_keywords_from_negative_list(
listId=43256533,
keywords=["competitor a", "tutorial", "wiki"],
)
PARAMETERS:
- listId (integer, required): negative keyword list id
(from list_negative_keywords_list).
- keywords (array of strings, required, min 1): exact text(s) to remove.
RESPONSE FORMAT:
{
"listId": 43256533,
"removed": [{"text": "free download", "keywordMatchType": "PHRASE", "resourceName": "..."}, ...],
"notFound": ["wiki"]
}
CHANNEL SCOPE:
BOTH search channels are supported: pass channel=MICROSOFT_ADS for Microsoft
Ads (Bing) and channel=GOOGLE_ADS for Google. The two channels hold SEPARATE
lists, so never substitute one channel for the other to get "close enough"
results.| Name | Required | Description | Default |
|---|---|---|---|
| listId | Yes | ID of the negative keyword list (from list_negative_keywords_list). | |
| channel | No | Ad channel scope. Both search channels are supported. These are PER-CHANNEL resources: GOOGLE_ADS and MICROSOFT_ADS hold separate sets, and one is invisible to the other. Defaults to GOOGLE_ADS when the user does not say which. | GOOGLE_ADS |
| keywords | Yes | Exact keyword texts to remove. Case-sensitive whole-text match. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description adds substantial behavior beyond that: case-sensitive exact matching, removal across all match types, notFound values reported without failing, internal list fetching, and the critical channel-separation warning. It also provides a RESPONSE FORMAT, which is valuable since no output schema exists. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: PURPOSE, MATCHING, WHEN TO USE, NOT FOR, COMMON USE CASES, PARAMETERS, RESPONSE FORMAT, CHANNEL SCOPE. It is front-loaded with the core purpose and uses clear headings for scannability. There is no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no output schema, the RESPONSE FORMAT section is essential and provided. Matching semantics, channel scope, examples, and alternatives are all covered. Combined with 100% schema coverage and annotations, there are no significant gaps an agent would need to infer.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds value with COMMON USE CASES showing exact invocation syntax and a CHANNEL SCOPE section clarifying that GOOGLE_ADS and MICROSOFT_ADS hold separate lists and must not be substituted. These nuances go beyond the schema descriptions, justifying a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific action ('Remove keywords'), resource ('negative keyword list'), and scoping ('single existing', 'matched by text'). It clearly distinguishes from siblings in the NOT FOR section, naming remove_keywords_from_campaign and list deletion as outside the scope. No ambiguity remains about what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit WHEN TO USE section lists concrete scenarios (undoing add_keywords_to_negative_lists mistakes, daily cleanup) and NOT FOR section names the exact alternative tool for detaching from campaigns. It even mentions the full-list wipe alternative not currently wrapped. This is the gold standard for routing an agent to the correct tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_offers_from_campaignRemove Offers from CampaignADestructiveInspect
Remove offers — Lead Gen forms OR Landing Pages — from one or more channels in an existing campaign.
Use this tool to detach a named offer from a channel (e.g. remove "Demo Request Form"
from FACEBOOK, or "Pricing LP" from GOOGLE_ADS). The offer type (Lead Gen vs Landing
Page) and its IDs are resolved internally — you only need the channel type and the
offer name. This is the single offer-removal tool (it replaced the Lead-Gen-only
remove_leadgen_offer_from_campaign).
Works on both campaign structures. On a Channel-First / Native (N×N×N) campaign the
offer is cleared from EVERY WizNativeAdContainer native ad that references it
(leadGenFormId / landingPageId), channel-wide — the ad is kept, and any container
then left with no asset at all is dropped. To remove an offer from only ONE
container/row, use add_and_edit_native_campaign_elements.modify_containers instead.
On Precision/METADATA it uses the legacy per-offer delete.
KEYWORDS: remove, delete, offer, lead gen, landing page, form, channel, campaign
WHEN TO USE:
- User wants to remove a specific offer (Lead Gen form or Landing Page) from a channel
- User wants to clean up offers from one or more channels
- Multiple offers across multiple channels can be removed in a single call
RESPONSE:
- Returns the refreshed campaign state plus a removal_results list with one
entry per requested removal recording its success or error. ALWAYS check
removal_results — a partial failure (e.g. one of two names not found) still
returns normally, so report only what actually came back successful.
REQUIRED PARAMETERS:
- campaign_id: Campaign ID (numeric identifier)
- channel_offers: Object mapping channel type → list of offer names to remove
CHANNEL TYPES: FACEBOOK, INSTAGRAM, GOOGLE_ADS, LINKEDIN, MICROSOFT_ADS, REDDIT
EXAMPLES:
Remove a Lead Gen form from FACEBOOK and a Landing Page from GOOGLE_ADS:
remove_offers_from_campaign({
"campaign_id": 42545,
"channel_offers": {
"FACEBOOK": ["Demo Request Form"],
"GOOGLE_ADS": ["Pricing LP"]
}
})
INTEGRATION WITH OTHER TOOLS:
- Use get_campaign_by_wizard_id to inspect current offers per channel before removing
- Use search_campaigns_by_names to find the campaign ID| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The unique identifier of the campaign | |
| channel_offers | Yes | Map of channel type to list of offer names (Lead Gen form or Landing Page) to remove. Example: {"FACEBOOK": ["Demo Form"], "GOOGLE_ADS": ["Pricing LP"]} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations mark destructiveHint=true and readOnlyHint=false, but the description goes beyond by detailing exact behavior: on Channel-First/Native it clears offers from all native ads and drops empty containers, while on Precision/METADATA it uses legacy per-offer delete. It also warns about partial failures and instructs checking removal_results, disclosing response behavior without any contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description is well-structured with clear sections (WHEN TO USE, RESPONSE, REQUIRED PARAMETERS, CHANNEL TYPES, EXAMPLES, INTEGRATION). Every section adds necessary information, and the core purpose is front-loaded. No redundant or filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (nested object parameter, destructive nature, two campaign structures, no output schema), the description is fully complete. It covers behavior per structure, response format and error handling, parameter details, channel enums, and integration with related tools (get_campaign_by_wizard_id, search_campaigns_by_names). Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds substantial value: it explains the channel_offers mapping with an example, lists all valid channel types (FACEBOOK, INSTAGRAM, GOOGLE_ADS, etc.), and clarifies that offer IDs are resolved internally. This goes well beyond the bare schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Remove offers — Lead Gen forms OR Landing Pages — from one or more channels in an existing campaign.' It clearly distinguishes itself from siblings like remove_leadgen_offer_from_campaign and other remove_* tools by stating it handles both offer types and is the single offer-removal tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains an explicit 'WHEN TO USE' section with concrete conditions (removing a specific offer, cleaning up offers, multiple channels). It also names an alternative for single-container removal (add_and_edit_native_campaign_elements.modify_containers) and explains when not to use it, providing clear routing among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_target_groups_from_campaignRemove Targeting Groups from CampaignADestructiveInspect
Remove targeting groups from one or more channels in an existing campaign.
Use this tool to detach a named Targeting Group from a channel (e.g. remove
"Tech Decision Makers" from LINKEDIN). Channel + targeting-group IDs are resolved
internally — you only need the channel type and the targeting group name. (Targeting
groups are NOT audiences — to remove a standard audience use
remove_audiences_from_campaign.)
Works on both campaign structures. On a Channel-First / Native (N×N×N) campaign the
targeting group is cleared from its WizNativeAdContainer.targetingGroupId; any
container then left with no asset at all is dropped. On Precision/METADATA it uses the
legacy group delete.
KEYWORDS: remove, delete, targeting group, target group, channel, campaign
RESPONSE:
- Returns the refreshed campaign state plus a removal_results list with one
entry per requested removal recording its success or error. ALWAYS check
removal_results — a partial failure (e.g. one of two names not found) still
returns normally, so report only what actually came back successful.
REQUIRED PARAMETERS:
- campaign_id: Campaign ID (numeric identifier)
- channel_target_groups: Object mapping channel type → list of targeting group names
EXAMPLE:
remove_target_groups_from_campaign({
"campaign_id": 42545,
"channel_target_groups": {"LINKEDIN": ["Tech Decision Makers"]}
})| Name | Required | Description | Default |
|---|---|---|---|
| campaign_id | Yes | The unique identifier of the campaign | |
| channel_target_groups | Yes | Map of channel type to list of targeting group names to remove. Example: {"LINKEDIN": ["Tech Decision Makers"]} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation, the description discloses internal ID resolution, behavior on WizNativeAdContainer.targetingGroupId, container dropping when no asset remains, use of the legacy group delete on Precision/METADATA, and partial failure behavior. It also warns to always check removal_results, which is valuable operational transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections: purpose, usage guidance, structure-specific behavior, keywords, response notes, required parameters, and an example. Each section contributes essential information without unnecessary filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a destructive, nested-object operation with no output schema, yet the description covers invocation context, both internal campaign structures, required parameters, an example, and the response format including partial failure behavior. Nothing essential is missing for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value by explaining that channel and targeting-group IDs are resolved internally, so only channel type and targeting group name are needed, and by providing a concrete example that maps campaign_id and channel_target_groups.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Remove targeting groups from one or more channels in an existing campaign,' a specific verb plus resource that clearly states the operation. It also explicitly distinguishes targeting groups from audiences by naming remove_audiences_from_campaign, making sibling differentiation strong.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool and provides an exclusion: 'Targeting groups are NOT audiences — to remove a standard audience use remove_audiences_from_campaign.' It also explains that both campaign structures are supported and details how each is handled, giving agents clear contextual guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
render_flexible_creativeRender Flexible Creative to PNGADestructiveInspect
Flatten a layered flexible-creative document into a final PNG (rendered from the SAME layout the editor shows) and upload it to the creatives library. Returns the rendered image URL, the library image id, and pixel dimensions.
INTERNAL SAVE-PATH TOOL — invoked by the backend when the user clicks Save in the editor; not part of the chat generation flow. Renders the doc's background + text/CTA/logo/image layers so the flat image is pixel-identical to the editor preview.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional library name for the rendered image. Omit it and one is derived from the doc as `<brand-domain>-<channel>-<width>x<height>.png`, which is normally what you want. Must end in a file extension. | |
| design | Yes | The layered creative document to flatten (canvas, background, layers, brand) — the same JSON the editor edits. | |
| upload_to_library | No | Push the rendered PNG to the creatives library. Default: true. | |
| archive_library_image_id | No | Optional. The library image id this save supersedes (the creative's previous render). Archived on the platform ONLY after the new upload succeeds, so re-saving an editable creative retires the old PNG instead of piling up dead library images. Never affects an ad already built from it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds concrete behavior beyond the annotations: it both flattens the document and uploads the PNG to the creatives library, returns specific values, and guarantees the output is pixel-identical to the editor preview. It also labels itself as the internal save-path tool, adding workflow context not captured by the readOnly and destructive flags. No contradiction with the annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is front-loaded with the core action and result, then adds a short internal-context note. The only minor waste is that 'SAME layout the editor shows' and 'pixel-identical to the editor preview' express the same idea twice, but overall it is tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies the return contract (URL, image id, dimensions). It also gives the internal save-path context, the required design object is documented in the schema, and the archive/upload semantics are covered in the parameter descriptions, so an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 and the schema already defines all four parameters including defaults. The description's return-value statement is useful but does not add parameter-level meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete operation—flattening a layered flexible-creative document to PNG and uploading it—plus the exact return values (URL, image id, dimensions). It also distinguishes the tool from creative-generation siblings by labeling it the internal save-path render that matches the editor preview.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says this is invoked by the backend when a user clicks Save in the editor and states it is not part of the chat generation flow. It does not name a specific alternative tool, but the when/when-not context is clear enough for routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_linkedin_ad_library_linksResolve LinkedIn Ad Library Links to Metadata AdsARead-onlyInspect
Map LinkedIn Ad Library links (linkedin.com/ad-library/detail/), sponsoredCreative URNs or bare LinkedIn creative ids to the ads in this account's Metadata library, so an ad the user points at by its LinkedIn link can be REUSED in a new campaign instead of rebuilt.
WHAT IT CAN AND CANNOT RESOLVE (repeat this to the user when a link is not found):
- It resolves ONLY ads that were launched THROUGH METADATA. Every ad Metadata
publishes to LinkedIn is recorded with the LinkedIn creative id LinkedIn gave
it, and that id is exactly what the Ad Library link carries. Those come back
with the library ad (id, name, type) plus the experiment and campaign that ran
them, ready to attach by name.
- An ad launched natively in LinkedIn Campaign Manager (a sponsored personal
post, a Thought Leader ad, anything built outside Metadata) is NOT in the
library and CANNOT be imported from the link, by this tool or any other. The
only way to run it here is to rebuild it from its source files (image, video,
PDF) with the ad tools.
- LinkedIn only. Meta or Google ad library links are refused per item.
HOW IT SEARCHES: the platform has no lookup by LinkedIn creative id, so this scans
the account's LinkedIn ads newest first (100 per page, `max_pages` pages, default
20, so the newest 2,000 ads) and stops as soon as every id is found. A miss with
`reached_end: false` means the ad may simply be older than the scan: pass
`campaign_ids` to narrow the scan to the campaigns that ran it, or raise
`max_pages`. A miss with `reached_end: true` means the account never launched
that ad through Metadata.
PARAMETERS:
- links: Ad Library URLs, `urn:li:sponsoredCreative:<id>` URNs or numeric LinkedIn
creative ids (1 to 20 per call).
- campaign_ids: optional wizard campaign ids that restrict the scan.
- max_pages: optional, 1 to 50, default 20.
RETURNS: {success, found, not_found, scanned_ads, scanned_pages, reached_end,
results: [{input, linkedin_creative_id, found: true, library_ad: {id, name, type,
channel, status, image_url}, experiment: {id, name, goal}, campaign: {id, name,
status}, stats: {spend, impressions, clicks, leads}, destination_url, reuse} |
{input, linkedin_creative_id, found: false, reason}]}
NEXT STEPS: attach a found ad by its library NAME through create_campaign /
add_and_edit_campaign_elements (`ads.list`), or read it with
get_ad_details(ids=<library_ad.id>). Never re-upload a found ad's creative: that
creates a duplicate library entry.| Name | Required | Description | Default |
|---|---|---|---|
| links | Yes | LinkedIn Ad Library URLs, sponsoredCreative URNs, or numeric LinkedIn creative ids. | |
| max_pages | No | Pages of 100 LinkedIn ads to scan, newest first. Default 20. | |
| campaign_ids | No | Optional wizard campaign ids to restrict the scan to. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false, and the description adds detailed scanning behavior (100 per page, max_pages default 20, stops when found), explains reached_end semantics, and warns against re-uploading creatives. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear headers and front-loaded purpose, but it is lengthy. Each section adds value, though some redundancy (e.g., repeating the cannot-resolve message) could be trimmed. Still, organization is strong.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description provides a complete return structure, error conditions, next steps, and limitations. An agent has all necessary information to call this correctly, including parameter formats and default values.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all parameters, but the description adds specifics: link types (URL, URN, numeric id), count limits (1–20), max_pages range (1–50, default 20), and how campaign_ids restricts the scan. This goes beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Map') and resource ('LinkedIn Ad Library links' to 'Metadata library'), and distinguishes from siblings by explicitly refusing Meta or Google links and noting it is LinkedIn-only. It also clarifies that it resolves external IDs to library ads, setting it apart from search tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: to reuse an ad in a new campaign. Provides clear when-not: cannot import ads launched natively in LinkedIn Campaign Manager, and gives the alternative of rebuilding from source files. Also advises on passing campaign_ids and raising max_pages for misses.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_visitor_ipResolve Visitor IP to CompanyARead-onlyInspect
Deanonymize a website visitor IP to the COMPANY that owns it.
Company-level only (no person-level PII). Use for visitor-to-account attribution.
RETURNS: {resolved: bool, company?: {domain, name, employee_range, industry, city, state}}. Returns {resolved: false} when the IP can't be resolved or targeting is not configured.
| Name | Required | Description | Default |
|---|---|---|---|
| ip | Yes | The visitor's IP address (IPv4 or IPv6). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and destructiveHint annotations, the description discloses the exact return shape and the failure behavior: '{resolved: false} when the IP can't be resolved or targeting is not configured.' It also clarifies the privacy boundary by explicitly excluding person-level PII, which is important behavioral context for a deanonymization tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured, with the primary action front-loaded and separate RETURNS / failure sections. Every sentence adds either purpose, scope, or behavioral detail, with no filler or redundant restatement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read-only tool, the description covers the essential context: what it resolves, the company-level scope, the exact return shape, and when it returns false. Because there is no output schema, the explicit return contract is especially valuable. It could also mention prerequisites or related tools, but the given context is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully describes the single parameter 'ip' as an IPv4 or IPv6 address, so the description adds little new parameter-level detail. It does imply the IP should be a website visitor IP, but the schema carries the baseline burden and the description does not need to compensate for gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Deanonymize a website visitor IP to the COMPANY that owns it.' It clearly distinguishes itself from sibling tools by emphasizing company-level resolution for visitor-to-account attribution, so an agent knows exactly what this tool does even among many siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states the intended use case: 'Use for visitor-to-account attribution.' It also sets an exclusion boundary by noting 'Company-level only (no person-level PII),' which helps avoid misuse. It does not name alternative tools or state when not to use it, but the context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
restart_experiment_keywordRestart Experiment KeywordADestructiveInspect
Restart a specific paused keyword in an experiment.
PURPOSE:
Restart a keyword that was previously paused in an experiment. This re-enables the keyword
so it starts running again in the specified experiment.
SCOPE - THIS TOOL ACTS ON ONE KEYWORD, NOT ON THE EXPERIMENT:
It restarts a SINGLE keyword INSIDE an experiment. It cannot restart a paused
experiment. To pause or restart a WHOLE experiment, use manage_experiment instead.
WHEN TO USE:
- Restart a keyword that was previously paused in an experiment
- Re-enable a keyword after resolving performance issues
- Resume keyword activity in a specific experiment
PREREQUISITE:
Use list_experiment_keywords first to find the keywordExternalId and wizExperimentId
for the keyword you want to restart. Both come from that tool's results:
keywordExternalId identifies the keyword on the ad channel, and wizExperimentId
is the experiment's ID (the same ID search_experiments returns as experimentId).
WORKFLOW:
1. Search for the keyword: list_experiment_keywords(keywordOrExperimentName="my keyword")
2. Note the keywordExternalId and wizExperimentId from the results
3. Restart it: restart_experiment_keyword(keywordExternalId=12345, wizExperimentId=678)
4. (Optional) Verify later: list_experiment_keywords(keywordOrExperimentName="my keyword")
to check the status has changed
PARAMETERS:
- keywordExternalId: Required. The external ID of the keyword to restart (from list_experiment_keywords).
- wizExperimentId: Required. The experiment ID where the keyword is running (from list_experiment_keywords).
WARNING: This action changes the state of the keyword in the experiment.
The keyword will resume running in the specified experiment.
WARNING: ASYNC FLOW: Restarting a keyword is an asynchronous operation. The status change
may not be immediately reflected. Use list_experiment_keywords after some time
to verify the keyword status has been updated.| Name | Required | Description | Default |
|---|---|---|---|
| wizExperimentId | Yes | The experiment ID where the keyword is running. | |
| keywordExternalId | Yes | The external ID of the keyword to restart. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal mutation with destructiveHint=true and readOnlyHint=false, so the bar is lower. The description adds valuable context beyond annotations: the operation is asynchronous, status changes may be delayed, and verification via list_experiment_keywords is recommended.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections, but it contains redundancy: the PURPOSE section restates the opening sentence, the WHEN TO USE bullets repeat the same idea, and the PARAMETERS section duplicates the schema. It is useful but not every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a state-changing tool with no output schema, the description is highly complete: it covers prerequisites, identifier sourcing, workflow, async behavior, verification steps, and a clear exclusion for whole-experiment operations. An agent has enough information to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. The description adds meaning by explaining where to obtain both IDs (keywordExternalId and wizExperimentId from list_experiment_keywords) and clarifies which ID identifies the keyword versus the experiment.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Restart a specific paused keyword in an experiment.' It also clearly scopes the tool to a single keyword inside an experiment and explicitly distinguishes it from manage_experiment, which handles whole experiments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit 'WHEN TO USE' bullets, a prerequisite workflow, and names the alternative tool for whole-experiment operations. The description also tells the agent to use list_experiment_keywords first and how to verify the restart afterward.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retrieve_target_group_by_idRetrieve Target Group by IDARead-onlyInspect
Get detailed target group information by ID.
USE FOR: "get target group details for ID X", "show target group with ID Y", "check target group configuration", "show audiences in target group X", analyze setup before changes.
PREREQUISITE: If you don't have the ID, use list_target_groups(name="X") first.
RESPONSE: {id, name, channel, audiences, targeting, status, createdDate, modifiedDate, size, configuration, ...}
WORKFLOW: list_target_groups(name="target_group_name") → get ID → retrieve_target_group_by_id(target_group_id=ID)
| Name | Required | Description | Default |
|---|---|---|---|
| target_group_id | Yes | The unique ID of the target group to retrieve. Must be a positive integer. If you don't have the ID, use list_target_groups to search by name first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds context by stating the response includes specific fields (id, name, channel, audiences, etc.) and warns to 'analyze setup before changes', reinforcing it's a safe read operation. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with sections (USE FOR, PREREQUISITE, RESPONSE, WORKFLOW) and is front-loaded with the core purpose. Every sentence adds value, with no redundant phrasing. It is concise yet comprehensive for the tool's simplicity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has one simple parameter, no output schema, and a read-only annotation. The description fully covers how to obtain the required ID, what the response will contain, and the expected workflow. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema covers the single parameter 100% with a description that already includes the prerequisite to use list_target_groups. The tool description adds workflow examples but no additional semantic meaning about the parameter itself. Given full schema coverage, a baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Get detailed target group information by ID', which is a specific verb+resource+method. It distinguishes from siblings like list_target_groups (which lists all) and update_target_group (which modifies), so an agent can immediately identify this as a read-only lookup tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit USE FOR examples, a PREREQUISITE clause directing agents to list_target_groups when the ID is unknown, and a WORKFLOW showing the exact sequence of calls. This leaves no ambiguity about when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_ads_by_namesSearch Ads by NameARead-onlyInspect
Search for ads by name in the Metadata platform library, with pagination.
**USE THIS TOOL WHEN THE USER ASKS ABOUT:**
- Ad details, information, or status
- Finding an ad by name
- Getting ad IDs
- Checking if an ad exists
- Looking up ad creative assets (images, thumbnails)
- Ad type or channel information
- Any question containing words like: "ad", "creative", "show me", "find", "search", "image"
SEARCH FEATURES:
- Partial, case-insensitive matching on ad names
- Returns ad ID, name, channel type, ad type, status, and image URLs
- Three-state status filter via the `status` param (default
`"active"`, preserves the prior active-only behaviour):
* `"active"` → active ads only
* `"archived"` → archived (soft-deleted) ads only; use
this to find an ad id for `unarchive_ad`
* `"all"` → both active and archived in one response
PAGINATION:
- Supports `page` and `size` parameters (defaults: page=0, size=25).
- Page numbering starts at 0.
- Recommended size: 5-25 to keep responses LLM-friendly. Use up
to 100 only when the caller needs a wider sweep — large pages
can blow your context budget.
- Returned `total_elements` and `total_pages` are taken from the
platform's PageResponse so callers can drive a paginator.
- When `ad_names` carries multiple entries, the platform endpoint
accepts only ONE name per request — this tool fires one paged
request per name and merges results. `page`/`size` apply
PER-NAME, `total_elements` is the SUM across names, and
`total_pages` is the MAX across names. Single-name searches
get clean pagination semantics; multi-name is best-effort.
PARAMETERS:
- ad_names: Array of ad name strings to search for (required, ≥1)
- page: Zero-based page index (optional, default 0)
- size: Results per page (optional, default 25)
- sort: Spring sort clause (optional, default "createdDate,desc";
also valid: "id,desc", "name,asc", etc.)
- status: "active" (default) / "archived" / "all". Pick the
bucket you want; "archived" is the unarchive
discovery path, "all" is the rare both-buckets case.
RETURNS:
{
"found_ads": [
{
"id": 190084,
"name": "AI_Marketing_Audit_Q4_2025_Demo_LI_LI",
"channelType": "LINKEDIN",
"adType": "IMAGE",
"completionStatus": "COMPLETED",
"status": true,
"thumbnail": "https://...",
"imageUrl": "https://..."
}
],
"missing_names": ["NonExistent"],
"total_found": 1,
"page": 0,
"size": 25,
"sort": "createdDate,desc",
"total_elements": 1,
"total_pages": 1
}
CHANNEL TYPES: LINKEDIN, FACEBOOK, INSTAGRAM, GOOGLE, REDDIT, MICROSOFT_ADS
AD TYPES: IMAGE, VIDEO, CAROUSEL, TEXT
STATUS: true (active) or false (inactive)| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Zero-based page index (default: 0). Page numbering starts at 0. | |
| size | No | Results per page (default: 25, recommended max: 25). Larger windows blow LLM token budgets — only request more when the caller actually needs it. | |
| sort | No | Spring sort clause, e.g. 'createdDate,desc' (default), 'id,desc', or 'name,asc'. | |
| status | No | Which status bucket to return. 'active' (default) is the prior active-only behaviour. 'archived' returns ONLY archived (soft-deleted) ads, which is what you need to find an ad's id for unarchive_ad. 'all' returns both active and archived in one response. Maps to the platform's status query param semantics (Set<Boolean>): active=true, archived=false, all=omit. | active |
| ad_names | Yes | Array of ad names or partial names to search for (case-insensitive, partial matching) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, openWorldHint=false. The description adds substantial behavioral detail: pagination semantics (page starts at 0, size limits, context budget advice), status filter mapping to platform Set<Boolean> semantics, multi-name handling (per-name requests, merged results, sum/max for total_elements/total_pages), and the return structure. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (USE THIS TOOL, SEARCH FEATURES, PAGINATION, PARAMETERS, RETURNS, CHANNEL TYPES). It front-loads the purpose and usage. While verbose, each section adds distinct value and avoids redundancy. Slightly over-lengthy but appropriately organized, so a 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by providing a detailed RETURN example with field names and types, plus enumerations for channel types and ad types. It also explains edge cases (multi-name merging, status semantics, sort options). All necessary information for correct invocation is present, even for an agent unfamiliar with the platform.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description goes far beyond schema by adding: default values for page, size, sort, status; recommended size ranges (5-25, max 100); explanations of status enum meaning and platform mapping; multi-name pagination caveats; and a concrete return example with field types. This adds significant semantic value beyond the JSON schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Search for ads by name in the Metadata platform library' and then enumerates specific user intents (ad details, finding by name, getting IDs, checking existence, creative assets, type/channel info). It distinguishes from sibling tools like search_campaigns_by_names and search_library_creatives_by_name by scoping to ads specifically.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly lists 'USE THIS TOOL WHEN THE USER ASKS ABOUT:' with concrete scenarios and even mentions trigger words. It does not explicitly name alternative tools, but it provides a clear decision framework for when this tool is appropriate. Missing explicit 'when not to use' guidance, hence a 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_campaigns_by_namesSearch Campaigns by NameARead-onlyInspect
Search for campaigns by name to get campaign details, IDs, and status.
KEYWORDS: campaign, search, find, lookup, status, active, paused, draft, marketing, advertising
**USE THIS TOOL WHEN THE USER ASKS ABOUT:**
- Campaign details, information, or status
- Finding a campaign by name
- Getting campaign IDs
- Checking if a campaign exists
- Looking up campaign status (active, paused, draft)
- Any question containing words like: "campaign", "show me", "find", "search", "list", "details", "status"
**ALWAYS use this tool first** before launching, updating, or referencing any campaign.
SEARCH FEATURES:
- Partial, case-insensitive matching (e.g., "Q1" matches "Q1_2026_Campaign")
- Returns campaign ID, full name, and current status
- Searches up to 150 visible campaigns per term
PARAMETERS:
- campaign_names: Array of campaign name strings to search for (required)
RETURNS:
{
"found_campaigns": [
{
"id": 159490,
"name": "LinkedIn_BoFu_Q1_2026",
"statusLabel": "Active"
}
],
"missing_names": ["NonExistent"],
"total_found": 1
}
STATUS LABELS: Active, Paused, Draft, Completed, Unknown
Use returned campaign IDs with launch_campaign or manage_campaign tools.
Anchor all date-related decisions to the REAL current date — call get_current_date if you are not already certain what today is.| Name | Required | Description | Default |
|---|---|---|---|
| campaign_names | Yes | Array of campaign names or partial names to search for (case-insensitive, partial matching) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and non-destructive behavior. The description adds matching semantics (partial, case-insensitive), the 150-campaign visibility limit, possible status labels, and a precise return shape including missing_names. This is useful behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a crisp one-liner and uses clear headings, but it is bloated by a keyword list, a very broad 'any question containing...' trigger, and an unrelated note about anchoring date decisions to get_current_date. Several sentences restate information already in the schema or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only search tool, this is nearly complete: it documents matching behavior, limits, status enums, and the return payload even without an output schema. It does not discuss empty-result edge cases or distinguish itself from search_campaigns_by_utm_value, but these are minor gaps for the stated purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the array semantics, case-insensitivity, and partial matching. The description restates the parameter but adds no new meaning beyond an illustrative return example, so the baseline score applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb-resource pair: 'Search for campaigns by name to get campaign details, IDs, and status.' This clearly separates it from search_campaigns_by_utm_value and supplies the exact output fields. The text also lists concrete use cases rather than restating the tool name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit trigger conditions ('Use this tool when the user asks about...') and a strong precedence rule ('ALWAYS use this tool first') before launch/update actions. It lacks a direct 'when not to use' or named alternatives among siblings, but the decision context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_campaigns_by_utm_valueSearch Campaigns By UTM ValueARead-onlyInspect
Find campaigns whose UTM tracking parameters CONTAIN a given value - the only correct way to answer "which campaigns use / still say X in their UTMs".
KEYWORDS: utm, utms, utm_source, utm_medium, utm_campaign, utm_term, utm_content, tracking parameters, search utm, find utm, placeholder, UPDATE ME, audit
USE THIS TOOL WHEN THE USER ASKS:
- "Which campaigns still have UPDATE ME in their UTMs?"
- "Which campaigns tag utm_source as <something>?"
- Any audit of UTM VALUES across campaigns.
CRITICAL - DO NOT ANSWER THIS FROM CAMPAIGN NAMES. Campaign names, experiment
names and tags do not contain UTM values. Searching them returns nothing and
produces a confident WRONG "no campaigns found" - the exact failure this tool
was built to end. If this tool errors or is unavailable, say you cannot check
rather than falling back to a name search.
INHERITANCE RULE - READ BEFORE ANSWERING ANY UTM QUESTION:
UTMs are inherited, never blank. A campaign channel with an empty stored
mapping does NOT have "no UTMs" - it tracks with the account's UTM defaults,
and where the account set nothing it tracks with the Metadata platform default.
Roughly half of all channel rows in production are in that inherited state.
NEVER report "no UTMs configured" from an empty stored field: report the
resolved value and its origin.
ORIGIN IS PER CHANNEL, not per key: a channel with an empty stored mapping
inherits the account default whole, so a channel whose resolved mapping differs
at all from that is stored on the campaign and every one of its values is an
override. The per-key `same_as_default` flag says whether that one key happens
to match the default anyway.
ORIGIN VALUES:
- campaign_override: stored on this campaign channel, differs from what it would inherit.
- account_default: inherited from this account's UTM defaults.
- platform_default: inherited from the Metadata-wide default (account set nothing).
- not_set: the channel really has no UTM mapping (non-sponsored channels only).
HONEST LIMIT: a campaign that stores a mapping identical to the default it
would inherit is reported as inherited. The platform returns resolved values
with no provenance, so that case cannot be distinguished - say so rather than
claiming the campaign has no override.
The match is a case-insensitive SUBSTRING over each enabled channel's EFFECTIVE
(post-inheritance) UTM value, so a campaign that inherits a matching account
default is returned too - which is correct, that is what it actually tracks with.
It matches VALUES, not keys: searching "utm_source" finds nothing.
MINIMUM 3 CHARACTERS. A shorter value is refused rather than sent, because the
platform ignores a sub-minimum filter and would return the whole campaign list,
which reads as "everything matches".
Optional filters mirror list_wizard_campaigns: page, size, sort_by, sort_order,
status (Draft, Launched, Finished), experiment_statuses, visibility, name.
RESPONSE SHAPE: same as list_wizard_campaigns -
{"totalElements": 20, "totalPages": 1, "data": [{"id": 173290, "name": "...", "status": "Launched", ...}]}
The rows do NOT include the matching UTM value. To show WHICH parameter matched,
call get_campaign_utms on the campaigns returned.
Page through until the returned rows cover totalElements before reporting a count.
READ-ONLY, current account only.| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Optional: additional server-side campaign name substring filter. | |
| page | No | 0-based page index. Default: 0 | |
| size | No | Results per page. Default: 25 | |
| status | No | Campaign-level status filter. Comma-separated subset of Draft, Launched, Finished. Omit to include all three. | |
| sort_by | No | Field to sort by. Default: createdDate | |
| utm_value | Yes | Case-insensitive substring to look for in the campaigns' effective UTM values (e.g. 'UPDATE ME'). Minimum 3 characters. | |
| sort_order | No | Sort order. Default: desc | |
| visibility | No | Optional: filter by campaign visibility. Omit to include all. | |
| experiment_statuses | No | Experiment-level status filter. Comma-separated subset of Active, WithoutSpend, Paused, Completed, Failed. Omit to include all five. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and non-destructive, but the description adds substantial behavioral context: effective post-inheritance matching, the three-origin model, the minimum-3-characters refusal, the honest limit about indistinguishable defaults, the response omitting matched values, and pagination behavior. These are exactly the details an agent cannot infer from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but organized with bolded headers and every block adds non-obvious knowledge: critical warning, inheritance rule, origin values, honest limit, matching semantics, and response shape. It is not lean, but it is front-loaded and free of filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, it provides the exact response shape, tells the agent to call get_campaign_utms on returned campaigns to show which parameter matched, and instructs paging until totalElements is covered. For a tool with inherited-state complexity, this is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers all 9 parameters at 100%, so baseline is 3; the description adds meaningful semantics for utm_value: case-insensitive substring over effective values, matches values not keys, and minimum 3 characters. It also explains that optional filters mirror list_wizard_campaigns and clarifies pagination semantics via totalElements.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Find campaigns whose UTM tracking parameters CONTAIN a given value') and distinguishes itself from search_campaigns_by_names by warning that campaign names do not contain UTM values. The 'only correct way' phrasing makes its niche unmistakable among many search-related siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly lists trigger phrasings ('Which campaigns still have UPDATE ME in their UTMs?') and provides a critical do-not-use rule: never answer from campaign names. It also tells the agent to say it cannot check rather than falling back to a name search if this tool errors.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_experiment_recipesSearch Campaign RecipesARead-onlyInspect
Find proven CAMPAIGN CONFIGURATIONS to build from — combinations of channel, ad format, audience type, bid strategy and budget band that have run together successfully across multiple advertisers.
USE THIS WHEN you are composing a campaign and need to decide HOW to build it: which channel and format pairing, what kind of audience, which bid strategy, roughly what daily budget. It answers "what should I build", not "how is my account performing".
DO NOT USE IT for cohort performance questions ("what's the median CPL
for my industry", "how do we compare to similar companies") — that is
query_metadata_analytics_benchmarks. Do not use it for the caller's own
campaign history — that is query_metadata_analytics_account.
Every returned recipe is backed by at least five distinct advertisers. Recipes below that floor are suppressed rather than returned, so an empty result means "no configuration is proven enough to recommend here", NOT "no data exists". Say so plainly rather than substituting a guess.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Natural-language description of the campaign you are building, e.g. "lead gen campaign targeting IT decision makers", "top of funnel awareness push for a new product launch". | |
| channel | No | Optional exact filter — "linkedin", "facebook", "google_ads", "instagram". Omit to search every channel. | |
| ad_format | No | Optional exact filter — "image", "video", "document", "carousel", "text". | |
| num_results | No | How many recipes to return (default 5). | |
| bid_strategy | No | Optional exact filter, e.g. "auto_bid", "manual_bid", "metadata_bid_agent". | |
| audience_type | No | Optional exact filter, e.g. "firmographic_include", "linkedin_retargeting", "native_targeting_dynamic". |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already mark this as read-only and non-destructive, and the description adds meaningful behavior beyond that: every recipe is backed by at least five distinct advertisers, sub-threshold recipes are suppressed, and an empty result means 'not enough proven data' rather than 'no data exists'. It even instructs the agent to report this plainly instead of guessing, which is high-value behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every section earns its place: definition, when-to-use, when-not-to-use with named alternatives, and empty-result semantics. It is front-loaded with the core purpose and uses clear paragraph breaks and capitalization to aid scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only search tool with an output schema, the description covers purpose, selection criteria, exclusions, and the meaning of empty results. Nothing needed to call the tool correctly is missing, and the output schema handles return-value details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the structured schema already documents every parameter and even gives query examples. The description reinforces the semantic theme by listing channel, ad format, audience type, bid strategy, and budget band as the dimensions of a recipe, but it does not add per-parameter detail beyond what the schema provides. Baseline 3 is appropriate because the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Find proven CAMPAIGN CONFIGURATIONS to build from') and immediately clarifies the scope: combinations of channel, ad format, audience type, bid strategy, and budget band. It explicitly distinguishes itself from sibling analytics tools, so an agent can tell it apart from query_metadata_analytics_benchmarks and query_metadata_analytics_account without opening their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit USE THIS WHEN guidance tied to composing campaigns and deciding how to build them, plus a crisp framing: answers 'what should I build', not 'how is my account performing'. It names the exact sibling tools for the cases it should NOT be used for, leaving no ambiguity about routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_experimentsSearch ExperimentsARead-onlyInspect
Search for experiments by name, status, and budget group with flexible filtering.
KEYWORDS: experiment, search, find, ad, test, status, active, paused, performance, campaign
WHEN TO USE:
- User wants to "find experiment X"
- User asks to "show experiments for campaign Y"
- User requests to "search for experiments matching Z"
- User wants to "see all experiments with name containing A"
- User asks "what experiments are in campaign B?"
- User asks "what is the ID of experiment C?"
- User wants to "find experiments in budget group X"
- User asks to "search experiments in specific budget groups"
- User wants to "show all active experiments"
- User asks "list paused experiments"
- User wants to "find experiments with status X"
PURPOSE:
This tool searches across all experiments with flexible filtering options.
You can search by name (partial, case-insensitive), filter by budget groups, and filter by status.
All filters are optional - use any combination to narrow down results.
SEARCH CAPABILITIES:
- Search by experiment name: Returns experiments with matching names
- Search by campaign name: Returns all experiments from campaigns with matching names
- Filter by budget groups: Narrow results to specific budget group IDs
- Filter by status: Show experiments with specific statuses (Active, Paused, etc.)
- Partial matching: Search term doesn't need to be exact
- Case-insensitive: "Test" matches "test", "TEST", "TeSt"
STATUS VALUES EXPLAINED:
- Active: Currently running and spending budget
- WithoutSpend: Running but not currently spending budget
- Paused: Temporarily stopped, can be restarted
- Completed: Finished (reached end date or completion criteria)
- Failed: Encountered an error during execution
- Disconnected: Connection to ad channel was lost
RETURN EXPERIMENT DATA FIELDS:
- experimentId, experimentName, wizCampaignId, wizCampaignName
- campaignGroup, statusLabel, dailyBudget, spent, impressions, clicks
- startDate, endDate| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (default: 0) | |
| size | No | Number of results per page (default: 5) | |
| sort | No | Sort criteria in format 'field,direction' (e.g., 'name,asc') | |
| search_name | No | The experiment or campaign name to search for (partial, case-insensitive matching). Optional - omit to skip name filtering. | |
| budget_group_ids | No | Optional array of budget group IDs to filter experiments. Only returns experiments that belong to these budget groups. | |
| launched_experiment_statuses | No | Optional array of experiment statuses to filter by. Valid values: Active, WithoutSpend, Paused, Completed, Failed, Disconnected |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and non-destructive safety, so the description need not repeat that. It adds meaningful behavioral details: partial and case-insensitive matching, plain-English meanings for each status value, and a list of returned data fields. These go beyond both the annotations and the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear section headings and bullet points, but the WHEN TO USE list is repetitive (e.g., 'find experiment X' and 'find experiments in budget group X' are nearly identical), and the KEYWORDS section is redundant with the rest. Could be trimmed by about a third without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all functional aspects: filters, combination of filters, status value meanings, and returned fields, which is especially valuable since there is no output schema. It omits pagination/sorting default behavior, but those parameters are already documented in the schema, so this is only a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value by explaining status semantics (e.g., 'WithoutSpend – running but not spending budget'), clarifying that filters are optional and combinable, and illustrating how budget group filtering works. This enriches the minimal schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb and resource: 'Search for experiments by name, status, and budget group.' It distinguishes from sibling tools like search_campaigns_by_names by explicitly targeting experimentsholistically and enumerating the exact filter dimensions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
An extensive WHEN TO USE section lists concrete user phrasings ('find experiment X', 'show active experiments') that map directly to this tool. It lacks explicit when-not-to-use guidance or named alternatives, but the examples are specific enough to disambiguate from siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_insights_criteria_fieldsSearch Insights Criteria FieldsARead-onlyInspect
Discover the fields an Insights (Spotlight) account-journey segment can filter on: the exact field names, their type, the operators each accepts, and the picklist options.
USE BEFORE create_segment, and before get_insights_report when you filter it. Omit search_keywords to get the whole catalog in compact form; pass keywords to narrow it (matched against field names and labels: "impressions", "score", "visits", "pricing", "opportunity").
WHAT A SEGMENT FILTERS: the companies in the account's Spotlight journey, one row per company, with engagement metrics that are computed INSIDE the lookback window the audience is later created with (create_audience_from_segment.lookback_window). Needs the Insights (Spotlight) subscription on the account: without it the catalog comes back empty or the call fails, and the right move is to say so, not to guess fields.
STATIC FIELDS (always present; use the NAME in criteria):
Marketing touchpoints: LINKEDIN_IMPRESSIONS (NUMERIC), LINKEDIN_ADS_ENGAGEMENT (NUMERIC, LinkedIn clicks), FORM_SUBMISSIONS (NUMERIC), CHANNEL (MULTIPICKLIST: LINKEDIN, FACEBOOK, GOOGLE_ADS, INSTAGRAM, EMAIL, THIRD_PARTY, DIRECT), HIGH_INTENT_PAGES (BOOLEAN)
Website engagement: WEBSITE_VISITS, TOTAL_PAGE_VIEWS, UNIQUE_VISITORS (NUMERIC), PAGE_URL (STRING; LIKE "/pricing" is the page-visit filter), IDENTIFIED_VISITORS (BOOLEAN), IS_ABM (BOOLEAN), UTM_SOURCE / UTM_MEDIUM / UTM_CAMPAIGN / UTM_TERM / UTM_CONTENT / UTM_KEYWORD / REFERRER (ARRAY)
Engagement score: SCORE (MULTIPICKLIST classification), CONFIDENCE_SCORE and TREND (MULTIPICKLIST)
CRM: ACCOUNT_STATUS (opportunity status, MULTIPICKLIST), IN_CRM (BOOLEAN), ACCOUNT_OWNER (MULTIPICKLIST); HubSpot adds DEAL_TYPE and DEAL_STAGE; Salesforce adds EMAILS, CALLS, EVENTS (NUMERIC), CAMPAIGN_NAME, CAMPAIGN_TYPE, CAMPAIGN_MEMBER_STATUS, RESPONDED; any connected CRM adds DYNAMIC fields (criterion field "DYNAMIC" plus entity and property)
Firmographic: INDUSTRIES, REVENUES, EMPLOYEES, COUNTRIES (MULTIPICKLIST), COMPANY_DOMAIN, COMPANY_NAME (STRING), ACCOUNT_LIST (MULTIPICKLIST of the account's ABM lists)
RESPONSE: {fields: [{name, label, criteria_fields: [{name, label, type, operators, options (first 10), options_total, dynamic?, entity?, status?}]}], missing_crm_fields, criteria_rules}. criteria_rules restates the value shape per type. A dynamic field with status PENDING is still being extracted from the CRM and cannot be used yet.
| Name | Required | Description | Default |
|---|---|---|---|
| search_keywords | No | Optional keywords matched against field names and labels, e.g. ['impressions', 'score']. Omit for the whole catalog. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the call read-only and non-destructive, and the description adds substantial behavioral context: it requires the Insights (Spotlight) subscription, warns that the catalog can come back empty or the call can fail without it, and explains that dynamic fields with status PENDING are not yet usable. It also discloses the response shape, going well beyond the annotation baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although long, the description earns its length: purpose is front-loaded, followed by usage sequencing, subscription prerequisites, a categorized static-field catalog, and response shape. The bullet grouping and section labels make the volume of information scannable and actionable, with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has only one optional parameter, no output schema, and no enums, so the description carries the full burden. It covers the response contract, field categories, per-field types, operator implications, subscription preconditions, and dynamic-field status. An agent has everything needed to call it correctly and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already describes search_keywords as 'Optional keywords matched against field names and labels, e.g. ['impressions', 'score']. Omit for the whole catalog,' and the description largely restates this. With 100% schema description coverage, the baseline is 3, and the description adds no material new meaning about the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Discover the fields an Insights (Spotlight) account-journey segment can filter on.' It names exactly what the tool returns (field names, types, operators, picklist options) and distinguishes it from siblings like get_insights_report and create_segment. The scope is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'USE BEFORE create_segment, and before get_insights_report when you filter it,' giving concrete sequencing guidance. It also explains when to omit vs. pass search_keywords and instructs the agent to say the subscription is missing rather than guess fields. This is exemplary usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_library_creatives_by_nameSearch Creative Library (Images, Videos, GIFs, Documents)ARead-onlyInspect
Search or list creative assets in the library by name, across ALL content types — images, videos, GIFs and documents. Returns detailed information about matching assets with pagination support.
KEYWORDS (for tool discovery): search creative library, list video creatives,
find videos, list uploaded videos, browse video library, search videos by name,
list all creatives, find creative by id, look up creative id, list documents,
list GIFs, library assets, video assets, creative assets, list creatives by type.
This is the general-purpose library search/list tool for every content
type — there is no separate "list videos" or "get library items" tool.
WHEN TO USE:
- Find specific creatives by name in the library
- List all creatives in the library (when creativeName is omitted)
- Search for creative assets with partial name matching
- Filter by content type (IMAGE, VIDEO, GIF, DOCUMENT)
- Locate creatives for use in ad creation
- Verify creative asset availability before campaign setup
- Get creative metadata and IDs for asset management
- Browse through paginated results
SEARCH BEHAVIOR:
- Supports partial name matching when creativeName is provided
- Case-insensitive search
- Returns all creatives matching the search term
- Automatically URL encodes the search name
- When creativeName is omitted, returns all creatives in the library
- Supports optional content type filtering (IMAGE, VIDEO, GIF, DOCUMENT)
- Use lower number in the size parameter. Preference for 5 or 10 max.
PAGINATION:
- Supports pagination with `page` and `size` parameters.
- Defaults: page=0, size=10 (server-side default in
`MetadataAPIClient.search_library_creatives_by_name`).
- Page numbering starts at 0.
- The platform returns Spring `PageResponse` shape
(`totalElements`, `totalPages`, `data`) so callers can
drive a paginator off the response.
- Recommended size: 5-10 to keep LLM responses manageable.
Larger windows (up to ~25) are accepted; anything beyond
blows token budgets fast.
- `sort` takes a Spring `field,direction` clause and defaults
to `id,desc`. Sort on `labelName` for the display name;
`name` holds the generated UUID.
RETURNED DATA:
- Creative asset ID and name
- File properties (size, dimensions, format)
- Upload and modification timestamps
- Visibility status and permissions
- Preview URLs and download links
- Associated metadata and tags
- Pagination metadata (total count, page info)
USE CASES:
- "List all images in the library"
- "Find all images with 'product' in the name"
- "Search for logo images in the library"
- "Get image ID for 'campaign-hero-banner.jpg'"
- "Find all images uploaded for the Q4 campaign"
- "Browse images page by page (page=0, size=5)"
- "List only videos: contentTypes=VIDEO"
- "Filter for images and videos: contentTypes=IMAGE,VIDEO"
- "Get all documents: contentTypes=DOCUMENT"
- "Find all asset types: contentTypes=IMAGE,VIDEO,GIF,DOCUMENT"
NOTE: This is the single tool for searching/listing ALL creative asset
types. To restrict to a type, pass contentTypes (e.g. VIDEO for videos
only); omit it to return every type. Use fetch_creative_details when you
already have a specific creative id and want its full metadata.| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Zero-based page index (default: 0). | |
| size | No | Results per page (default: 10, recommended max: 10). Larger windows blow LLM token budgets — only request more when the caller actually needs it. | |
| sort | No | Spring sort clause, 'field,direction' (default: 'id,desc'). The platform binds a full Pageable to this endpoint, so any ImageLibrary column works: labelName, createdDate, contentType, sizeInKb, width, height, status, id. WARNING: sort on labelName for the display name. 'name' holds the generated UUID that doubles as the S3 object key, so sorting on it produces an order no person can read. | |
| contentTypes | No | Filter by content types (comma-separated). Supported values: IMAGE,VIDEO,GIF,DOCUMENT. Example: IMAGE,VIDEO or IMAGE%2CVIDEO%2CGIF%2CDOCUMENT | |
| creativeName | No | Name or partial name of the creative to search for. Supports partial matching and is case-insensitive. Omit to list all creatives. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral context beyond that: case-insensitive partial matching, automatic URL encoding, server-side pagination defaults (page=0, size=10), Spring PageResponse shape, sort default id,desc, and a warning about sorting on labelName vs the UUID field. It also cautions about token budgets for large sizes. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely verbose, containing a large KEYWORDS discovery block, extensive USE CASES examples, and repeated information (e.g., contentTypes is described three times). While it is front-loaded with the core purpose, the overall length is excessive for an agent selecting and using the tool, and several sections (KEYWORDS, repetitive USE CASES) do not earn their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite the verbosity, the description is thorough: it covers search behavior, pagination shape and defaults, sorting nuances, returned data fields, and use cases. It even references fetch_creative_details as an alternative. Given the tool complexity and no output schema, the description provides enough for an agent to call it correctly. Minor omissions like error handling or permissions are not critical for a read-only search tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description does add extra guidance like 'Recommended size: 5-10' and reminds that sort on labelName is the display name, but these are largely behavioral or advisory rather than new parameter semantics. Most parameter meaning (partial matching, contentTypes values, defaults) is already in the schema descriptions, so the description adds only marginal value beyond that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches or lists creative assets by name across all content types (images, videos, GIFs, documents). It explicitly distinguishes itself from sibling tools like fetch_creative_details and asserts it is the general-purpose library search/list tool with no separate list/video tool, so an agent can correctly determine its scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'WHEN TO USE' section lists eight specific scenarios (find by name, list all, filter by type, etc.) and the NOTE explicitly tells the agent to use fetch_creative_details when a specific creative id is already held. This provides clear when-to-use guidance and names the alternative, exceeding basic expectations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_linkedin_engagement_sourcesSearch LinkedIn Engagement SourcesARead-onlyInspect
Find which LinkedIn campaigns or pages to retarget, for a chosen engagement source type. STEP 2 of the LinkedIn Engagement Retargeting flow.
Each result's `id` is the LinkedIn URN to pass as `engagement_source_urns` to
create_linkedin_engagement_retargeting_audience. The audience will contain people who
engaged with the sources you select, so this choice determines who is in it.
REQUIRED FIRST: call get_linkedin_engagement_source_types and pick an
`engagementSourceType` plus an `engagementTrigger`.
**ALWAYS PASS engagement_trigger AND lookback_window_days TOGETHER.** With both, every
candidate carries `engagementCount`, the volume of engagement behind it, sorted
highest-first — which is the only way to tell which sources are worth retargeting.
Without the pair the platform returns no counts and the order is not meaningful.
Use the same trigger and lookback you intend to create the audience with, or the
numbers describe a different audience than the one you are about to build.
DO NOT CALL THIS FOR THE WEBSITE SOURCE TYPE. Website retargeting is defined by URL
match rules, not by picking sources, and this tool refuses it. Go straight to the
create tool with `page_set_name` and `url_match_groups`.
READING THE RESULTS:
- `id` — the LinkedIn URN (e.g. `urn:li:sponsoredCampaign:743409464`). Pass it
verbatim. It is NOT the numeric campaign id and must never be reconstructed.
- `name` — the campaign or page name, for telling the user what you picked.
- `engagementCount` — how many engagements that source drew under the trigger and
lookback you passed. Absent when you did not pass both.
- `engagementMetricLabel` / `engagementMetric` — WHAT was counted, which follows the
trigger: "Total Engagement" for an any-interaction trigger, "Opens" for a
conversation open, clicks for a chargeable-click one. Quote this label when you
report numbers, so "1,200 opens" is not reported as impressions.
- `status` — the campaign's state. `PENDING_DELETION` campaigns still appear and are
still valid engagement history, but prefer live ones when both have volume.
ORGANIZATION_PAGES candidates carry no status; that is normal, not missing data.
HOW TO CHOOSE:
- Prefer sources with real `engagementCount`. A source with 0 builds an audience
that will stay empty however long LinkedIn is given.
- Selecting several sources is normal and usually right: the audience is the UNION of
everyone who engaged with any of them, so more sources means more reach.
- IF EVERY CANDIDATE SHOWS 0, do not silently build from all of them. That means the
account has no engagement of this kind in the window. Say so, and offer the real
options: a longer lookback, a shallower trigger, a different source type, or
waiting until campaigns have run. Building anyway produces an empty audience the
user will believe is populated.
- Only the top `limit` results come back, not the whole account. Narrow with `search`
rather than assuming the list is complete.
WHEN TO USE:
- After picking a source type, to find what can be retargeted
- "Which of my video campaigns got the most engagement?"
- "Find my lead gen form campaigns"
- To resolve a campaign the user named to its URN, via `search`
PARAMETERS:
- engagement_source_type: an `engagementSourceType` from step 1 (required).
WEBSITE is not valid here.
- engagement_trigger: a trigger valid for that source type. Pass it WITH
lookback_window_days to get engagement counts and a meaningful order.
- lookback_window_days: 30, 60, 90, 180 or 365. Pairs with engagement_trigger.
- search: narrow by name, case-insensitive substring. Use it when the user named a
campaign, or when the account has many campaigns.
- limit: how many to return (default 12, max 100).
RETURNS:
- sources[]: the candidates, as described above
- engagementMetricLabel: what the counts measure
- count: how many came back
- next_step: which tool to call next
IMPORTANT NOTES:
- ORGANIZATION_PAGES returns exactly one candidate, the account's own company page.
That is the whole result set, not a truncated one.
- An empty `sources` list means the account has nothing of that type. Report that and
suggest a different source type rather than retrying the same call.| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many candidates to return. Default 12, max 100. Results are the TOP N by engagement, not the whole account. | |
| search | No | Narrow candidates by name (case-insensitive substring). Use when the user named a specific campaign, or when the account has more campaigns than `limit`. | |
| engagement_trigger | No | An `engagementTrigger` valid for this source type. Pass together with lookback_window_days to get `engagementCount` per candidate, sorted highest-first. Use the same trigger you will create the audience with. | |
| lookback_window_days | No | Window the engagement counts are measured over. Pass together with engagement_trigger, and use the same value you will create the audience with. | |
| engagement_source_type | Yes | An `engagementSourceType` from get_linkedin_engagement_source_types (e.g. VIDEO_ADS, SINGLE_IMAGE_ADS, DOCUMENT_ADS, CONVERSATION_ADS, LEAD_GEN_FORMS, ORGANIZATION_PAGES). WEBSITE is not valid here — it has no sources to pick. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/non-destructive annotations, the description discloses meaningful behaviors: the tool refuses WEBSITE, returns only the top `limit` results, omits `engagementCount` when trigger/lookback are not paired, returns exactly one candidate for ORGANIZATION_PAGES, and treats empty sources as a real absence of engagement data. Nothing contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with clear headings, scannable bullets, and front-loaded constraints. Every section contributes operational guidance rather than restating boilerplate, and the length is justified by the number of edge cases an agent must get right.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully compensates by documenting each result field, explaining edge cases like PENDING_DELETION and ORGANIZATION_PAGES, and naming the `next_step` tool. Nothing needed to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even with 100% schema coverage, the description adds critical semantics the schema cannot convey: the two-parameter pairing requirement, URN vs numeric id distinction, WEBSITE invalidity, and the intended use of `search` when a user names a campaign. This goes well beyond baseline schema documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find which LinkedIn campaigns or pages to retarget, for a chosen engagement source type' and positions it as STEP 2 of an explicit flow. It also names the adjacent create_linkedin_engagement_retargeting_audience tool, so an agent can distinguish this search step from the audience-creation step.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to call get_linkedin_engagement_source_types first, gives concrete query examples, and states a hard exclusion: DO NOT CALL THIS FOR THE WEBSITE SOURCE TYPE, routing instead to the create tool. It also instructs the agent to use the same trigger/lookback as the audience it will build and how to handle all-zero results.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_reddit_criteriaSearch Reddit Target Group CriteriaARead-onlyInspect
Get available Reddit targeting criteria and their reference values (externalId + name) for target group creation.
USE FOR: "what Reddit communities match X?", "search Reddit interests/keywords", "find subreddits about Y", get valid references before create_reddit_target_group, resolve location countries/states for Reddit.
CRITERIA TYPES:
communities: Search subreddits/communities by name (requires search_terms)
interests: Search Reddit interest categories (requires search_terms)
keywords: Search contextual keywords (requires search_terms)
locations: Country/state options for the mandatory LOCATION criterion (search_terms optional; omit to list all)
RESPONSE: For communities/interests/keywords, a paginated {content: [{externalId, name}]} — use externalId in the COMMUNITIES/INTERESTS/KEYWORDS criteria. For locations, {countries, states, regions} where each item has a numeric id — put that numeric id (NOT the object) into the LOCATION criterion's countries/states arrays.
WORKFLOW: search_reddit_criteria → build targeting (LOCATION first) → create_reddit_target_group
| Name | Required | Description | Default |
|---|---|---|---|
| search_terms | No | Search keywords (min 2 characters). Required for communities/interests/keywords. Example: ['technology'] | |
| criteria_type | Yes | Type of Reddit criteria to search. communities/interests/keywords require search_terms; locations returns countries/states (search_terms optional). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and non-destructive annotations, the description discloses important runtime behavior: paginated response for communities/interests/keywords, the exact shape {content: [{externalId, name}], the locations response {countries, states, regions}, and the warning to use the numeric location id rather than the object. This is behavior an agent could not infer from annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well structured with clear labeled sections: USE FOR, CRITERIA TYPES, RESPONSE, and WORKFLOW. Every sentence carries operational value, from the use-case examples to the pagination note, with no filler or repetition of annotation data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only 2 params and no output schema, the description fully compensates: it documents the required search_terms per criteria type, the exact response shapes for each branch, how to use externalId vs numeric id, and how the tool fits into the create_reddit_target_group workflow. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers the parameters at 100%, including criteria_type enums and the search_terms requirement note. The description adds extra semantics beyond the schema: which response shape each param value yields, that search_terms should be omitted to list all locations, and that the returned numeric id (not the object) is what goes into the LOCATION criterion.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb ('Get available Reddit targeting criteria') and the resource, plus the purpose: returning externalId + name reference values for target group creation. The USE FOR examples ('what Reddit communities match X?', 'find subreddits about Y') clearly distinguish this as a Reddit lookup tool distinct from generic siblings like search_target_group_criteria and create_reddit_target_group.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage guidance: use it before create_reddit_target_group, with the workflow 'search_reddit_criteria → build targeting (LOCATION first) → create_reddit_target_group'. It also explains when search_terms is required versus optional per criteria_type, and for locations it says 'omit to list all, which tells the agent exactly when each variant applies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_target_group_criteriaSearch Target Group CriteriaARead-onlyInspect
Get available criteria and their supported values (names and IDs) for target group creation/updates.
USE FOR: "what targeting criteria are available?", "what options for [criteria type]?", "supported values for industries/seniority/job functions", "how to search job titles/interests/member groups?", validate criteria before creating target group, get valid IDs for create_target_group.
CRITERIA TYPES:
LIST-BASED (returns predefined options):
age-ranges: Age range options
company-categories: Company classifications
company-growth-rates: Growth rate ranges
revenues: Revenue ranges
employees: Employee count ranges
industry-taxonomy: Industry codes/names
jobFunctions: Job function categories
seniority: Seniority levels
followed-companies: Company follow options
locations: Geographic data (MANDATORY as FIRST criteria for LinkedIn) - use search_terms for filtering
SEARCH-BASED (use search_terms):
job-title: Search job titles (reference_type: LINKEDIN_JOB_TITLES)
member-groups: Search LinkedIn groups (reference_type: LINKEDIN_MEMBER_GROUPS)
member-skills: Search professional skills
interests: Search interests (reference_type: LINKEDIN_INTERESTS)
traits: Search behaviors (reference_type: LINKEDIN_TRAITS)
NUMERIC: years-of-experience (0-12, not retrieved via this tool)
OPERATION MODES:
List: search_target_group_criteria(channel="LINKEDIN", criteria_type="seniority")
Search: search_target_group_criteria(channel="LINKEDIN", criteria_type="job-title", search_terms=["engineer"], exact_match=false)
Direct: search_target_group_criteria(channel="LINKEDIN", reference_type="LINKEDIN_JOB_TITLES", search_terms=["engineer"])
RESPONSE: Array of {externalId, name}. Use externalId in target group config, show name to users.
CHANNEL: Only LINKEDIN supported.
| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | The advertising channel for which to retrieve criteria. Only LINKEDIN is supported. | |
| exact_match | No | Whether to require exact matches in search (default: true). Set to false for broader/fuzzy matching. | |
| search_terms | No | Array of search keywords for search-based criteria (job-title, member-groups, interests, traits). Example: ['engineer', 'developer'] | |
| criteria_type | No | Type of targeting criteria to retrieve or search. List-based (returns predefined options): - age-ranges: Age range segments - company-categories: Company type classifications - company-growth-rates: Company growth classifications - revenues: Company revenue ranges - employees: Employee count ranges - industry-taxonomy: Industry classification - jobFunctions: Job function categories - seniority: Seniority levels - followed-companies: Company follow options - locations: Geographic locations (countries, states, cities) - MANDATORY as first criteria for LinkedIn Search-based (requires search_terms): - job-title: Search job titles - member-groups: Search LinkedIn groups - member-skills: Search LinkedIn member skills - interests: Search interests/topics - traits: Search behaviors/characteristics | |
| reference_type | No | Specific reference type for search operations (LinkedIn only). Auto-determined from criteria_type and channel if not provided. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral detail: it specifies the response format (array of {externalId, name}), instructs to use externalId in config and show name to users, notes that locations must be the first criteria for LinkedIn, and mentions that years-of-experience is numeric and not retrieved via this tool. These details go well beyond the annotations and inform the agent's expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense but well-structured with clear headings (USE FOR, CRITERIA TYPES, OPERATION MODES, RESPONSE, CHANNEL) and bullet lists. It front-loads the purpose and usage, and every sentence contributes necessary guidance. Despite its length, it remains scannable and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 parameters, multiple criteria types, three modes, no output schema), the description fully equips an agent: it covers how to list, search, and directly reference, explains the response shape, notes the LinkedIn-only constraint, and even flags edge cases like years-of-experience not being retrieved. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
While schema coverage is 100%, the description adds crucial interaction semantics: it explains how criteria_type and reference_type relate (reference_type auto-determined), when to provide search_terms (search-based criteria), the default and effect of exact_match, and the distinction between list and search modes. It also provides concrete examples of operation modes. This is meaningful added meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves available criteria and supported values for target group creation/updates, and it breaks down into list-based, search-based, and numeric categories. It names the exact resource and verb, and the detailed criteria types and operation modes make it unmistakable versus siblings like search_reddit_criteria or search_insights_criteria_fields.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a dedicated 'USE FOR' section listing concrete intents (e.g., 'what targeting criteria are available?', 'validate criteria before creating target group'), and it explains three operation modes with examples. It also states 'Only LINKEDIN supported,' which excludes other channels, and implicitly signals when not to use this tool. This is explicit and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_campaign_utmsSet Campaign UTMsADestructiveInspect
Set or clear the UTM tracking parameters of ONE channel on a wizard campaign, merging into what the channel already stores.
KEYWORDS: utm, utms, set utm, change utm, utm_source, utm_medium, utm_campaign, utm_term, utm_content, tracking parameters, campaign override, UPDATE ME
USE THIS TOOL WHEN THE USER ASKS:
- "Set utm_source=Linkedin and utm_medium=paid-social on this campaign"
- "Fix the UPDATE ME placeholder in campaign X's UTMs"
- "Use utm_campaign=DG_Touch-3 on the LinkedIn channel"
INHERITANCE RULE - READ BEFORE ANSWERING ANY UTM QUESTION:
UTMs are inherited, never blank. A campaign channel with an empty stored
mapping does NOT have "no UTMs" - it tracks with the account's UTM defaults,
and where the account set nothing it tracks with the Metadata platform default.
Roughly half of all channel rows in production are in that inherited state.
NEVER report "no UTMs configured" from an empty stored field: report the
resolved value and its origin.
ORIGIN IS PER CHANNEL, not per key: a channel with an empty stored mapping
inherits the account default whole, so a channel whose resolved mapping differs
at all from that is stored on the campaign and every one of its values is an
override. The per-key `same_as_default` flag says whether that one key happens
to match the default anyway.
ORIGIN VALUES:
- campaign_override: stored on this campaign channel, differs from what it would inherit.
- account_default: inherited from this account's UTM defaults.
- platform_default: inherited from the Metadata-wide default (account set nothing).
- not_set: the channel really has no UTM mapping (non-sponsored channels only).
HONEST LIMIT: a campaign that stores a mapping identical to the default it
would inherit is reported as inherited. The platform returns resolved values
with no provenance, so that case cannot be distinguished - say so rather than
claiming the campaign has no override.
INPUT:
- campaign_id: the WIZARD campaign id (from list_wizard_campaigns / search_campaigns_by_names).
- channel: the enabled channel to edit: LINKEDIN, FACEBOOK, INSTAGRAM, GOOGLE_ADS,
MICROSOFT_ADS or REDDIT. UTMs are stored per channel; call once per channel.
- utms: object of UTM key to value. Standard keys UTM_SOURCE, UTM_MEDIUM, UTM_TERM,
UTM_CAMPAIGN, UTM_CONTENT (utm_source style is accepted and normalised); other keys
are custom static parameters. A value is either literal text ("paid-social") or one
of the platform's dynamic tokens, substituted at serve time: AD_CHANNEL, AD_NAME,
CAMPAIGN_NAME, OFFER_TYPE, OFFER_FORM_NAME, AUDIENCE_NAME_OR_KEYWORD, EXPERIMENT_ID,
EXPERIMENT_NAME, NATIVE_CHANNEL_CAMPAIGN_ID, NATIVE_CHANNEL_ADGROUP_ID,
NATIVE_CHANNEL_CREATIVE_ID, NATIVE_CHANNEL_KEYWORD, NATIVE_CHANNEL_SEARCH_TERM.
Keys you omit keep their current value; an empty string clears a key (the channel
then inherits that key's default again only if the whole mapping becomes empty).
`metadata_cid` is reserved and refused.
HOW IT WRITES: the platform endpoint replaces the campaign's whole UTM map and blanks
any enabled channel left out of it, so this tool reads the current mappings first and
re-sends every other enabled channel unchanged. A channel that was inheriting the
account default is re-sent with the same values it already resolves to, so tracking
does not change for it.
A Draft campaign carries the result into launch. On a launched campaign the mapping is
stored and reaches the ad platform with the next campaign publish (Microsoft Ads is
pushed live immediately). Verify with get_campaign_utms.
RESPONSE SHAPE:
{"success": true, "campaign_id": 173290, "channel": "LINKEDIN",
"applied": {"set": {"UTM_SOURCE": "Linkedin"}, "cleared": []},
"stored_mapping": {...}, "resolved": {...same shape as get_campaign_utms.channels.LINKEDIN...},
"notes": ["..."]}
Account-level UTM defaults are NOT edited here (get_account_utm_defaults is read-only).| Name | Required | Description | Default |
|---|---|---|---|
| utms | Yes | UTM key to value, e.g. {"UTM_SOURCE": "Linkedin", "UTM_MEDIUM": "paid-social", "UTM_CAMPAIGN": "DG_Touch-3_TAG", "UTM_CONTENT": "AD_NAME"}. Empty string clears a key. | |
| channel | Yes | The enabled channel whose UTM mapping to edit. | |
| campaign_id | Yes | Wizard campaign id (the `id` from list_wizard_campaigns). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=true, and the description adds substantial behavioral context: it discloses that the endpoint replaces the whole UTM map and blanks omitted channels, but that the tool mitigates this by reading and re-sending other channels. It explains inheritance (empty stored mapping ≠ no UTMs, resolves to account/platform default), origin values (campaign_override, account_default, platform_default, not_set), and the honest limit about identical mappings being reported as inherited. It also describes the response shape and verification step. This goes far beyond the annotation flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but meticulously structured with clear sections (KEYWORDS, USE THIS TOOL, INHERITANCE RULE, ORIGIN VALUES, INPUT, HOW IT WRITES, RESPONSE SHAPE). Core purpose is front-loaded; every section earns its place by addressing a distinct operational concern (selection, inheritance semantics, write behavior, response). It reads like a well-organized reference rather than a wall of text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema is provided, but the description gives an explicit RESPONSE SHAPE example with fields and a pointer to get_campaign_utms for verification. It covers inheritance rules, origin values, the honest limit, per-channel behavior, and draft vs launched timing. For a complex mutation tool with no output schema, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds critical meaning: it enumerates valid UTM keys, explains dynamic tokens (AD_CHANNEL, CAMPAIGN_NAME, etc.), clarifies that empty string clears a key and inheritance behavior, reserves metadata_cid, and explains the merging semantics (omitted keys keep current value). It also clarifies the 'channel' enum and that campaign_id comes from list_wizard_campaigns. The description transforms the schema from flat field names into a rich operational contract.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a clear verb+resource: 'Set or clear the UTM tracking parameters of ONE channel on a wizard campaign, merging into what the channel already stores.' It differentiates from siblings (get_campaign_utms is read, get_account_utm_defaults is read-only) and includes an explicit 'USE THIS TOOL WHEN THE USER ASKS' section with concrete examples. The scope (one channel) is front-loaded and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use examples ('Set utm_source=Linkedin...', 'Fix the UPDATE ME placeholder...'), names alternatives (get_campaign_utms for reading, get_account_utm_defaults for account defaults), and explicitly states 'Account-level UTM defaults are NOT edited here'. It also explains the write behavior (reads current mappings, re-sends other channels) and when changes take effect (draft vs launched). No ambiguity about selection or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_landing_subdomainSet Landing Page SubdomainADestructiveInspect
Set the subdomain this account's generated landing pages are served from.
USE FOR: "set our landing page domain", "I want our pages on zoom.ad.live", "use acme as our landing subdomain", "our landing pages should be branded".
SET ONCE: this claims a subdomain for an account that has NONE. It cannot change or release one that is already set, and it does not fail loudly when asked to; it returns status "locked" and changes nothing. A change is support's to make.
WHEN TO OFFER IT UNPROMPTED: new accounts start with no subdomain, so their landing pages are served from a long shared service URL. If get_account_details shows landingSubdomain is null and the user is creating or about to create a landing page, offer to set one, since a branded URL is what goes into their ads. Suggest a label derived from their own company domain (acme.com -> "acme") and let them confirm or change it. Do NOT set one without the user agreeing to the specific name.
ARGS:
subdomain (required): the label ONLY, never the full hostname. Pass "zoom", not "zoom.ad.live" and not "https://zoom.ad.live". Pass an empty string to release the account's current claim.
RULES THE LABEL MUST MEET: 1-63 characters of a-z, 0-9 and hyphens; no leading or trailing hyphen; not all digits; not a reserved name (www, api, app, mail, cdn, admin and similar). The platform only trims and lowercases what you send; it does NOT rewrite an invalid label into a valid one, so build a valid label yourself before calling: "Zoom Events" is refused, "zoom-events" is accepted. Always report the value the tool returns rather than what you sent, because the two can differ.
SCOPE: acts on the CALLER'S OWN account only. There is no account argument and it cannot be pointed at another account; to set one for a different account, an operator does it from the platform admin screen.
RESPONSE status AND WHAT TO DO NEXT:
"set": claimed. Tell the user the stored subdomain.
"cleared": the claim was released; pages fall back to the default URL.
"unavailable": another account already holds that name. This is NOT an error. Tell the user it is taken, suggest a variant, and call again once they choose.
"invalid": the label breaks the rules above. Rewrite it, confirm with the user, call again.
"not_permitted": the caller is not an account admin, and nothing was changed. Tell them an admin on their account has to set it, under Settings then Configurations. Do not ask them for a name and do not retry.
"locked": the account already has a subdomain and nothing was changed. Tell the user it is already set, name it, and say support changes it. Do NOT retry and do NOT offer to pick a different name.
IMPORTANT: the name is globally unique and first come first served, and once pages are live it is baked into ad URLs already in market, so changing it later breaks them. That is why it is set once and only support can move it.
| Name | Required | Description | Default |
|---|---|---|---|
| subdomain | Yes | The subdomain label only, without any zone suffix or scheme ("zoom", not "zoom.ad.live"). Empty string releases the current claim. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations only indicate destructiveHint=true and readOnlyHint=false, but the description goes far beyond: it states the set-once behavior, silent 'locked' failure mode, no rewriting of invalid labels, global uniqueness, first-come-first-served nature, impact on live ad URLs, and account-scope restrictions. This fully discloses behavioral characteristics and does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place for a destructive, one-time, support-only-change operation. It is front-loaded with the core purpose, then uses clear labeled sections for usage, arguments, rules, response statuses, and consequences. The structure makes the dense information navigable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description fully compensates by enumerating every possible response status and the appropriate follow-up action. It also covers permissions, scope, validity rules, edge cases, and downstream business impact. Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already documents the single subdomain parameter, the description adds substantial meaning: label only with examples, empty string as a release action, required label rules, reserved-name exclusions, lowercasing/trimming behavior, and validation that the agent must perform before calling. This is far beyond the schema's baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Set the subdomain this account's generated landing pages are served from.' It clearly distinguishes this tool from the many sibling tools by scoping it to landing page subdomains and the caller's own account.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit USE FOR phrases, a concrete 'WHEN TO OFFER IT UNPROMPTED' trigger tied to get_account_details returning a null landingSubdomain, and clear when-not-to conditions: do not set without user agreement, do not retry on locked or not_permitted, and changes require support. This leaves no ambiguity about when to invoke the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_search_channel_final_url_suffixSet Final URL Suffix on a Search ChannelADestructiveInspect
Set or clear the Final URL Suffix on a wizard campaign's search channel (Google Ads or Microsoft Ads). The suffix is appended to every final URL the platform serves — typically UTM parameters for tracking (utm_source, utm_medium, utm_campaign, ...).
Matches the platform UI's "Final URL Suffix" input under the Google Ads / Microsoft Ads channel's Advanced Settings section.
KEYWORDS: final url suffix, final-url-suffix, url suffix, suffix, utm, utm parameters,
utm source, utm medium, utm campaign, tracking, tracking template, url tracking,
tracking parameters, google ads, google, microsoft ads, microsoft, bing,
search channel, search campaign, campaign settings, advanced settings
WHEN TO USE:
- Add or change UTM / tracking parameters on Google Ads or Microsoft Ads final URLs
- Clear an existing suffix (pass empty string "")
REQUIREMENTS:
- The campaign MUST already have the target channel enabled (via create_campaign /
add_and_edit_campaign_elements with a `google` and/or `microsoft` block).
- Final URL Suffix is search-channel-only. LinkedIn / Meta / Reddit do NOT support
it and the tool will reject other channel types.
PARAMETERS:
- campaign_id (required): the wizard campaign ID.
- channel (required): "GOOGLE_ADS" or "MICROSOFT_ADS".
- final_url_suffix (required): the suffix string. Max 2048 chars. Format: key=value
pairs separated by `&`. Allowed characters: A–Z a–z 0–9 . _ ~ = & { } - or %XX
percent-encoded. Spaces and [ ] ( ) # ? must be percent-encoded. Pass empty string
"" to clear.
EXAMPLES:
Set UTMs on a Google Ads channel:
set_search_channel_final_url_suffix({
"campaign_id": 177214,
"channel": "GOOGLE_ADS",
"final_url_suffix": "utm_source=metadata&utm_medium=cpc&utm_campaign={campaignid}"
})
Clear the suffix on a Microsoft Ads channel:
set_search_channel_final_url_suffix({
"campaign_id": 177214,
"channel": "MICROSOFT_ADS",
"final_url_suffix": ""
})
RESPONSE: {success, campaign_id, channel_id, channel, applied:{final_url_suffix}, errors?}
INTEGRATION WITH OTHER TOOLS:
- Use search_campaigns_by_names / get_campaign_by_wizard_id to find the campaign.
- Google Ads / Microsoft Ads channels are enabled by create_campaign or
add_and_edit_campaign_elements with a `google` / `microsoft` block.| Name | Required | Description | Default |
|---|---|---|---|
| channel | Yes | Which search channel on the campaign to update. Final URL Suffix is only supported on these two. | |
| campaign_id | Yes | The unique identifier of the wizard campaign. | |
| final_url_suffix | Yes | Tracking suffix appended to every final URL on this channel. Format: key=value pairs separated by `&`. Allowed characters: A–Z a–z 0–9 . _ ~ = & { } - or %XX percent-encoded. Pass empty string "" to clear. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=true, and openWorldHint=true. The description adds meaningful behavioral context: the suffix is appended to every final URL the platform serves, it matches the platform UI's 'Final URL Suffix' input, and it can be cleared by passing an empty string. It also discloses the rejection behavior for unsupported channel types. The only minor gap is that it doesn't explicitly state whether clearing is destructive or reversible, but the annotations already flag destructiveHint=true, so the description adds sufficient context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (WHEN TO USE, REQUIREMENTS, PARAMETERS, EXAMPLES, RESPONSE, INTEGRATION WITH OTHER TOOLS). It is longer than average, but every section earns its place: the examples are instructive, the requirements prevent errors, and the integration notes help with workflow. The keyword list is somewhat redundant and could be trimmed, but it doesn't detract significantly from the overall structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter tool with no output schema, the description is remarkably complete. It covers prerequisites (channel must be enabled), constraints (search-channel-only, max 2048 chars, allowed characters), examples for both setting and clearing, the response shape, and integration with sibling tools for finding the campaign. An agent has everything needed to call this tool correctly without opening the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds value by explaining the format of final_url_suffix (key=value pairs separated by `&`, allowed characters, percent-encoding requirements) and by providing two concrete examples showing exact parameter values. It also clarifies the channel enum values and the meaning of passing an empty string. This goes beyond the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Set or clear'), a specific resource ('Final URL Suffix on a wizard campaign's search channel'), and explicitly names the two supported platforms (Google Ads or Microsoft Ads). It also distinguishes itself from sibling tools by noting it is search-channel-only and that LinkedIn/Meta/Reddit do not support it. This is a clear, specific purpose statement that an agent can act on.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has an explicit 'WHEN TO USE' section listing two concrete use cases (add/change UTM parameters, clear existing suffix). It also has a 'REQUIREMENTS' section stating the campaign must already have the target channel enabled, and explicitly says the tool will reject other channel types. This is exactly the kind of when-to-use and when-not-to-use guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_search_channel_locationsSet Geo Targeting on a Search ChannelADestructiveInspect
Set the geographic targeting of a wizard campaign's search channel (Google Ads or Microsoft Ads) — which countries/states the campaign serves in, and which countries to exclude.
Matches the platform UI's "Location" picker under the Google Ads / Microsoft Ads channel SETTINGS panel, plus the "Negative Locations" editor under that channel's Advanced Settings.
WARNING: NEW SEARCH CAMPAIGNS DEFAULT TO UNITED STATES. The platform seeds the Location
field with United States, so a campaign created without calling this tool serves in
the US only. Whenever the user names a geography — "target Canada and the UK",
"run this in EMEA", "exclude India" — set it explicitly; do not assume the default
is what they want.
KEYWORDS: geo, geos, geo targeting, geotargeting, geographic, geography, location,
locations, location targeting, country, countries, state, states, region, territory,
market, target location, exclude location, exclude geo, exclude country,
negative location, negative locations, location exclusion, excluded locations,
where the campaign runs, google ads, google, microsoft ads, microsoft, bing,
search channel, search campaign, campaign settings
WHEN TO USE:
- Point a search campaign at specific countries/states instead of the US default
- Exclude countries the campaign must not serve in
- Clear targeting back to all locations (countries=[], states=[])
REQUIREMENTS:
- The campaign MUST already have the target channel enabled (via create_campaign /
add_and_edit_campaign_elements with a `google` and/or `microsoft` block).
- Geo targeting here is search-channel-only. LinkedIn / Meta / Reddit carry location
on the audience or target group instead — use create_target_group or the audience
tools for those.
PARAMETERS (each one REPLACES that side of the targeting; omit to leave untouched):
- campaign_id (required): the wizard campaign ID.
- channel (required): "GOOGLE_ADS" or "MICROSOFT_ADS".
- countries: country NAMES to target, e.g. ["United States", "Canada"].
Pass [] to clear (= all locations).
- states: US state NAMES to target, e.g. ["Texas", "California"].
Pass [] to clear. States are US-only.
- excluded_countries: country NAMES the campaign must NOT serve in.
Pass [] to clear all exclusions.
Names are matched case-insensitively against the platform's location catalog and
common shorthand resolves ("USA", "UK", "UAE"). An unrecognised name is REJECTED
rather than skipped — a silently dropped geo would serve the campaign somewhere
nobody chose. At least one of the three lists must be given.
WARNING: EXCLUSIONS ARE COUNTRY-LEVEL ONLY. The platform stores exclusions as bare
location ids with no country/state discriminator, and state ids overlap country ids,
so an excluded state would be read back as an unrelated country. The UI's Negative
Locations picker is countries-only for the same reason. To narrow within a country,
target the states you want via `states` instead of excluding the ones you don't.
EXAMPLES:
Target Canada and the UK on Google Ads (replacing the US default):
set_search_channel_locations({
"campaign_id": 177214,
"channel": "GOOGLE_ADS",
"countries": ["Canada", "United Kingdom"]
})
Target three US states only:
set_search_channel_locations({
"campaign_id": 177214,
"channel": "GOOGLE_ADS",
"countries": ["United States"],
"states": ["Texas", "California", "New York"]
})
Keep targeting as-is but exclude two countries on Microsoft Ads:
set_search_channel_locations({
"campaign_id": 177214,
"channel": "MICROSOFT_ADS",
"excluded_countries": ["India", "Pakistan"]
})
RESPONSE: {success, campaign_id, channel_id, channel, applied:{locations?:{countries,states}, excluded_locations?:{countries}}, errors?}
`applied` echoes the resolved location NAMES, so you can confirm back to the user what the campaign now targets.
INTEGRATION WITH OTHER TOOLS:
- Use search_campaigns_by_names / get_campaign_by_wizard_id to find the campaign.
- create_campaign and add_and_edit_campaign_elements accept the same geo inline on
their `google` / `microsoft` blocks — prefer that when creating, and use this tool
to change geo on a campaign that already exists.| Name | Required | Description | Default |
|---|---|---|---|
| states | No | US state NAMES to target, e.g. ["Texas", "California"]. REPLACES the channel's current states. Pass [] to clear. Omit to leave unchanged. US states only. | |
| channel | Yes | Which search channel on the campaign to update. Geo targeting is set per channel and only these two carry it. | |
| countries | No | Country NAMES to target, e.g. ["United States", "Canada"]. REPLACES the channel's current countries. Pass [] to clear (targets all locations). Omit to leave unchanged. | |
| campaign_id | Yes | The unique identifier of the wizard campaign. | |
| excluded_countries | No | Country NAMES the campaign must NOT serve in, e.g. ["India"]. REPLACES the channel's current exclusions. Pass [] to clear them all. Omit to leave unchanged. Country-level only — states cannot be excluded. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate write (readOnlyHint=false) and destructive (destructiveHint=true), but the description goes further: warns about the US default, replacement semantics (each list replaces), country-level-only exclusions with id overlap issue, and rejection of unrecognized names. Adds substantial behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but every section earns its place: core purpose front-loaded, then warnings, parameters, examples, response format, integration. Headers and bullet points aid scanning. No fluff; all content is actionable for the agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter mutation tool with no output schema, the description is complete: it specifies requirements (channel enabled), parameter semantics, validation behavior, response structure, examples, and integration with other tools. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds rich semantics: explains replacement vs omit behavior, how [] clears, case-insensitive matching with shorthand resolution, rejection of unknown names, and the 'at least one list required' constraint. Examples illustrate parameter usage clearly. Far exceeds baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource, and scope: 'Set the geographic targeting of a wizard campaign's search channel (Google Ads or Microsoft Ads) — which countries/states the campaign serves in, and which countries to exclude.' Clearly distinguishes from sibling tools like create_target_group for other channels.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'WHEN TO USE' section lists concrete scenarios, and 'INTEGRATION WITH OTHER TOOLS' clarifies when to use inline geo on create_campaign vs this tool. Also states it's search-channel-only and routes LinkedIn/Meta/Reddit to other tools. No ambiguity left.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stop_impersonationSwitch back to your own Metadata accountAIdempotentInspect
Switch back from a client account to your own default Metadata account.
Reverses impersonate_account: subsequent tools operate on the caller's own
account again. Safe to call even when not currently impersonating (no-op).
Call it when the user is done working in the other account, or before
switching to a different one.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds behavioral context beyond annotations: it explains the reversal effect on subsequent tools and the no-op behavior when not impersonating. The annotations already include idempotentHint=true and destructiveHint=false, so the no-op aspect is partially covered, but the description clarifies the operational impact and safety, which is valuable. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a clear opening statement, an explanatory sentence about reversal, and a final usage directive. Every sentence adds value, and the purpose is front-loaded. No fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with a clear purpose and usage, the description is complete. It covers what the tool does, when to call it, and its behavior in edge cases (no-op). The presence of an output schema presumably handles return details. Nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline for parameter semantics is 4. The description doesn't need to elaborate on parameter meaning because there are none. It correctly focuses on behavior and usage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool's action: switching back from a client account to the caller's own default Metadata account. It also references the inverse operation, `impersonate_account`, which distinguishes it from the sibling tool with the same prefix. This makes the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides direct usage guidance: call it when the user is done working in the other account or before switching to a different one. It also notes that it's safe to call when not impersonating (no-op), which prevents unnecessary hesitation. This is explicit and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unarchive_adUnarchive AdAInspect
Unarchive (restore) one or more previously archived ads.
Brings an archived (soft-deleted) ad back to active status. The
reverse of archive_ad. The ad's id, creative_json, and history are
preserved across archive/unarchive — same row, status flip.
USE THIS TOOL WHEN:
- User asks to restore, unarchive, undelete, recover, reactivate,
bring back, or undo the archiving of an ad.
- User wants to reuse an ad they previously archived.
HOW TO GET THE id(s) FOR ARCHIVED ADS:
- Archived ads are NOT returned by `search_ads_by_names` by default
(the default `status="active"` filters them out).
- Call `search_ads_by_names(ad_names=[...], status="archived")` to
get ONLY archived ads in the results, then pass the matching ids
to this tool. Use `status="all"` if you also want active matches
in the same response (rare; usually you want just "archived").
- get_ad_details(ids=...) works on archived ids too if you already
have the id.
ALSO KNOWN AS: unarchive ad, restore ad, undelete ad, recover ad,
reactivate ad, bring back ad, undo archive.
KEYWORDS: unarchive, restore, undelete, recover, reactivate,
bring back, undo archive, revive, resurrect.
PARAMETERS:
- ids: Array of integer ad ids (at least one). Bulk-friendly.
RETURNS:
{ "success": true, "unarchived_ids": [123, 456], "count": 2 }
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Ad id(s) to unarchive. At least one integer required; pass multiple to restore in bulk. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that the operation is a status flip from archived to active, that the ad's id, creative_json, and history are preserved, and that it is a soft-delete reversal. This goes beyond the annotations (readOnlyHint=false, destructiveHint=false) by clarifying the non-destructive, reversible nature. However, it does not mention any permission prerequisites or potential side effects (e.g., whether it can be applied to ads in any state), so a 4 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized with clear sections (purpose, usage, how-to-get-ids, aliases, parameters, returns). It front-loads the core purpose and usage. Some redundancy exists (e.g., aliases and keywords overlap), but every section contributes actionable guidance. It could be trimmed slightly, but the structure is effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only one parameter fully documented in the schema and no output schema, the description provides a sample return shape, explains how to obtain valid ids, and gives the exact conditions under which to use the tool. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully documents the single 'ids' parameter as an array of integers with minItems=1 and a clear description. The tool description adds 'at least one integer required' (redundant) and 'bulk-friendly' (minor). Since schema coverage is 100%, the description adds marginal value, warranting the baseline score of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Unarchive (restore) one or more previously archived ads') and immediately frames it as the reverse of archive_ad. It also distinguishes from the sibling unarchive_audience by focusing solely on ads, and provides a clear list of user intents that map to this tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'USE THIS TOOL WHEN' section lists all relevant intents (restore, undelete, recover, reactivate, etc.). It also provides a precise workflow for obtaining archived ad ids via search_ads_by_names with status='archived', and notes that get_ad_details works on archived ids. This is exemplary routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
unarchive_audienceUnarchive AudienceAInspect
Unarchive (restore) a previously archived custom audience on the Metadata platform. Use this tool when the user wants to unarchive, restore, or reactivate a custom audience.
You can identify the audience either by its numeric custom_audience_id or by its name.
If only the audience name is provided, the tool will search existing audiences to resolve the correct ID before unarchiving.
PARAMETERS:
• custom_audience_id (optional): The numeric ID of the custom audience to unarchive.
• audience_name (optional): The name of the custom audience to unarchive. Used to look up the ID if custom_audience_id is not provided.
At least one of custom_audience_id or audience_name must be provided.
RESPONSE:
• actionStatus: "SUCCEEDED" if the audience was unarchived successfully.
| Name | Required | Description | Default |
|---|---|---|---|
| audience_name | No | The name of the custom audience to unarchive. If provided without custom_audience_id, the tool will search for the audience by name to resolve the ID. | |
| custom_audience_id | No | The numeric ID of the custom audience to unarchive. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/destructive hints, and the description adds notable behavior: name-based ID resolution ('search existing audiences to resolve the correct ID') and the response format (actionStatus: SUCCEEDED). It does not cover failure or not-found behavior, but provides meaningful operational transparency beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear purpose and uses labeled PARAMETERS/RESPONSE sections for easy scanning. It is somewhat verbose and repeats schema fields, but every major section contributes useful operational or constraint information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-optional-parameter tool with no output schema, the description covers input selection, ID resolution behavior, the at-least-one requirement, and the success response. It does not describe error cases or prerequisites (e.g., audience must currently be archived), but the provided context is largely sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds the critical constraint that 'At least one of custom_audience_id or audience_name must be provided' and explains their fallback relationship. This goes beyond the schema, which marks both as optional with no required-count validation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with 'Unarchive (restore) a previously archived custom audience on the Metadata platform,' stating a precise verb, resource, and action. This clearly differentiates from the sibling archive_audience by emphasizing restoration/re-activation of a previously archived audience.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'Use this tool when the user wants to unarchive, restore, or reactivate a custom audience,' giving clear when-to-use context. It does not explicitly name exclusions or alternative tools like archive_audience, so it misses the full when-not boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_brand_kitUpdate Brand KitADestructiveInspect
Update existing brand kit with brand DNA parameters. Only company_url is required; all others are optional.
UPDATABLE FIELDS (grouped by section):
TOP-LEVEL:
- long_description: Company marketing description
- logo_url / logo_urls: Direct URL(s) to logo images (permanent override; super-user only)
- clear_logos: true removes the permanent logo override (super-user only)
- search_keywords: List of SEO/search keywords
- colors: Legacy flat color list [{hex, type, name?}]
- fonts: Legacy flat font list [{name, type}]
- website_background: Hex color of the brand website's background, used by generate_brand_creative as the default ad background
COLOR PALETTES (each entry: {hex, name, usage}):
- primary_colors, accent_colors, extended_palette, semantic_colors
TYPOGRAPHY (string values):
- primary_font, primary_font_usage, secondary_font, secondary_font_usage
- headline_font, headline_weight, headline_size, headline_case, headline_linespace, headline_letterspace
- eyebrow_font, eyebrow_weight, eyebrow_case, eyebrow_linespace, eyebrow_letterspace
- subtitle_font, subtitle_weight, subtitle_linespace, subtitle_letterspace
- body_font, body_weight, body_size, body_linespace, body_letterspace
- cta_font, cta_weight, cta_size, cta_linespace, cta_letterspace
LOGO USAGE:
- logo_on_dark, logo_on_light, logo_clear_space: string rules
- logo_misuse: list of misuse rules
CTA SYSTEM:
- button_shape, button_background, button_text_color, button_text_weight, button_text_case, button_padding
- standard_ctas: list of CTA labels
- cta_placement: placement guidance
SIGNATURE ELEMENTS:
- tagline, tagline_placement: strings
- tagline_variants, visual_motifs, promotional_elements: lists
MESSAGING:
- tone: string
- value_propositions, headline_formulas, proof_points: lists
- product_names: dict (e.g. {platform: "X", vlm: "Y"})
CONTENT HIERARCHY:
- content_hierarchy_order: list, content_hierarchy_spacing: string, content_hierarchy_text_max_width: string
PHOTOGRAPHY:
- photography_style, photography_treatment, photography_avoid: strings
- photography_subjects: list
RULES:
- dos: list of "do" rules
- donts: list of "don't" rules
LAYOUT & CHANNELS:
- primary_layouts: list of layout dicts
- channel_linkedin, channel_facebook, channel_display: channel config dicts
EXAMPLE: {"company_url": "ambient.ai", "tagline": "See what matters.", "headline_font": "Chakra Petch", "primary_colors": [{"hex": "#FFFFFF", "name": "White", "usage": "Primary background"}]}| Name | Required | Description | Default |
|---|---|---|---|
| dos | No | Brand 'do' rules. | |
| tone | No | Brand tone description. | |
| donts | No | Brand 'don't' rules. | |
| fonts | No | Legacy flat font list. Each: {name, type}. | |
| colors | No | Legacy flat color list. Each: {hex (with #), type, name?}. | |
| tagline | No | Primary brand tagline. | |
| cta_font | No | CTA/button font family. | |
| cta_size | No | CTA/button font size. | |
| logo_url | No | Direct URL to a single company logo image (back-compat; prefer logo_urls). Setting a permanent brand logo requires elevated Metadata permissions. | |
| body_font | No | Body text font family. | |
| body_size | No | Body text font size. | |
| logo_urls | No | One or more direct URLs to logo images to set as the brand's permanent logo(s). Each uploaded logo is automatically expanded into clean, persisted variants (transparent, high-res, and both a light and dark version when the mark is a single color) so generated creatives have multiple usable options. Setting a permanent brand logo requires elevated Metadata permissions. | |
| cta_weight | No | CTA/button font weight. | |
| body_weight | No | Body text font weight. | |
| clear_logos | No | Remove the brand kit's permanent logo override entirely (no logo_url needed), so creatives fall back to the cached Brandfetch logo variants for the domain. Use when a manually set logo turned out wrong or low quality. Same elevated Metadata permissions as setting one. | |
| company_url | Yes | Company website URL or domain (e.g. 'ambient.ai'). | |
| logo_misuse | No | List of logo misuse rules. | |
| button_shape | No | Button shape description. | |
| eyebrow_case | No | Eyebrow text case rule. | |
| eyebrow_font | No | Eyebrow font family. | |
| logo_on_dark | No | Logo color rule on dark backgrounds. | |
| primary_font | No | Primary font family name. | |
| proof_points | No | Evidence/social proof items. | |
| accent_colors | No | Accent color palette. | |
| cta_linespace | No | CTA/button line spacing. | |
| cta_placement | No | CTA placement guidance. | |
| headline_case | No | Headline text case rule. | |
| headline_font | No | Headline font family. | |
| headline_size | No | Headline font size range. | |
| logo_on_light | No | Logo color rule on light backgrounds. | |
| product_names | No | Product name mapping (e.g. {platform: 'X', vlm: 'Y'}). | |
| standard_ctas | No | Standard CTA labels. | |
| subtitle_font | No | Subtitle font family. | |
| visual_motifs | No | Brand visual motifs. | |
| body_linespace | No | Body text line spacing. | |
| button_padding | No | Button padding. | |
| eyebrow_weight | No | Eyebrow font weight. | |
| primary_colors | No | Primary color palette. | |
| secondary_font | No | Secondary/display font family name. | |
| channel_display | No | Display ads channel config. | |
| cta_letterspace | No | CTA/button letter spacing. | |
| headline_weight | No | Headline font weight. | |
| primary_layouts | No | Layout system definitions. | |
| search_keywords | No | SEO/search keywords for the brand. | |
| semantic_colors | No | Semantic/status colors. | |
| subtitle_weight | No | Subtitle font weight. | |
| body_letterspace | No | Body text letter spacing. | |
| button_text_case | No | Button text case. | |
| channel_facebook | No | Facebook channel config. | |
| channel_linkedin | No | LinkedIn channel config. | |
| extended_palette | No | Extended grayscale palette. | |
| logo_clear_space | No | Logo clear space rule. | |
| long_description | No | Company description for marketing use. | |
| remove_old_logos | No | When true (default), replace the brand's existing logos with the provided ones; when false, append to them. | |
| tagline_variants | No | Alternative taglines. | |
| button_background | No | Button background style. | |
| button_text_color | No | Button text color rule. | |
| eyebrow_linespace | No | Eyebrow line spacing. | |
| headline_formulas | No | Headline writing patterns. | |
| photography_avoid | No | Photography anti-patterns. | |
| photography_style | No | Photography style description. | |
| tagline_placement | No | Tagline placement guidance. | |
| button_text_weight | No | Button text weight. | |
| headline_linespace | No | Headline line spacing. | |
| primary_font_usage | No | Primary font usage description. | |
| subtitle_linespace | No | Subtitle line spacing. | |
| value_propositions | No | Core value propositions. | |
| website_background | No | 6-digit hex color (e.g. '#FFFFFF') of the brand website's background. generate_brand_creative uses it as the default dominant background for ads (use_website_background). Set it when the user wants ads to match their site's background or the auto-detected value is wrong. | |
| eyebrow_letterspace | No | Eyebrow letter spacing. | |
| headline_letterspace | No | Headline letter spacing. | |
| photography_subjects | No | Recommended photo subjects. | |
| promotional_elements | No | Promotional proof points. | |
| secondary_font_usage | No | Secondary font usage description. | |
| subtitle_letterspace | No | Subtitle letter spacing. | |
| photography_treatment | No | Photo treatment rules. | |
| content_hierarchy_order | No | Content element ordering. | |
| content_hierarchy_spacing | No | Section spacing guidance. | |
| content_hierarchy_text_max_width | No | Max text block width. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the description does not need to repeat safety. It adds useful behavioral context: logo_url/logo_urls and clear_logos require elevated permissions and clear_logos removes the permanent override. It also explains website_background's effect on generate_brand_creative. These details go beyond the annotation without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long (necessary for 78 parameters) but extremely well-organized with section headers and a front-loaded requirement statement. Every field is listed under a logical category. It is not concise in word count, but the structure makes it efficient to scan. Slightly verbose for some fields that are self-explanatory, but acceptable given complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 78 parameters, no output schema, and complex nested objects, the description is comprehensive. It covers all fields, provides grouping, explains legacy vs modern structures, and includes an example. It even flags permission requirements and behavioral nuances. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds significant value by grouping parameters into sections, clarifying nested object shapes (e.g., color palettes with hex/name/usage), and providing a concrete example. It does not merely repeat schema descriptions but adds structure and usage hints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Update'), resource ('existing brand kit'), and the core requirement ('Only company_url is required; all others are optional'). It is distinct from sibling tools like generate_brand_kit (creation) and get_brand_kit (read), making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states this is for updating an existing brand kit, which differentiates it from creation/read siblings. It does not explicitly name alternatives or exclusion conditions, but the 'update existing' phrasing plus the huge field list makes the usage context clear. Lacks explicit 'when not to use' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_experiments_daily_budgetsUpdate Experiments Daily BudgetsADestructiveInspect
Update daily budget allocations for one or more experiments in the Metadata platform.
KEYWORDS: experiment, budget, daily, update, change, adjust, spending, allocation, modify
WHEN TO USE:
- User wants to "change the daily budget for experiment X"
- User asks to "adjust daily budget for experiments A, B, C"
- User requests to "update experiment budgets"
- User wants to "allocate more budget to experiment Y"
- User asks to "set daily budget to X for multiple experiments"
PURPOSE:
This tool allows you to adjust the daily budget amount for active experiments.
The daily budget controls how much money each experiment can spend per day.
REQUIRED PARAMETERS:
- budgets: A dictionary mapping experiment IDs to their new daily budget values
BUDGET VALUE FORMAT:
Budget values can be provided as:
- Strings with comma separator (European format): "100,50" → 100.50
- Strings with dot separator (US format): "100.50" → 100.50
- Numbers: 100, 100.5, 100.50
- All values are automatically converted to 2 decimal places
INPUT EXAMPLES:
- Single experiment: {"budgets": {"12345": "100.50"}}
- Multiple experiments: {"budgets": {"12345": 100.50, "12346": "150,75", "12347": 200}}
INTEGRATION WITH OTHER TOOLS:
- Use search_experiments to find the experiment IDs to update the daily budget.| Name | Required | Description | Default |
|---|---|---|---|
| budgets | Yes | Dictionary mapping experiment IDs to new daily budget values. Keys are experiment IDs (integers or strings), values are budget amounts (numbers or strings with comma/dot separators). Example: {'12345': 100.50, '12346': '150,75'} |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, and the description aligns with them, adding genuinely non-obvious behavior: values can be European comma or US dot strings, and all values are normalized to 2 decimal places. It also says budgets apply to active experiments. It does not detail side effects or irreversibility, but the annotation coverage lowers the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear one-sentence summary and then organized into labeled sections (WHEN TO USE, PURPOSE, FORMAT, EXAMPLES, INTEGRATION). The KEYWORDS section and the repeated PURPOSE sentence add some redundancy, but the structure and concrete examples keep it usable despite the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter mutation tool, the description covers when to use it, the input format, worked examples, and how to obtain experiment IDs via search_experiments. The main gaps are the absence of any indication of return behavior (no output schema) and what happens for inactive or unknown experiment IDs, but these are not blockers for a correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the budgets dictionary at 100% coverage, but the description goes well beyond it by explaining European comma semantics ('100,50' -> 100.50), dot/US format, numeric inputs, automatic rounding to 2 decimals, and providing single- and multi-experiment examples. This adds real meaning that the schema pattern alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific action ('Update daily budget allocations') on a specific resource ('experiments') and adds the scope 'one or more,' which separates it from broader experiment-management siblings like manage_experiment. The PURPOSE section reinforces the semantics without tautology, explaining that the daily budget controls per-day spend.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The WHEN TO USE section provides concrete natural-language triggers ('change the daily budget for experiment X', 'set daily budget to X') that make matching easy. It also names search_experiments as the companion lookup tool. However, it does not explicitly state when not to use this tool or point to alternatives for non-budget experiment changes, so exclusions are missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_linkedin_channel_settingsUpdate LinkedIn Channel SettingsADestructiveInspect
Update the LinkedIn channel settings of an existing DRAFT wizard campaign: native objective, bidding optimization goal (including Reach), bid strategy with manual bid amount, and the LinkedIn conversion actions the campaign optimizes toward.
These are the settings the platform UI shows in the LinkedIn channel drawer of the
campaign draft page (Native Objective, Bidding Optimization Goal, Bid, Conversion
Actions). The campaign MUST already have its LinkedIn channel enabled (via
create_campaign / add_and_edit_campaign_elements with a `linkedin` block).
WARNING: DRAFT-ONLY: the platform rejects these edits once the campaign is Launching/Launched.
KEYWORDS: linkedin, linkedin campaign, linkedin settings, campaign settings, draft campaign,
objective, native objective, brand awareness, website visits, engagement, video views,
bidding optimization goal, optimization goal, reach, impressions, landing page clicks,
engagement clicks, bid, bid strategy, auto bid, manual bid, maximum delivery,
conversion, conversions, conversion actions, conversion tracking, insight tag, settings
WHEN TO USE:
- Set the LinkedIn native objective (e.g. Brand Awareness instead of the default Engagement)
- Optimize a Brand Awareness campaign for REACH instead of IMPRESSIONS
- Switch between auto bid (LinkedIn maximum delivery) and a manual bid
- Pick which LinkedIn conversion actions the campaign optimizes toward and reports on
PARAMETERS (campaign_id required; everything else optional, and an unspecified
setting keeps its current value on the channel):
- campaign_id: the wizard campaign ID
- objective: BRAND_AWARENESS | WEBSITE_VISIT | ENGAGEMENT | VIDEO_VIEW, the LinkedIn
native objective. Only selectable on Brand Awareness (CTR) campaigns: a Lead Gen
(CPL) campaign derives it from its offer at launch (lead-gen form -> LEAD_GENERATION,
landing page -> WEBSITE_CONVERSION). The platform default for a new LinkedIn channel
is ENGAGEMENT. Every ad already on the channel must be supported by the objective
(VIDEO_VIEW is video-only, MESSAGE ads only fit WEBSITE_VISIT, DOCUMENT ads lock the
objective, a video-only channel accepts only ENGAGEMENT or VIDEO_VIEW). A channel
holding CTV ads is always Brand Awareness / Reach at launch and cannot be changed here.
Changing the objective also resets the cost type and the bidding optimization goal to
the objective's default (BRAND_AWARENESS -> IMPRESSIONS, WEBSITE_VISIT ->
LANDING_PAGE_CLICKS, ENGAGEMENT -> ENGAGEMENT_CLICKS, VIDEO_VIEW -> VIDEO_VIEWS), so
pass bidding_optimization_goal in the same call when you want something else.
- bidding_optimization_goal: what LinkedIn optimizes delivery for. Allowed per objective:
BRAND_AWARENESS -> IMPRESSIONS | REACH; WEBSITE_VISIT -> LANDING_PAGE_CLICKS |
IMPRESSIONS; ENGAGEMENT -> ENGAGEMENT_CLICKS | IMPRESSIONS; VIDEO_VIEW -> VIDEO_VIEWS |
IMPRESSIONS. Conversation and Message ads are always IMPRESSIONS. CTR campaigns only.
- bid_strategy: AUTO_BID (LinkedIn "maximum delivery", what the campaign builder applies
by default) or MANUAL_BID (needs bid_amount). CTV ads REQUIRE AUTO_BID; Spotlight and
Text ads REQUIRE MANUAL_BID.
- bid_amount: manual bid in the account currency, used only with MANUAL_BID.
- conversion_action_ids: ids of LinkedIn conversion actions (from list_linkedin_conversions)
the campaign should optimize toward and count as conversions: website visits, URL-rule
page views, lead form fills. REPLACES the current selection; pass [] to clear it (the
campaign then falls back to the account's default Insight Tag URL match). Every id must
exist and be enabled on the connected LinkedIn account, or launch validation fails.
NOTE: the platform UI only shows this picker for campaigns with landing-page offers and
an objective other than Brand Awareness; ids stored outside that case are still sent to
LinkedIn at launch, but that path is not exercised by the UI.
NOT SETTABLE ANYWHERE IN THE PLATFORM (say so instead of promising them): LinkedIn
Audience Network on/off and its category exclusions, audience expansion (campaigns always
launch with expansion OFF), frequency caps, Thought Leader ads. LinkedIn geo targeting is
not a channel setting either: it lives on the audience / target group.
EXAMPLES:
Brand Awareness optimized for Reach on auto bid:
update_linkedin_channel_settings({"campaign_id": 12345, "objective": "BRAND_AWARENESS",
"bidding_optimization_goal": "REACH", "bid_strategy": "AUTO_BID"})
Track two conversion actions on a Website Visits campaign:
update_linkedin_channel_settings({"campaign_id": 12345,
"conversion_action_ids": ["123456", "234567"]})
RESPONSE: {success, campaign_id, channel_id, campaign_status, campaign_goal,
channel_ad_types, applied:{...}, errors?}. `applied` echoes exactly what was pushed to
the platform.
INTEGRATION WITH OTHER TOOLS:
- list_linkedin_conversions lists the conversion actions available on the account
- search_campaigns_by_names / get_campaign_by_wizard_id to find the campaign
- The LinkedIn channel is enabled by create_campaign or add_and_edit_campaign_elements
- check_campaign_launch_readiness validates the result before launch| Name | Required | Description | Default |
|---|---|---|---|
| objective | No | LinkedIn native objective. Brand Awareness (CTR) campaigns only; Lead Gen campaigns derive it from the offer at launch. Resets the bidding optimization goal to the objective's default. | |
| bid_amount | No | Manual bid amount in the account currency. Applied only with MANUAL_BID. | |
| campaign_id | Yes | The unique identifier of the wizard campaign | |
| bid_strategy | No | AUTO_BID = LinkedIn maximum delivery (required for CTV ads); MANUAL_BID needs bid_amount (required for Spotlight and Text ads). | |
| conversion_action_ids | No | LinkedIn conversion action ids from list_linkedin_conversions. REPLACES the channel's selection; [] clears it. | |
| bidding_optimization_goal | No | What LinkedIn optimizes delivery for. Must fit the channel's objective: BRAND_AWARENESS takes IMPRESSIONS or REACH, WEBSITE_VISIT takes LANDING_PAGE_CLICKS or IMPRESSIONS, ENGAGEMENT takes ENGAGEMENT_CLICKS or IMPRESSIONS, VIDEO_VIEW takes VIDEO_VIEWS or IMPRESSIONS. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and readOnlyHint=false, and the description goes well beyond that: it warns the platform rejects edits once the campaign is Launching/Launched, explains that changing the objective resets cost type and bidding optimization goal, states that conversion_action_ids REPLACES the current selection and [] clears it, and discloses that some settings are not settable anywhere in the platform. It also notes the UI-only picker caveat for conversion actions. This is rich behavioral disclosure with no contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: purpose, DRAFT-ONLY warning, keywords, when-to-use, parameter semantics, not-settable list, examples, response shape, and integration with other tools. It is front-loaded with the core purpose and the critical DRAFT-ONLY constraint. The only minor deduction is that the keyword list and the extensive parameter prose could be trimmed without losing value, but the structure is clear and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex mutation tool with 6 parameters, no output schema, and destructive annotations, the description is remarkably complete: it covers prerequisites (channel must be enabled), constraints (draft-only, ad-type requirements), side effects (objective resets), response shape, and integration with sibling tools. The examples demonstrate realistic calls. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds substantial meaning beyond the schema: per-objective allowed bidding goals, the fact that CTV ads REQUIRE AUTO_BID while Spotlight/Text ads REQUIRE MANUAL_BID, the default ENGAGEMENT objective, the lead-gen derivation rule, and the fallback to the account's default Insight Tag URL match when conversion_action_ids is cleared. It also explains the reset behavior when objective changes. This far exceeds the schema's descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Update the LinkedIn channel settings of an existing DRAFT wizard campaign' and enumerates exactly which settings are affected (native objective, bidding optimization goal, bid strategy, conversion actions). It also distinguishes itself from siblings by scoping to the LinkedIn channel drawer of the campaign draft page and by naming related tools like create_campaign, add_and_edit_campaign_elements, and list_linkedin_conversions. The DRAFT-ONLY warning further disambiguates it from launch-time tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has an explicit 'WHEN TO USE' section listing four concrete scenarios (set native objective, optimize for REACH, switch bid strategy, pick conversion actions). It also states when NOT to use it: 'NOT SETTABLE ANYWHERE IN THE PLATFORM' lists settings this tool cannot change, and it names sibling tools for related operations (list_linkedin_conversions, search_campaigns_by_names, check_campaign_launch_readiness). This is exemplary routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_meta_placementsUpdate Meta Placements (Facebook / Instagram)ADestructiveInspect
Set the channel-level Meta placement default of an existing DRAFT wizard campaign's Facebook or Instagram channel: automatic placements (Meta decides where ads serve) or a manual list of surfaces (Feed, Stories, Reels, ...).
Placements are where the ads serve inside Meta's networks. This is the same
"Placements" control the platform UI shows in the Facebook/Instagram section of
the campaign draft page. The campaign MUST already have the channel enabled
(via create_campaign / add_and_edit_campaign_elements).
WARNING: DRAFT-ONLY: the platform rejects the edit once the campaign is Launching/Launched.
KEYWORDS: meta, facebook, instagram, threads, placements, placement, feed, stories,
reels, explore, search results, profile feed, automatic placements, manual placements,
advantage+ placements, where ads serve, surfaces, channel settings, campaign settings
WHEN TO USE:
- Serve ads only on specific surfaces (e.g. Instagram Reels and Stories)
- Switch a channel back to automatic placements (Meta optimizes delivery)
- The user asks where their Facebook/Instagram ads will appear
PARAMETERS:
- campaign_id: the wizard campaign ID (required)
- channel: FACEBOOK | INSTAGRAM (required — the campaign channel to edit)
- mode: AUTO | MANUAL (required). AUTO = automatic placements, clears any
manual set. MANUAL = serve only on the placements listed.
- placements: array of placement codes, required when mode=MANUAL, ignored
for AUTO. Facebook surfaces: FB_FEED, FB_STORIES, FB_REELS,
FB_SEARCH_RESULTS. Instagram surfaces: IG_FEED, IG_PROFILE_FEED,
IG_EXPLORE, IG_EXPLORE_HOME, IG_STORIES, IG_REELS, IG_SEARCH_RESULTS.
Threads: TH_THREADS_STREAM.
PLACEMENT RULES (enforced; violations return a descriptive error):
- Companion rules: FB_STORIES and FB_SEARCH_RESULTS require FB_FEED;
IG_PROFILE_FEED, IG_SEARCH_RESULTS and IG_EXPLORE require IG_FEED;
IG_EXPLORE_HOME requires IG_EXPLORE; TH_THREADS_STREAM requires IG_FEED.
- An INSTAGRAM channel accepts IG_* placements only.
- A FACEBOOK channel always accepts FB_* placements. IG_* / TH_* placements
on a FACEBOOK channel additionally need the account's unified-placement
rollout (feature flag CORE_META_IG_PLACEMENT_ON_FB) — the platform rejects
them on accounts without it.
- IG_PROFILE_FEED is not available on Lead Gen (CPL) campaigns.
- AUTO is rejected while the channel has ad groups (per-ad-group setups keep
manual placements).
This tool sets the campaign-wide default for the channel. Per-ad-group
placement overrides exist in the platform UI but are not editable through
chat yet — send users to the campaign page for per-ad-group customization.
EXAMPLES:
Instagram channel, Reels + Stories + Feed only:
update_meta_placements({"campaign_id": 12345, "channel": "INSTAGRAM",
"mode": "MANUAL", "placements": ["IG_FEED", "IG_STORIES", "IG_REELS"]})
Facebook channel back to automatic placements:
update_meta_placements({"campaign_id": 12345, "channel": "FACEBOOK", "mode": "AUTO"})
RESPONSE: {success, campaign_id, channel_id, channel, campaign_status,
applied:{mode, placements}, previous?, errors?}
`previous` echoes the channel's placement state before the edit.
INTEGRATION WITH OTHER TOOLS:
- Use search_campaigns_by_names / get_campaign_by_wizard_id to find the campaign
- The channel is enabled by create_campaign or add_and_edit_campaign_elements
- Reddit placements (feed/conversations) are a different system: use
update_reddit_channel_settings for those| Name | Required | Description | Default |
|---|---|---|---|
| mode | Yes | AUTO = automatic placements (Meta decides, clears the manual set). MANUAL = serve only on the placements listed in `placements`. | |
| channel | Yes | Which campaign channel to edit. Meta placements only exist on Facebook and Instagram channels. | |
| placements | No | Placement codes to serve on. Required when mode=MANUAL (at least one); ignored for AUTO. Companion rules apply — see the tool description. | |
| campaign_id | Yes | The unique identifier of the wizard campaign |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and readOnlyHint=false, and the description goes well beyond that: it warns DRAFT-ONLY with platform rejection, explains AUTO clears any manual set, documents enforced placement rules with companion requirements, notes IG_PROFILE_FEED unavailability on Lead Gen, and states AUTO is rejected while the channel has ad groups. It also discloses the response shape including `previous` and `errors?`. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: purpose, keywords, when-to-use, parameters, placement rules, examples, response, and integration. It is well-structured with clear headers and front-loaded with the core purpose. It loses one point because the keyword list is somewhat redundant and the overall length is high, though the density of useful information justifies most of it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex mutation tool with 4 parameters, enforced business rules, and no output schema, the description is remarkably complete. It covers prerequisites, constraints, placement rules, examples, response format, and integration with other tools. An agent has everything needed to select and invoke this tool correctly, including edge cases like the unified-placement rollout and per-ad-group limitations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds substantial meaning beyond the schema: it explains the semantic difference between AUTO and MANUAL (AUTO clears manual set), lists exact placement codes per surface, documents companion rules, channel-specific restrictions, the unified-placement rollout flag, and the Lead Gen exception. It also clarifies that `placements` is ignored for AUTO. This far exceeds what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Set'), a specific resource ('channel-level Meta placement default of an existing DRAFT wizard campaign's Facebook or Instagram channel'), and the two modes (automatic vs manual list of surfaces). It clearly distinguishes this from sibling tools like update_reddit_channel_settings and update_linkedin_channel_settings by naming them and noting Reddit placements are a different system.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description has an explicit 'WHEN TO USE' section listing concrete scenarios (serve ads only on specific surfaces, switch back to automatic placements, user asks where ads will appear). It also states when NOT to use it: DRAFT-ONLY, rejected once Launching/Launched, and per-ad-group overrides are not editable through chat. It names alternatives (update_reddit_channel_settings) and prerequisite tools (create_campaign / add_and_edit_campaign_elements).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_reddit_channel_settingsUpdate Reddit Channel SettingsADestructiveInspect
Update the Reddit channel settings of an existing DRAFT wizard campaign: native objective, allow comments, placements (feed/conversations), conversion pixel, and (for manual-bid objectives) the bid amount.
These are the same settings the platform UI shows in the Reddit section of the
campaign draft page. The campaign MUST already have its Reddit channel enabled
(via create_campaign / add_and_edit_campaign_elements with a `reddit` block).
WARNING: DRAFT-ONLY: the platform rejects these edits once the campaign is Launching/Launched.
KEYWORDS: reddit, reddit campaign, reddit settings, campaign settings, draft campaign,
objective, native objective, traffic, brand awareness, reach, views, video views, video views 6s,
impressions, clicks, comments, allow comments, placements, placement, feed, conversations,
pixel, conversion pixel, conversion tracking, bid, bid amount, manual bid, auto bid, settings
WHEN TO USE:
- Change the Reddit objective (e.g. from Brand Awareness to Traffic)
- Toggle "Allow comments" on Reddit ads
- Select placements (Feed and/or Conversations)
- Attach or clear a Reddit conversion pixel
- Set a manual bid amount for Brand Awareness / Video Views objectives
PARAMETERS (campaign_id required; everything else optional — unspecified
settings keep their current values on the channel):
- campaign_id: the wizard campaign ID
- objective: IMPRESSIONS (Brand awareness and Reach) | CLICKS (Traffic) |
VIDEO_VIEWABLE_IMPRESSIONS_6S (Video Views 6s). Mirrors the platform UI's
Native Objective dropdown.
WARNING: Lead Gen (CPL) campaigns only accept CLICKS (landing pages require it).
WARNING: Video Views requires the channel to contain ONLY video ads.
- allow_comments: whether Redditors can comment on the promoted post (platform default: true)
- placements: {"feed": bool, "conversations": bool}. At least one must stay
selected (Feed wins if both are false). Conversations is forced OFF when the
channel has video ads.
- conversion_pixel_id: pixel id from the account's Reddit Ads Manager. Pass an
empty string "" to clear. Pixels are managed in Reddit Ads Manager, not here.
- bid_amount: manual bid amount. Only applied when the effective objective uses
MANUAL_BID (IMPRESSIONS / Video Views). Ignored for CLICKS (AUTO_BID).
BID STRATEGY (automatic): changing the objective re-applies the UI's auto-switch —
CLICKS → AUTO_BID; IMPRESSIONS / VIDEO_VIEWABLE_IMPRESSIONS_6S → MANUAL_BID.
The bid strategy is left untouched when neither objective nor bid_amount is sent.
EXAMPLES:
Switch a Brand Awareness campaign's Reddit channel to Traffic:
update_reddit_channel_settings({"campaign_id": 12345, "objective": "CLICKS"})
Disable comments and run Feed-only:
update_reddit_channel_settings({
"campaign_id": 12345,
"allow_comments": false,
"placements": {"feed": true, "conversations": false}
})
Brand awareness with a manual bid and a conversion pixel:
update_reddit_channel_settings({
"campaign_id": 12345,
"objective": "IMPRESSIONS",
"bid_amount": 1.5,
"conversion_pixel_id": "pixel_abc123"
})
RESPONSE: {success, campaign_id, channel_id, campaign_status, applied:{...}, errors?}
`applied` echoes exactly what was pushed to the platform.
INTEGRATION WITH OTHER TOOLS:
- Use search_campaigns_by_names / get_campaign_by_wizard_id to find the campaign
- Reddit channel is enabled by create_campaign or add_and_edit_campaign_elements
- Reddit ads come from create_update_image_ad / create_update_video_ad with channels=["REDDIT"]| Name | Required | Description | Default |
|---|---|---|---|
| objective | No | Reddit native objective. IMPRESSIONS = Brand awareness and Reach; CLICKS = Traffic (the only objective allowed on Lead Gen campaigns); VIDEO_VIEWABLE_IMPRESSIONS_6S = Video Views 6s (video-only channels). | |
| bid_amount | No | Manual bid amount, applied only when the effective objective uses MANUAL_BID (IMPRESSIONS / Video Views). | |
| placements | No | Where the ads serve. At least one placement must stay selected; conversations is forced off when the channel has video ads. | |
| campaign_id | Yes | The unique identifier of the wizard campaign | |
| allow_comments | No | Allow Redditors to comment on the promoted post. Platform default is true. | |
| conversion_pixel_id | No | Reddit conversion pixel id (created in Reddit Ads Manager). Empty string clears the pixel. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations note destructiveHint=true, and the description aligns by emphasizing the mutation is DRAFT-ONLY and rejected once launching/launched — a critical consequence any agent must know. It discloses conditional behavior beyond annotations: the objective→bid-strategy auto-switch, the Feed-wins fallback when both placements are false, conversations forced off for video ads, the Lead Gen CLICKS-only constraint, and the empty-string pixel clearing semantics. This is exactly the contextual disclosure the rubric rewards.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is long, but the complexity justifies it: 6 parameters, one nested object, conditional behaviors, and no output schema. Structure is excellent — front-loaded purpose and warning, then sections for parameters, bid strategy, examples, response, and integrations. It earns its length; the only ding is that the keyword block and extended sections push it past what a strict editor might trim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 6 params, a nested placements object, enum constraints, multiple conditionals (manual bid, video ads, lead gen), and no output schema, this is exceptionally complete. It provides a response envelope, three worked examples, integration pointers to related tools, and a bid-strategy explanation — nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with detailed schema descriptions, but the description still adds meaningful meaning: it maps objective enums to the platform UI's Native Objective dropdown, explains the auto bid-strategy switching tied to objective changes, clarifies bid_amount is ignored for CLICKS, and specifies that conversion_pixel_id is an empty string to clear. It genuinely enriches the schema rather than repeating it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement: it updates Reddit channel settings on an existing DRAFT wizard campaign, enumerating exactly which settings (objective, comments, placements, pixel, bid amount). This clearly differentiates it from siblings like update_linkedin_channel_settings and update_meta_placements, which target different channels.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains an explicit WHEN TO USE section listing five concrete scenarios (change objective, toggle comments, select placements, attach/clear pixel, set manual bid). It also states the prerequisite (channel must be enabled via create_campaign/add_and_edit_campaign_elements) and the draft-only constraint. It does not, however, explicitly name sibling alternatives to exclude, which would push this to a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_target_groupUpdate Target GroupADestructiveInspect
Update existing target group with new name and/or targeting criteria. Supports BOTH include AND exclude rules — including adding/removing exclude audiences.
CRITICAL - PUT REQUEST: You MUST provide ALL fields, not just changed ones.
'name' is ALWAYS REQUIRED even if not changing
If updating targeting, provide complete targeting object (full include + exclude)
Always retrieve current config first via retrieve_target_group_by_id and merge changes onto it
PREREQUISITE WORKFLOW:
list_target_groups(name="X") → get ID
retrieve_target_group_by_id(target_group_id=ID) → get current config, check isModifiable fields, copy existing exclude audiences
search_target_group_criteria → get new criteria IDs
estimate_target_group → MANDATORY: verify isMatchCountTooSmall=false
update_target_group with ID and ALL required fields (full targeting object)
MODIFIABILITY: Name always modifiable. LOCATION usually isModifiable=false. Check retrieve_target_group_by_id response for other fields.
TARGETING STRUCTURE: Same as create_target_group — full include array + single exclude object containing both criteria and audiences. See create_target_group description for the full example payload (with NATIVE_LOCATION, AGE, COMPANY_NAME exclude criteria, and FIRMOGRAPHIC_EXCLUDE audience). Only update criteria with isModifiable=true.
WARNING: AUDIENCES ≠ TARGET GROUPS. Both include[].audiences and exclude.audiences accept Custom Audience records ONLY (the entities returned by get_matched_audiences). Target Groups (the entities returned by list_target_groups / retrieve_target_group_by_id) are a separate entity in a separate ID space and CANNOT be attached here; the platform silently drops or rejects them. If the user names "X" and only list_target_groups matches it (not get_matched_audiences), do NOT pass the Target Group's id as mdAudienceId. Stop, tell the user "X is a Target Group, not a Custom Audience", and offer to rebuild X as a Custom Audience (e.g. via create_audiences with the same criteria) before retrying.
ADDING/REMOVING EXCLUDE AUDIENCES: Provide the COMPLETE desired exclude.audiences array. Each entry needs: mdAudienceId (integer, REQUIRED — the numeric Custom Audience id like 49067 from get_matched_audiences, its customAudienceId / mdAudienceId field, NEVER that row's id, NEVER the audience name string, NEVER a placeholder like 1/2/3/4 (rejected pre-flight), and NEVER a Target Group id from list_target_groups; see the AUDIENCES ≠ TARGET GROUPS note above), name, type (EXCLUDE variant like FIRMOGRAPHIC_EXCLUDE/RETARGETING_EXCLUDE/CONTACT_LIST_EXCLUDE), matchCount, matchCountType, inactive, and the audience's own criteria array. To remove an exclusion, omit it from the array. To add one, append it.
RESPONSE: {id, name, channel, audienceSize, status, modifiedDate, targeting}
VALIDATION: Must estimate first and verify isMatchCountTooSmall=false before updating.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | REQUIRED: Target group name. CRITICAL - This is a PUT request so you MUST provide the name even if not changing it. Use retrieve_target_group_by_id to get the current name if you don't have it. | |
| targeting | No | Updated targeting configuration (optional). Structure must match create_target_group format. Only update criteria that have isModifiable=true in the current configuration. All criteria IDs/references must come from search_target_group_criteria tool. REQUIRED: Must estimate this targeting first and verify isMatchCountTooSmall is false. NOTE: This is a PUT request - if the target group has targeting, you should provide the complete targeting object. | |
| target_group_id | Yes | The unique ID of the target group to update. Must be a positive integer. Use list_target_groups to find the ID by name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only indicate readOnlyHint=false and destructiveHint=true, but the description adds critical behavioral context: PUT request semantics requiring all fields, modifiability checks via isModifiable, the need to merge with current config, and the requirement to estimate and verify isMatchCountTooSmall. It also explains the response format. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but highly structured with clear sections (CRITICAL, PREREQUISITE WORKFLOW, MODIFIABILITY, TARGETING STRUCTURE, WARNING, ADDING/REMOVING EXCLUDE AUDIENCES, RESPONSE, VALIDATION). Critical information is front-loaded, and each paragraph serves a distinct purpose. No redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity—PUT semantics, nested targeting, audience type distinctions—the description covers all necessary context: prerequisites, workflow, modifiability, full example reference, response format, and validation steps. With no output schema, the response description fills that gap. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
While the schema covers all three parameters with descriptions, the tool description significantly enriches them: explains that 'name' is always required even if unchanged, details the targeting structure (include array + exclude object), specifies the exact fields needed for exclude audiences (mdAudienceId, name, type, matchCount, etc.), and warns about invalid values. This goes well beyond the schema's generic descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Update existing target group with new name and/or targeting criteria.' It also clarifies scope by supporting include and exclude rules, and distinguishes itself from create_target_group and retrieve_target_group_by_id by name. The purpose is unmistakable and differentiates from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit prerequisite workflow with numbered steps, including listing, retrieving, searching criteria, and mandatory estimation before updating. It also warns when not to pass target group IDs as audiences and instructs to stop and inform the user if the entity is a Target Group, not a Custom Audience. Clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_account_list_csv_audienceUpload Account List CSV and Create AudienceAInspect
Upload a list of company ACCOUNTS (name + website) as an Account List CSV and create a FIRMOGRAPHIC_INCLUDE audience on the Metadata platform, optionally overlaid with platform-side contacts criteria.
AUDIENCE TYPE: Account List CSV / CSV Upload - Accounts (platform stores `customAudienceType=FIRMOGRAPHIC_INCLUDE`; the main UI's audience-map renders this enum as "CSV Upload - Accounts").
This tool is ONLY for company/account-level data (company names and websites).
Do NOT use this tool for contact-level data (emails, phone numbers, individual people).
For contacts, use upload_contact_list_csv_audience instead.
TWO WAYS TO SUPPLY THE ACCOUNT LIST — provide EXACTLY ONE of:
• `companies`: an inline JSON object map `{ "<companyname>": "<companywebsite>", ... }`. Use this for short ad-hoc lists you have already parsed into context.
• `companies_source_csv_url`: a public URL of a CSV file with header EXACTLY `companyname,companywebsite` (case-insensitive, whitespace-trimmed). Use this WHENEVER THE USER ATTACHED A CSV to the chat — the URL is surfaced to you via `AudienceBrief.attached_file_urls`; pass it through verbatim. The MCP server downloads + validates + parses the CSV so a multi-megabyte file never has to travel through your context.
If both are provided, or neither, the tool errors with a clear message — pick one.
OPTIONAL CONTACTS CRITERIA: layer per-contact filters on top of the account list, matching the same shape `create_firmographic_audience` uses:
• `location_country_ids` / `location_state_ids` — geography
• `job_title_includes` / `job_title_excludes` — free-text title keywords
• `job_function_include_ids` / `job_function_exclude_ids`
• `seniority_include_ids` / `seniority_exclude_ids`
• `contacts_per_company_limit`
When set, the resulting audience matches only contacts inside the listed companies that ALSO satisfy these filters — e.g. "this 1,999-account list, but only VP/Director/Manager Engineering contacts in Canada + Saint Pierre and Miquelon + United States" becomes a single call. When all of these are omitted, every contact in every uploaded company is matched.
WHEN TO USE:
- "Upload these companies/accounts as an audience" / "Create an account list audience" / "Upload account list CSV"
- "Create a CSV Upload - Accounts audience with this CSV and these contact filters"
- The user attached a CSV of companies (company name + website) and asked for a CSV-Upload audience
WHEN NOT TO USE:
- When the data is contact-level (emails, phone numbers, individual people) — use `upload_contact_list_csv_audience`.
- For pure firmographic targeting without an attached account list — use `create_firmographic_audience`.
INLINE-MAP DATA MAPPING RULES (when you choose the `companies` path):
- Each KEY must be the **company name**; each VALUE must be the **company website URL**.
- Format: { "<companyname>": "<companywebsite>", ... }
- Example:
{
"Acme Corp": "https://acme.com",
"Globex International": "https://globex.com",
"Salesforce": "https://salesforce.com"
}
- DO NOT pass column headers as keys; DO NOT reverse the mapping; DO NOT send raw file paths or bytes.
CSV-URL HEADER RULES (when you choose the `companies_source_csv_url` path):
- The first row of the CSV MUST be exactly `companyname,companywebsite` (case-insensitive — `Company Name,Website` is rejected; rename the columns first or fall back to the inline map path).
- Rows with an empty company name are dropped server-side.
- The server enforces a 50 MB cap on the downloaded file.
PARAMETERS:
- audience_name (required)
- companies (optional, mutually exclusive with companies_source_csv_url)
- companies_source_csv_url (optional, mutually exclusive with companies)
- location_country_ids / location_state_ids (optional contacts criteria)
- job_title_includes / job_title_excludes (optional)
- job_function_include_ids / job_function_exclude_ids (optional)
- seniority_include_ids / seniority_exclude_ids (optional)
- contacts_per_company_limit (optional)
RETURNS:
- success, id / audience_id, audience_name, audience_type (FIRMOGRAPHIC_INCLUDE), file_id, companies_count, upload_filename, expectedNumberOfCompanies, expectedNumberOfContacts, cappedContactCount
IMPORTANT NOTES:
- There is a small delay between upload and audience creation while the platform processes the file; the tool waits for that internally.
- The companies map / source CSV must contain at least one usable row.
- Company websites should be valid URLs (e.g., https://example.com).| Name | Required | Description | Default |
|---|---|---|---|
| companies | No | Inline map of company names to website URLs (optional). Example: {"Acme Corp": "https://acme.com", "Globex": "https://globex.com"}. MUTUALLY EXCLUSIVE with `companies_source_csv_url` — provide exactly one. | |
| audience_name | Yes | Name for the new audience (required). | |
| job_title_excludes | No | Free text keywords for job titles to exclude (optional). Example: ['Senior', 'Lead'] | |
| job_title_includes | No | Free text keywords for job titles to include (optional). Example: ['Software Engineer', 'Manager'] | |
| location_state_ids | No | State IDs for geographic targeting (optional). Valid US State IDs: 1 (Alabama), 2 (Alaska), 3 (Arizona), 4 (Arkansas), 5 (California), 6 (Colorado), 7 (Connecticut), 8 (Delaware), 9 (Florida), 10 (Georgia), 11 (Hawaii), 12 (Idaho), 13 (Illinois), 14 (Indiana), 15 (Iowa), 16 (Kansas), 17 (Kentucky), 18 (Louisiana), 19 (Maine), 20 (Maryland), 21 (Massachusetts), 22 (Michigan), 23 (Minnesota), 24 (Mississippi), 25 (Missouri), 26 (Montana), 27 (Nebraska), 28 (Nevada), 29 (New Hampshire), 30 (New Jersey), 31 (New Mexico), 32 (New York), 33 (North Carolina), 34 (North Dakota), 35 (Ohio), 36 (Oklahoma), 37 (Oregon), 38 (Pennsylvania), 39 (Rhode Island), 40 (South Carolina), 41 (South Dakota), 42 (Tennessee), 43 (Texas), 44 (Utah), 45 (Vermont), 46 (Virginia), 47 (Washington), 48 (West Virginia), 49 (Wisconsin), 50 (Wyoming), 52 (District of Columbia). Example: [5] for California, [32] for New York | |
| location_country_ids | No | Country IDs for geographic targeting (optional). Valid IDs: 1 (Afghanistan), 2 (Albania), 3 (Algeria), 4 (American Samoa), 5 (Andorra), 6 (Angola), 7 (Anguilla), 8 (Antarctica), 9 (Antigua and Barbuda), 10 (Argentina), 11 (Armenia), 12 (Aruba), 13 (Australia), 14 (Austria), 15 (Azerbaijan), 16 (Bahamas), 17 (Bahrain), 18 (Bangladesh), 19 (Barbados), 20 (Belarus), 21 (Belgium), 22 (Belize), 23 (Benin), 24 (Bermuda), 25 (Bhutan), 26 (Bolivia), 27 (Bosnia and Herzegovina), 28 (Botswana), 29 (Brazil), 30 (British Indian Ocean Territory), 31 (British Virgin Islands), 32 (Brunei), 33 (Bulgaria), 34 (Burkina Faso), 35 (Burundi), 36 (Cambodia), 37 (Cameroon), 38 (Canada), 39 (Cape Verde), 40 (Cayman Islands), 41 (Central African Republic), 42 (Chad), 43 (Chile), 44 (China), 45 (Christmas Island), 46 (Cocos Islands), 47 (Colombia), 48 (Comoros), 49 (Cook Islands), 50 (Costa Rica), 51 (Croatia), 53 (Curacao), 54 (Cyprus), 55 (Czech Republic), 56 (Democratic Republic of the Congo), 57 (Denmark), 58 (Djibouti), 59 (Dominica), 60 (Dominican Republic), 61 (East Timor), 62 (Ecuador), 63 (Egypt), 64 (El Salvador), 65 (Equatorial Guinea), 66 (Eritrea), 67 (Estonia), 68 (Ethiopia), 69 (Falkland Islands), 70 (Faroe Islands), 71 (Fiji), 72 (Finland), 73 (France), 74 (French Polynesia), 75 (Gabon), 76 (Gambia), 77 (Georgia), 78 (Germany), 79 (Ghana), 80 (Gibraltar), 81 (Greece), 82 (Greenland), 83 (Grenada), 84 (Guam), 85 (Guatemala), 86 (Guernsey), 87 (Guinea), 88 (Guinea-Bissau), 89 (Guyana), 90 (Haiti), 91 (Honduras), 92 (Hong Kong), 93 (Hungary), 94 (Iceland), 95 (India), 96 (Indonesia), 98 (Iraq), 99 (Ireland), 100 (Isle of Man), 101 (Israel), 102 (Italy), 103 (Ivory Coast), 104 (Jamaica), 105 (Japan), 106 (Jersey), 107 (Jordan), 108 (Kazakhstan), 109 (Kenya), 110 (Kiribati), 111 (Kosovo), 112 (Kuwait), 113 (Kyrgyzstan), 114 (Laos), 115 (Latvia), 116 (Lebanon), 117 (Lesotho), 118 (Liberia), 119 (Libya), 120 (Liechtenstein), 121 (Lithuania), 122 (Luxembourg), 123 (Macau), 124 (Macedonia), 125 (Madagascar), 126 (Malawi), 127 (Malaysia), 128 (Maldives), 129 (Mali), 130 (Malta), 131 (Marshall Islands), 132 (Mauritania), 133 (Mauritius), 134 (Mayotte), 135 (Mexico), 136 (Micronesia), 137 (Moldova), 138 (Monaco), 139 (Mongolia), 140 (Montenegro), 141 (Montserrat), 142 (Morocco), 143 (Mozambique), 144 (Myanmar), 145 (Namibia), 146 (Nauru), 147 (Nepal), 148 (Netherlands), 149 (Netherlands Antilles), 150 (New Caledonia), 151 (New Zealand), 152 (Nicaragua), 153 (Niger), 154 (Nigeria), 155 (Niue), 157 (Northern Mariana Islands), 158 (Norway), 159 (Oman), 160 (Pakistan), 161 (Palau), 162 (Palestine), 163 (Panama), 164 (Papua New Guinea), 165 (Paraguay), 166 (Peru), 167 (Philippines), 168 (Pitcairn), 169 (Poland), 170 (Portugal), 171 (Puerto Rico), 172 (Qatar), 173 (Republic of the Congo), 174 (Reunion), 175 (Romania), 176 (Russia), 177 (Rwanda), 178 (Saint Barthelemy), 179 (Saint Helena), 180 (Saint Kitts and Nevis), 181 (Saint Lucia), 182 (Saint Martin), 183 (Saint Pierre and Miquelon), 184 (Saint Vincent and the Grenadines), 185 (Samoa), 186 (San Marino), 187 (Sao Tome and Principe), 188 (Saudi Arabia), 189 (Senegal), 190 (Serbia), 191 (Seychelles), 192 (Sierra Leone), 193 (Singapore), 194 (Sint Maarten), 195 (Slovakia), 196 (Slovenia), 197 (Solomon Islands), 198 (Somalia), 199 (South Africa), 200 (South Korea), 201 (South Sudan), 202 (Spain), 203 (Sri Lanka), 205 (Suriname), 206 (Svalbard and Jan Mayen), 207 (Swaziland), 208 (Sweden), 209 (Switzerland), 211 (Taiwan), 212 (Tajikistan), 213 (Tanzania), 214 (Thailand), 215 (Togo), 216 (Tokelau), 217 (Tonga), 218 (Trinidad and Tobago), 219 (Tunisia), 220 (Turkey), 221 (Turkmenistan), 222 (Turks and Caicos Islands), 223 (Tuvalu), 224 (U.S. Virgin Islands), 225 (Uganda), 226 (Ukraine), 227 (United Arab Emirates), 228 (United Kingdom), 229 (United States), 230 (Uruguay), 231 (Uzbekistan), 232 (Vanuatu), 233 (Vatican), 234 (Venezuela), 235 (Vietnam), 236 (Wallis and Futuna), 237 (Western Sahara), 238 (Yemen), 239 (Zambia), 240 (Zimbabwe), 241 (Guadeloupe). Example: [29] for Brazil, [229] for United States | |
| seniority_exclude_ids | No | Seniority level IDs to exclude (optional). Valid IDs: 2-11 as listed above | |
| seniority_include_ids | No | Seniority level IDs to include (optional). Valid IDs: 2 (Manager), 3 (Director), 4 (VP), 5 (CXO), 6 (Unpaid), 7 (Training), 8 (Senior), 9 (Owner), 10 (Entry), 11 (Partner). Example: [10, 7] for Entry and Training | |
| companies_source_csv_url | No | Public URL of a CSV file with header EXACTLY `companyname,companywebsite` (case-insensitive). The MCP server downloads, validates, and parses the file. Use this when the user attached a CSV to the chat — the URL is surfaced via `AudienceBrief.attached_file_urls`. MUTUALLY EXCLUSIVE with `companies`. | |
| job_function_exclude_ids | No | Job function IDs to exclude (optional). Valid IDs: 1-28 as listed above | |
| job_function_include_ids | No | Job function IDs to include (optional). Valid IDs: 1 (Marketing), 2 (Sales), 3 (Customer Service), 4 (Finance), 5 (HR), 6 (PR), 7 (Media), 8 (Design), 9 (Engineering), 10 (Operations), 11 (Legal), 12 (Education), 13 (Health), 14 (Real Estate), 15 (Accounting), 16 (Administrative), 17 (Business Development), 18 (Community Services), 19 (Consulting), 20 (Entrepreneurship), 21 (IT), 22 (Military Services), 23 (Product Management), 24 (Program/Project Management), 25 (Purchasing), 26 (QA), 27 (Research), 28 (Trades). Example: [9] for Engineering | |
| contacts_per_company_limit | No | Maximum number of contacts to target per company (optional). Example: 20 |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, destructiveHint=false), the description discloses a processing delay that the tool waits through, a 50 MB CSV size cap, server-side dropping of empty rows, mutual-exclusivity error conditions, and the specific return fields. This goes well beyond what the annotations already provide and gives the agent a clear picture of side effects and constraints. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely long, but it is well-organized with clear sections, bolded terms, and bullets. It front-loads the core purpose and the crucial contact-level exclusion. Some redundancy exists (e.g., the PARAMETERS summary repeats schema names), but the structure makes the length navigable and each substantive rule earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 12 parameters, no output schema, and two input modes, the description covers all critical context: input format requirements, error conditions for invalid combos, processing behavior, size limits, return fields, and example use cases. An agent could correctly invoke this tool in both the inline-map and CSV-URL scenarios without needing additional information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, yet the description adds substantial meaning: it fully explains the two mutually exclusive supply paths, gives explicit data mapping rules and CSV header requirements, provides an inline example, and describes how optional contacts criteria layer on top of the account list. This is far beyond the baseline schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: upload an account list CSV and create a FIRMOGRAPHIC_INCLUDE audience. It explicitly distinguishes from contact-level uploads and pure firmographic targeting by naming upload_contact_list_csv_audience and create_firmographic_audience, so an agent can tell this tool apart without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It has dedicated WHEN TO USE and WHEN NOT TO USE sections that list example phrasings and name the alternative tools for contact-level data and firmographic targeting. It also explains the two mutually exclusive input paths and directs the agent to use the CSV URL whenever the user attached a CSV, which removes ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_contact_list_csv_audienceUpload Contact List CSV and Create Contact List AudienceAInspect
Upload a list of individual CONTACTS (people) as a Contact List CSV and create a CONTACT_LIST audience on the Metadata platform.
ALSO KNOWN AS: "CSV Upload - Contacts", "Contacts List", "Contact List CSV", "CSV Contacts audience", "CSV Upload - Contacts List Audience".
AUDIENCE TYPE: Contact List / CSV Upload - Contacts.
This tool is ONLY for contact/people-level data (email, first name, last name, job title, etc.).
Do NOT use this tool for company/account-level data (company names and websites) — use upload_account_list_csv_audience instead.
This tool performs a two-step process:
1. Generates a Contact List CSV file from the provided contact data and uploads it.
2. Creates a CONTACT_LIST audience using the uploaded contact list file.
WHEN TO USE:
- "Create a CSV Upload - Contacts with the list"
- "CSV Upload - Contacts"
- "Create a contacts list audience"
- "Upload these contacts as an audience"
- "Create a contact list audience from these people"
- "I have a list of emails and names, create an audience"
- "Build a contact list audience"
- "Upload contact list CSV"
- When the data contains people-level fields: email, first name, last name, job title, company, country
WHEN NOT TO USE:
- When the user wants to upload company accounts (company name + website) — use upload_account_list_csv_audience.
- When the data is account/company-level, not contact/people-level.
WORKFLOW:
1. Provide the audience name and an array of contact objects.
2. The tool generates a CSV with the header: email,firstname,lastname,jobtitle,employeecompany,country,appleidfa,googleaid
3. Uploads the CSV, then creates the CONTACT_LIST audience.
CRITICAL — DATA MAPPING RULES (READ CAREFULLY BEFORE CALLING THIS TOOL):
The "contacts" parameter is a JSON array of objects. Each object represents one contact/person
and MUST use these exact field names:
- "email" → The contact's email address (REQUIRED per contact)
- "firstname" → The contact's first name
- "lastname" → The contact's last name
- "jobtitle" → The contact's job title / role
- "employeecompany" → The company the contact works at
- "country" → The contact's country
- "appleidfa" → Apple IDFA (advertising identifier), optional
- "googleaid" → Google Advertising ID, optional
Example:
[
{
"email": "jane@metadata.io",
"firstname": "Jane",
"lastname": "Johnson",
"jobtitle": "Marketing Manager",
"employeecompany": "Metadata.io",
"country": "United States",
"appleidfa": "EA7583CD-A667-48BC-B806-42ECB2B48606",
"googleaid": ""
},
{
"email": "john@metadata.io",
"firstname": "John",
"lastname": "Johnson",
"jobtitle": "Marketing Manager",
"employeecompany": "Metadata.io",
"country": "United States",
"appleidfa": "",
"googleaid": "cdda802e-fb9c-47ad-9866-0794d394c912"
}
]
IF THE USER PROVIDES A FILE (CSV, XLSX, spreadsheet, or any tabular data):
1. You MUST first read and inspect the file contents.
2. Identify which columns map to: email, firstname, lastname, jobtitle, employeecompany, country, appleidfa, googleaid.
- The columns may NOT be literally named as above. They could be named:
"Email Address", "E-mail", "First Name", "First", "Last Name", "Surname",
"Job Title", "Title", "Role", "Position", "Company", "Organization", "Employer",
"Country", "Location", "Apple IDFA", "IDFA", "Google AID", "GAID", or any variation.
- Use your best judgment to map the correct columns to the expected field names.
- If ambiguous, ask the user to clarify which column maps to which field.
3. Extract every row from the file and build the contacts array yourself,
mapping each column value to the correct field name.
4. Do NOT pass raw file contents, column headers, or file paths — always transform into
the array-of-objects format described above.
5. Skip rows where email is empty/missing (email is the minimum required field per contact).
6. For any field not present in the source data, omit it or pass an empty string.
7. If the file has no identifiable email column, ask the user which column contains emails.
DO NOT:
- Use the source file's column names as field names — always normalize to: email, firstname, lastname, jobtitle, employeecompany, country, appleidfa, googleaid.
- Send the raw file path or file bytes — extract the data and build the array.
- Confuse this with account/company uploads — this is for PEOPLE, not companies.
TWO WAYS TO SUPPLY THE CONTACTS — provide EXACTLY ONE of:
• `contacts`: an inline JSON array of contact objects. Use this for short ad-hoc lists you have already parsed into context.
• `contacts_source_csv_url`: a public URL of a CSV file with header EXACTLY `email,firstname,lastname,jobtitle,employeecompany,country,appleidfa,googleaid` (case-insensitive, whitespace-trimmed). Use this WHENEVER THE USER ATTACHED A CSV to the chat — the URL is surfaced to you via `AudienceBrief.attached_file_urls`; pass it through verbatim. The MCP server downloads + validates + uploads the file without the rows ever travelling through your LLM context (essential for 100k+ row contact files).
If both are provided, or neither, the tool errors with a clear message — pick one.
CSV-URL HEADER RULES (when you choose the `contacts_source_csv_url` path):
- First row of the CSV MUST be exactly `email,firstname,lastname,jobtitle,employeecompany,country,appleidfa,googleaid` (case-insensitive).
- Rows with an empty email are dropped server-side before counting.
- The 300–300,000 row limit is enforced on the post-filter count.
- The server enforces a 50 MB cap on the downloaded file.
PARAMETERS:
- audience_name: Name for the new contact list audience (required)
- contacts: Array of contact objects (optional, mutually exclusive with contacts_source_csv_url).
At minimum each contact must have "email". All other fields are optional but recommended.
- contacts_source_csv_url: URL of a contacts CSV with the canonical 8-column header (optional, mutually exclusive with contacts).
RETURNS:
- success: Whether the operation completed successfully
- audience_name: The name of the created audience
- audience_type: CONTACT_LIST
- file_id: The ID of the uploaded contact list file
- contacts_count: Number of contacts processed by the backend
- contacts_provided: Number of contacts sent in the request
IMPORTANT NOTES:
- CONTACT LIMITS: Minimum 300 contacts, maximum 300,000 contacts.
- Email is the minimum required field per contact — contacts without email are dropped.
- The audience type created is CONTACT_LIST, distinct from Account List CSV (FIRMOGRAPHIC_INCLUDE).
- appleidfa and googleaid are optional mobile advertising identifiers — leave empty if not available.| Name | Required | Description | Default |
|---|---|---|---|
| contacts | No | Inline array of contact objects (optional). Each object represents one person/contact with fields: email (required), firstname, lastname, jobtitle, employeecompany, country, appleidfa, googleaid. Minimum 300 contacts, maximum 300,000 contacts. MUTUALLY EXCLUSIVE with `contacts_source_csv_url` — provide exactly one. | |
| audience_name | Yes | Name for the new contact list audience (required). | |
| contacts_source_csv_url | No | Public URL of a contacts CSV file with header EXACTLY `email,firstname,lastname,jobtitle,employeecompany,country,appleidfa,googleaid` (case-insensitive). The MCP server downloads, validates, and uploads the file. Use this when the user attached a CSV to the chat — the URL is surfaced via `AudienceBrief.attached_file_urls`. MUTUALLY EXCLUSIVE with `contacts`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate it is not read-only (readOnlyHint=false) and not destructive (destructiveHint=false), so the description goes far beyond by disclosing the two-step process (generate/upload CSV then create audience), constraints (min 300, max 300,000 rows, 50 MB cap), server-side row dropping for empty emails, and precise data mapping rules. This is rich behavioral context not available in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear headers and front-loaded purpose, but it is very long (over 1000 words). Some repetition exists (e.g., the 'DO NOT' section repeats points from the mapping rules). Nonetheless, the complexity justifies much of the detail, and the organized sections make it navigable. It earns a 4, not 5, due to occasional redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity, the description covers all necessary aspects: usage intent, input methods, data transformation rules, limits, return fields (since there is no output schema), and error conditions (mutual exclusivity). It is comprehensive enough for an agent to call it correctly without external references.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, yet the description adds significant meaning: it details the exact field names and normalization requirements for the contacts array, explains the mutual exclusivity of the two parameters, and specifies the CSV header rules. For contacts_source_csv_url, it clarifies the exact header format and that the server handles download/validation, which is not evident from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear, specific action: 'Upload a list of individual CONTACTS (people) as a Contact List CSV and create a CONTACT_LIST audience on the Metadata platform.' It distinguishes itself from the sibling upload_account_list_csv_audience by explicitly stating 'Do NOT use this tool for company/account-level data — use upload_account_list_csv_audience instead.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes explicit 'WHEN TO USE' and 'WHEN NOT TO USE' sections, listing concrete user intents and the alternative tool for account-level data. It also provides detailed guidance on the two input methods (inline JSON vs. CSV URL) and when to choose each, including the case of attached CSV files.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_document_creativeUpload Document CreativeAInspect
Upload PDF documents to the Metadata platform library so they can be promoted as LinkedIn Document Ads. Downloads each PDF from its URL and uploads it to the platform library as a DOCUMENT asset.
WARNING: PDF-ONLY: the downloaded file MUST have the `application/pdf` content-type
and be at most 100 MB (platform limits for document assets). Images go through
`upload_image_creative`, videos through `upload_video_creative`.
WARNING: WHEN YOU NEED TO CALL THIS:
Call this BEFORE `create_update_document_ad` ONLY when the document is not in the
library yet. If `search_library_creatives_by_name(contentTypes="DOCUMENT")` already
finds it, pass that id straight to `create_update_document_ad` as `libraryId`.
WORKFLOW INTEGRATION (when an upload IS needed):
1. Upload the PDF URL with this tool -> response contains the integer `id` (the library id).
2. Pass that integer `id` as `libraryId` in `create_update_document_ad`.
REQUIRED PARAMETERS:
- documents: Array of publicly accessible PDF URLs.
OPTIONAL PARAMETERS:
- names: Library label per document, positional against `documents`. Defaults to the
file name from the URL. Use the document's real title ("2026 B2B Benchmark Report")
so the library stays readable.
RESPONSE FORMAT:
Returns array of objects, one per document. `id` is returned as a string; pass it to
`create_update_document_ad` as an integer.
[
{"url": "https://example.com/report.pdf", "name": "2026 B2B Benchmark Report", "id": "15791", "success": true},
{"url": "https://example.com/bad.pdf", "name": "bad.pdf", "id": null, "success": false, "error": "..."}
]
ERROR HANDLING:
- If one upload fails, others continue.
- A content-type other than application/pdf is rejected with a clear error.
| Name | Required | Description | Default |
|---|---|---|---|
| names | No | Optional library labels, one per document in the same order. | |
| documents | Yes | Array of PDF URLs to upload to the platform library. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes beyond the annotations by explaining that the tool downloads each PDF, enforces application/pdf content-type and 100 MB limits, returns per-document success/failure objects, and continues processing after individual failures. It also discloses the id string-to-integer conversion quirk, which is critical for correct downstream use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear sections: purpose, warnings, workflow integration, parameters, response format, and error handling. Every sentence contributes operational knowledge, and the critical workflow steps are explicitly numbered.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the description fully compensates by showing the response format with examples, explaining error conditions, and walking through the integration with create_update_document_ad. Nothing an agent needs to call this tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description adds meaning: documents must be publicly accessible PDF URLs, names are positional against documents, default to the URL file name, and should use the real document title. This materially improves an agent's ability to supply high-quality input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: uploads PDF documents into the Metadata platform library as DOCUMENT assets for LinkedIn Document Ads. It explicitly distinguishes itself from sibling upload_image_creative and upload_video_creative via the PDF-only warning.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: call only when the document is not yet in the library, after checking search_library_creatives_by_name, and before create_update_document_ad. It also names the alternatives for non-PDF assets, leaving no ambiguity about tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_image_creativeUpload Image CreativeAInspect
Upload images directly to Metadata platform library to create image creatives. Downloads images from provided URLs and uploads them to the platform. REQUIRED STEP IN AD CREATION WORKFLOW: This tool MUST be called between generate_brand_creative and create_update_image_ad. WORKFLOW INTEGRATION: This tool is part of the ad creation workflow and should be used: 1. BEFORE creating ads with create_update_image_ad (which requires imageLibraryId/creativeID) 2. IN COMBINATION with generate_brand_creative to create AI-generated images first, then upload them 3. When you need to upload existing images from external sources
**COMMON WORKFLOWS:**
- Upload existing images → Get imageLibraryId → Use in create_update_image_ad
- Generate image with generate_brand_creative → Download generated image → Upload with this tool → Use in create_update_image_ad
- Batch upload multiple creative assets for campaign preparation
**IMPORTANT:** The returned image ID (imageLibraryId/creativeID) is REQUIRED when creating ads.
Every ad needs a creative asset, so you must upload images first before calling create_update_image_ad.
REQUIRED PARAMETERS:
- images: Array of image URLs to upload
IMAGE REQUIREMENTS:
- URLs must be valid and publicly accessible
- Supported formats: PNG, JPG, JPEG, GIF, WebP, and others
- Images will be downloaded and then uploaded to platform
- Filenames with spaces will have spaces replaced with underscores
EXAMPLES:
Single Image:
upload_image([
"https://my-bucket.s3.amazonaws.com/images/sample-image.png"
])
Multiple Images:
upload_image([
"https://my-bucket.s3.amazonaws.com/images/logo.png",
"https://example-assets.s3.us-west-2.amazonaws.com/photos/banner.jpg",
"https://content-bucket.s3.eu-west-1.amazonaws.com/uploads/hero image.webp"
])
RESPONSE FORMAT:
Returns array of objects for each image:
[
{
"url": "https://original-url.com/image.png",
"name": "image.png",
"id": 12345,
"success": true
},
{
"url": "https://failed-url.com/bad.png",
"name": "bad.png",
"id": null,
"success": false,
"error": "Download failed: Connection timeout"
}
]
ERROR HANDLING:
- If one upload fails, others will continue
- Each result includes success status
- Failed uploads include error message
- Successful uploads include platform image ID
USE CASES:
- Upload creative assets before creating ads
- Import images from external sources
- Batch upload multiple campaign images
- Migrate images from other platforms| Name | Required | Description | Default |
|---|---|---|---|
| names | No | Optional library name per image, positional against `images`. Pass one whenever you know what the creative is: without it the name is taken from the URL, which for a generated creative is an opaque key like `brand_creative_20260814_211126_66d8a83e.png` and leaves the user unable to tell their creatives apart in the library. Use `<brand-domain>-<channel>-<width>x<height>.png`, e.g. `stripe-com-linkedin-1200x1200.png`. A name MUST end in one of .jpg/.jpeg/.png/.gif/.mov/.mp4/.html/.pdf. | |
| images | Yes | Array of image URLs to upload to platform |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=false, the description correctly signals a mutating import operation and adds the download-from-URL mechanism, partial-failure behavior, success/failure response format, and filename underscore replacement. None of this repeats the annotations, and no contradictions exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but highly structured, with clear sections, bolded workflow directives, examples, response format, and error handling. It has some redundancy (the intro sentence, 'IMPORTANT' callout, and 'USE CASES' section repeat earlier points), but the front-loaded ordering and scannable bullets keep it effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, so the description compensates by documenting the exact response array shape, per-image success/failure fields, and error handling. It also covers prerequisites, downstream dependencies, and batch behavior, leaving an agent with enough information to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents both parameters at 100% coverage, so the description doesn't need to compensate; however, it adds beyond the schema by specifying supported formats (PNG/JPG/GIF/WebP), URL accessibility, and the underscore substitution behavior for filenames. The optional `names` parameter is not mentioned in the description, but its schema entry already contains detailed usage guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Upload images directly to Metadata platform library to create image creatives.' It names the downstream sibling create_update_image_ad and frames generate_brand_creative as a preceding step, which makes the tool's role in the ad workflow unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly declares 'REQUIRED STEP IN AD CREATION WORKFLOW' and states it 'MUST be called between generate_brand_creative and create_update_image_ad.' It also lists distinct use cases (existing images, generated images, batch uploads), giving the agent concrete conditions for invoking it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upload_video_creativeUpload Video CreativeAInspect
Upload videos directly to the Metadata platform library to create video creatives. Downloads videos from provided URLs and uploads them to the platform.
WARNING: VIDEO-ONLY: The downloaded file MUST have a `video/*` content-type
(e.g. video/mp4, video/quicktime). GIFs and image formats are
rejected — use `upload_image_creative` for those.
WARNING: WHEN YOU NEED TO CALL THIS:
Call this BEFORE `create_update_video_ad` ONLY when you don't already
have a videoLibraryId. If the user (or an earlier step) has
already given you a creativeID for the video, skip the upload
and pass that id straight to `create_update_video_ad`.
WORKFLOW INTEGRATION (when an upload IS needed):
1. Upload your video URL with this tool → response contains the integer `id` (the videoLibraryId).
2. Pass that integer `id` as `creativeID` in `create_update_video_ad`.
COMMON WORKFLOWS:
- Upload existing video → Get videoLibraryId → Use as creativeID in `create_update_video_ad`.
- For Reddit VIDEO ads, ALSO upload a thumbnail image via `upload_image_creative` and pass that image
library id as `redditThumbnailLibraryId` to `create_update_video_ad`.
REQUIRED PARAMETERS:
- videos: Array of video URLs to upload.
OPTIONAL PARAMETERS:
- thumbnail_library_id: Existing imageLibraryId to attach to the
uploaded video as its platform thumbnail. Most callers don't
need this — Reddit VIDEO ads handle thumbnails at ad-creation
time via `redditThumbnailLibraryId`, not here.
- usage_type: "CTV" to upload the video for a LinkedIn CTV
(Connected TV) ad. The platform then validates the file as CTV
inventory (6 to 60 seconds, 1920x1080 or 1280x720, at most
500 MB; LinkedIn recommends exactly 15, 30, 45 or 60 seconds)
and only such an upload can back `create_update_ctv_ad`. A
non-compliant file is rejected at upload with the platform's
reason. Omit for in-feed video ads.
VIDEO REQUIREMENTS:
- URLs must be valid and publicly accessible.
- Supported formats: MP4 (recommended), MOV, and other video/* MIME types.
- For GIFs (image/gif): use `upload_image_creative` instead.
RESPONSE FORMAT:
Returns array of objects, one per video. `id` is returned as a
string (the platform's library ids are integers but the upload
response stringifies them); pass it to `create_update_video_ad` as an
integer (Python `int(id)` if you need the cast).
[
{
"url": "https://example.com/video.mp4",
"name": "video.mp4",
"id": "12345", # videoLibraryId — use as creativeID in create_update_video_ad
"success": true
},
{
"url": "https://example.com/bad.mp4",
"name": "bad.mp4",
"id": null,
"success": false,
"error": "Download failed: Connection timeout"
}
]
ERROR HANDLING:
- If one upload fails, others continue.
- Each result includes a success flag and (on failure) an error message.
- A content-type that does not start with `video/` is rejected
with a clear error pointing the caller at `upload_image_creative`.
| Name | Required | Description | Default |
|---|---|---|---|
| videos | Yes | Array of video URLs to upload to the platform library. | |
| usage_type | No | Set to CTV when the video is for a LinkedIn Connected TV ad; the platform validates the CTV spec at upload. Omit for in-feed video ads. | |
| thumbnail_library_id | No | Optional existing imageLibraryId to attach as the video's platform thumbnail. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, openWorldHint=true, and destructiveHint=false. The description adds substantial behavioral detail: it downloads from URLs, validates content-type, returns a per-video array with success flags and error messages, and handles partial failures. It also discloses response type casting (id as string). This far exceeds what annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: warnings, workflow steps, common workflows, parameter explanations, response format, and error handling. It is front-loaded with the most critical warning (video-only) and the when-to-call rule. The use of headings and numbered lists keeps it scannable despite length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description provides a full response format example, including failure cases. It covers workflow integration with create_update_video_ad, prerequisites (public URLs, video/* MIME types), and error handling (partial success). Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description enriches each parameter: usage_type gets CTV-specific validation details (duration, resolution, size) and its role in create_update_ctv_ad; thumbnail_library_id is clarified with when it is needed versus when Reddit handles thumbnails. It adds actionable semantics beyond the schema's terse descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Upload videos directly to the Metadata platform library to create video creatives.' It clearly distinguishes from upload_image_creative by stating that GIFs and image formats are rejected and pointing to the sibling tool. This makes the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance: 'Call this BEFORE create_update_video_ad ONLY when you don't already have a videoLibraryId,' and instructs to skip upload if a creativeID is already available. It also names the alternative (upload_image_creative) for non-video content. These are concrete decision rules, not vague hints.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
website_engagement_statsGet Website Engagement StatisticsARead-onlyInspect
Website visitor engagement metrics: session data, page views, visitor behavior analytics.
USE FOR: Website traffic/engagement, visitor behavior analysis, session/page view metrics, website conversion funnel, engagement trends, website performance by period. NOT FOR: Campaign ad performance (use experiment_performance_stats), account list performance (use account_list_performance), budget groups (use budget_group_performance), geographic demographics (use demographic_country_stats).
TIMEFRAMES: YESTERDAY, LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_MONTH, MONTH_TO_DATE (default), LIFETIME
METRICS: sessions, uniqueVisitors, newVisitors, returningVisitors | pageViews, pagesPerSession, avgSessionDuration | bounceRate, exitRate, timeOnPage | conversions, conversionRate, goals
REQUIRED: Valid timeframe must be specified. Default: MONTH_TO_DATE if ambiguous.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number for pagination (0-based). Example: page=0 for the first page. | |
| size | No | Number of results per page. Default: 15; raise it (up to 10000) to pull the full engagement set in one call. | |
| sort | No | Sorting criteria. Examples: 'sessions,desc' (default), 'pageViews,desc', 'uniqueVisitors,desc', 'conversionRate,desc'. Format: field,direction where direction is 'asc' or 'desc'. | sessions,desc |
| dateRange | Yes | Timeframe for engagement data. Options: YESTERDAY, LAST_7_DAYS, LAST_14_DAYS, LAST_30_DAYS, LAST_MONTH, MONTH_TO_DATE (default), LIFETIME. REQUIRED parameter. | MONTH_TO_DATE |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is known. The description adds that a valid timeframe must be specified and defaults to MONTH_TO_DATE if ambiguous, and it enumerates the metric categories returned. These details go beyond the annotations by describing query scoping and output content.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear headings (USE FOR, NOT FOR, TIMEFRAMES, METRICS, REQUIRED). Each section delivers useful information without redundancy, and the one-line summary is front-loaded. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering the read-only safety profile and the schema detailing all four parameters, the description completes the picture by listing available metrics and valid timeframes, and by noting the mandatory timeframe requirement. It does not mention pagination behavior, but the schema's page/size parameters already address that. For a stats-read tool with no output schema, this is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description repeats the timeframe enum and default from the schema without adding new parameter-level meaning. The METRICS list implicitly relates to sort fields, but this is not explicit, so it does not raise the score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as providing website visitor engagement metrics, listing specific data types (session data, page views, visitor behavior analytics). The NOT FOR section explicitly distinguishes it from sibling tools like experiment_performance_stats and demographic_country_stats, so an agent can easily tell it apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The USE FOR block enumerates concrete use cases (website traffic/engagement, conversion funnel, engagement trends) and the NOT FOR block names excluded scenarios with exact sibling tool references. This gives explicit when-to-use and when-not-to-use guidance with alternatives, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
171 tool updates
- First observed
account_funnel_reports - First observed
account_level_stats - First observed
account_list_performance - First observed
add_and_edit_campaign_elements - First observed
add_and_edit_native_campaign_elements - First observed
add_extensions_to_native_campaign - First observed
add_keywords_to_negative_lists - First observed
add_negative_keyword_lists_to_live_campaigns - First observed
archive_ad - First observed
archive_audience - First observed
budget_group_performance - First observed
check_campaign_launch_readiness - First observed
connect_channel - First observed
connect_crm - First observed
create_audience_from_segment - First observed
create_bombora_audience - First observed
create_budget_group - First observed
create_campaign - First observed
create_csv_upload_linkedin_native_audience - First observed
create_facebook_native_criteria_audience - First observed
create_firmographic_audience - First observed
create_g2_intent_dynamic_audience - First observed
create_g2_intent_linkedin_native_dynamic_audience - First observed
create_g2_intent_static_audience - First observed
create_google_business_logo_extension - First observed
create_google_callout_extension - First observed
create_google_image_extension - First observed
create_google_lead_form_extension - First observed
create_google_price_extension - First observed
create_google_promotion_extension - First observed
create_google_sitelink_extension - First observed
create_google_structured_snippet_extension - First observed
create_keywords - First observed
create_linkedin_engagement_retargeting_audience - First observed
create_linkedin_native_criteria_audience - First observed
create_marketing_automation_contacts_audience - First observed
create_microsoft_business_logo_extension - First observed
create_microsoft_callout_extension - First observed
create_microsoft_image_extension - First observed
create_microsoft_price_extension - First observed
create_microsoft_promotion_extension - First observed
create_microsoft_sitelink_extension - First observed
create_microsoft_structured_snippet_extension - First observed
create_native_structure_campaign - First observed
create_negative_keywords_list - First observed
create_reddit_target_group - First observed
create_retargeting_audience - First observed
create_salesforce_contacts_audience - First observed
create_segment - First observed
create_target_group - First observed
create_technographic_audience - First observed
create_update_carousel_ad - First observed
create_update_convo_ad - First observed
create_update_ctv_ad - First observed
create_update_document_ad - First observed
create_update_google_ads_ad - First observed
create_update_image_ad - First observed
create_update_linkedin_message_ad - First observed
create_update_microsoft_ads_ad - First observed
create_update_offer - First observed
create_update_video_ad - First observed
deep_funnel_stats - First observed
delete_negative_keyword_lists - First observed
demographic_country_stats - First observed
disconnect_channel - First observed
duplicate_campaign - First observed
duplicate_negative_keywords_list - First observed
edit_brand_creative - First observed
enrich_company_domain - First observed
estimate_target_group - First observed
experiment_performance_stats - First observed
experiments_keywords_stats - First observed
fetch_creative_details - First observed
find_lookalike_companies - First observed
find_offer_url - First observed
find_privacy_url - First observed
fix_flexible_creative - First observed
generate_brand_creative - First observed
generate_brand_kit - First observed
generate_flexible_brand_creative - First observed
get_abm_account_lists - First observed
get_account_details - First observed
get_account_opportunities_insights - First observed
get_account_summary_insights - First observed
get_account_utm_defaults - First observed
get_ad_details - First observed
get_audience_details - First observed
get_brand_kit - First observed
get_budget_group - First observed
get_campaign_by_wizard_id - First observed
get_campaign_targeting_locations - First observed
get_campaign_utms - First observed
get_converted_leads_summary - First observed
get_credit_balance - First observed
get_credit_transactions - First observed
get_current_date - First observed
get_deep_audience_details - First observed
get_insights_report - First observed
get_integrations_status - First observed
get_intent_topics - First observed
get_linkedin_engagement_source_types - First observed
get_matched_audiences - First observed
get_negative_keywords_list_details - First observed
get_offer - First observed
get_payment_status - First observed
get_retargeting_audiences - First observed
get_segment_criteria - First observed
impersonate_account - First observed
launch_campaign - First observed
list_budget_groups - First observed
list_experiment_keywords - First observed
list_extensions - First observed
list_keywords - First observed
list_linkedin_conversions - First observed
list_marketing_automation_lists - First observed
list_negative_keywords_list - First observed
list_salesforce_mixed_criteria - First observed
list_search_terms - First observed
list_segments - First observed
list_target_groups - First observed
list_user_accounts - First observed
list_wizard_campaigns - First observed
manage_campaign - First observed
manage_experiment - First observed
pause_experiment_keyword - First observed
performance_metrics - First observed
query_metadata_analytics_account - First observed
query_metadata_analytics_benchmarks - First observed
regenerate_flexible_background - First observed
remove_ad_from_campaign - First observed
remove_audiences_from_campaign - First observed
remove_channels_from_campaign - First observed
remove_extensions_from_native_campaign - First observed
remove_keywords_from_campaign - First observed
remove_keywords_from_negative_list - First observed
remove_offers_from_campaign - First observed
remove_target_groups_from_campaign - First observed
render_flexible_creative - First observed
resolve_linkedin_ad_library_links - First observed
resolve_visitor_ip - First observed
restart_experiment_keyword - First observed
retrieve_target_group_by_id - First observed
search_ads_by_names - First observed
search_campaigns_by_names - First observed
search_campaigns_by_utm_value - First observed
search_experiment_recipes - First observed
search_experiments - First observed
search_insights_criteria_fields - First observed
search_library_creatives_by_name - First observed
search_linkedin_engagement_sources - First observed
search_reddit_criteria - First observed
search_target_group_criteria - First observed
set_campaign_utms - First observed
set_landing_subdomain - First observed
set_search_channel_final_url_suffix - First observed
set_search_channel_locations - First observed
stop_impersonation - First observed
unarchive_ad - First observed
unarchive_audience - First observed
update_brand_kit - First observed
update_experiments_daily_budgets - First observed
update_linkedin_channel_settings - First observed
update_meta_placements - First observed
update_reddit_channel_settings - First observed
update_target_group - First observed
upload_account_list_csv_audience - First observed
upload_contact_list_csv_audience - First observed
upload_document_creative - First observed
upload_image_creative - First observed
upload_video_creative - First observed
website_engagement_stats
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables detection and analysis of pre-public product launches through web search, content extraction, AI-powered scoring, and automated alerting. Provides comprehensive tools for surfacing stealth startup signals before they trend publicly.MIT

industrylens-mcpofficial
AlicenseNot gradedqualityBmaintenanceBrowse IndustryLens's published competitive-intelligence reports and head-to-head competitor comparisons from any AI agent — real, source-backed data.MIT- AlicenseNot gradedqualityBmaintenanceAnalyze LinkedIn & email outreach campaigns, track pipeline performance, and review lead conversations for RevOps, Sales Managers, and SDR teams.Apache 2.0
- AlicenseAqualityAmaintenanceDetects hiring intent signals by scanning job boards for specific companies. Returns structured role data for outbound sales targeting.1129 npm1MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.