v1.0.3 to v1.1.0

72 added, 11 removed. Audit A to A.

---
name: xnurta-create-ai-group
description: >-
Create a NEW AI managed group (托管组) for Amazon Sponsored ads and place campaigns
under it when required. Routes by ad type - SD via create_sd_ai_managed_group (campaigns
required); SP/SB via
save_sp_sb_ai_managed_group (create mode). Use when the user wants to create / set up /
新建 / 建一个 a managed group, or put campaigns under AI management for the first time,
even without the exact words "managed group". This creates the group itself - it is NOT
for enabling or editing an existing group (use xnurta-edit-ai-group) or deleting one (use
xnurta-delete-ai-group).
metadata:
- version: 1.0.3
+ version: 1.1.0
---
# Create AI Managed Group
Create a new AI managed group. SD creation requires campaigns; SP/SB creation may
create an empty group or include campaigns. This is a
**write, non-idempotent** operation: calling it twice creates two groups. Read
[`references/platform-notes.md`](references/platform-notes.md) once before your
first write - it covers auth, the shared response envelope, the 30s-timeout rule,
and how errors come back (`data.error` + an optional `recoveryHint` that isn't always
populated, so some stay generic).
## The one thing that decides everything: ad type
Creation logic differs by ad type, and they use **different tools**. Your first job
is always to determine the campaign type, then route:
| Ad type | Tool | Read before building the call |
|---|---|---|
| **SD** (Sponsored Display) | `create_sd_ai_managed_group` | [`references/create-sd.md`](references/create-sd.md) |
| **SP / SB** (Sponsored Products / Brands) | `save_sp_sb_ai_managed_group` (leave `aiGroupId` empty -> create mode) | [`references/create-sp-sb.md`](references/create-sp-sb.md) |
How to determine the ad type, in order of preference:
1. The user says it ("SP 托管组", "for my Sponsored Display campaigns").
2. Infer it from the campaigns to be added - look them up and read `campaignType`.
3. If still unknown, **ask the user** - don't guess. A group is created for one ad
type; picking the wrong tool creates the wrong kind of group.
> SP and SB both go through `save_sp_sb_ai_managed_group`, but a few capabilities
> are SP-only (see `create-sp-sb.md`). SB is not SP - don't copy SP-only fields
> into an SB group.
> **Reads use the full signature.** Every `get_entity_metadata` call requires
> `profileIds`, `entity`, and `userContext` -
> `get_entity_metadata(profileIds=[<id>], entity='campaign', userContext='<why>')`.
> The shorthand `get_entity_metadata(entity='campaign')` fails; always pass all three.
## Disambiguate before writing (when in doubt, ASK - don't guess)
Everyday words - in English OR Chinese - map to different fields. Before setting a value,
be sure which field the user means; if it could be more than one, list the options and
ask - don't guess.
This section lists **business meanings only** - the exact field depends on ad type, so
confirm the meaning first, then use the ad-type reference to pick the field.
- **"budget" / "预算"** - decide the sense AND whether it's a **target value** or an
**increase**:
- **托管组总预算 / group total budget** (= sum of the group's enabled campaigns' daily
budgets) and **a single campaign's daily budget** are **target values**. Note: **a
single campaign's daily budget cannot be set through the managed-group tools** (it's
campaign-level - use the platform).
- **按表现调预算 / performance (dynamic) budget** is an **increase cap on top of the
current budget, NOT a target** (fixed `+$num` or `+num%`); its scope depends on **预算
重新分配** (OFF = per enabled campaign; ON = whole group). See
[`references/coupling-rules.md`](references/coupling-rules.md).
- **预算重新分配 / budget reallocation** - a switch that also changes the scope of 按表现调预算.
Which field, at create time:
- **SD** uses `budget` + `budgetChange` (a boolean toggle) - **there is no `budgetType`
at create** (`budgetType`/`budgetRatio` are edit/batch only).
- **SP/SB create has no group-budget input at all** - only budget-related action-space
switches. If the user wants an SP/SB group's spend budget set at creation, tell them
that's not a create-time field here.
Never map "set budget to X" (a target) onto the dynamic-budget increase value; if the
meaning isn't clear, ask. When enabling 按表现调预算 at create, **set 预算重新分配
explicitly** - its scope (per-campaign vs whole-group) depends on it; don't rely on an
unknown default. To preview a cap, base it on the **enabled** campaigns among those
you're adding (use each one's `dailyBudget`).
- **"target / goal" / "目标"**: 推广目标 `targetType` (1 growth / 2 stability / 3 volume /
4 legacy) vs 目标 ACOS (`acos`). **Create has no `roas` field** - if the user says
"目标 ROAS", do NOT build `roas`; tell them create can't set a target ROAS directly, and
ask whether they want to set the promotion target or convert it to a target ACOS. Also:
"ACOS 优先模式 / ACOS priority" is the strict-ACOS switch (see the ACOS-priority item
below), **not** setting a target ACOS value - don't confuse them.
- **AI on/off at creation**: see "AI on vs off at creation" below - only start AI if the
user explicitly asked to create-and-start.
- **"ACOS 优先模式 / strict ACOS / ACOS priority"** (`bidPerformanceStrictAcosStatus`) - a
sub-switch of 按表现调价, **SP only**, and only triggers with `targetType=2` +
`bidPerformanceStatus=1` + `aiPersonality>=3`. It's a tradeoff (may underspend / reduce
orders) - confirm with the user before enabling. See
[`references/coupling-rules.md`](references/coupling-rules.md).
## Workflow (same for every ad type)
1. **Resolve inputs to IDs and codes.**
- **Campaigns -> internal `campaignId`.** Look them up with
`get_entity_metadata(profileIds=[...], entity='campaign', userContext='...')`.
Each row has both `campaignId` (internal auto-increment int) and
`amazonCampaignId` (Amazon's long string ID). **Always pass `campaignId` into
`campaignIds`; never `amazonCampaignId`** - the Amazon ID is a ~20-digit value
that overflows the int32 the tool expects and the call fails. The lookup also
gives each campaign's `campaignType` (routing) and `aiGroupId` (conflict check).
- **A `campaignId` from `get_ads_perf` may be the Amazon long ID, not the internal
one.** Never feed a `campaignId` taken from `get_ads_perf` straight into
`campaignIds` - first map it through `get_entity_metadata` (match on
`amazonCampaignId`) to the internal `campaignId`. Only the internal int works.
- **One profile, one ad type.** A create targets a single `profileId`, and every
campaign must belong to that profile and share the same `campaignType`. If the
user mixes profiles or mixes SP + SB (or gives a name that matches campaigns in
several stores), stop and clarify - don't silently pick a store or mis-route.
- **Chinese terms -> codes.** Map Chinese goal wording ("推动增长", "活动冲量",
"保持订单稳定", "激进人格") to the right field + code via
[`references/enum-i18n.md`](references/enum-i18n.md) before building the call,
and translate back when you confirm/report.
2. **Map the request to a single business meaning** (see "Disambiguate before writing").
Especially for budget/target wording, decide exactly what the user wants set and which
field it is (after ad type is known). **If more than one meaning is plausible, STOP and
ask - don't build a create on a guessed interpretation.**
3. **Pre-flight checks:**
- **Name uniqueness.** The `aiGroupName` filter is a `like` (substring) match, not
exact - query `get_entity_metadata(profileIds=[...], entity='aiGroup',
filters={"aiGroupName": {"like": "%<name>%"}}, userContext='...')`, then compare names
**exactly** in the returned rows. If an exact match exists, ask for a different
name rather than letting the create fail.
- - **Name not blank.** Reject a pure-whitespace / trims-to-empty name yourself - the
- UI blocks it, MCP doesn't.
+ - **Name not blank, and ≤ 200 characters.** Reject a pure-whitespace / trims-to-empty
+ name yourself - the UI blocks it, MCP doesn't. The UI also caps the name at **200
+ characters**; the API doesn't state a limit, so treat 200 as the safe ceiling and
+ shorten with the user's agreement rather than sending something longer. A duplicate
+ name comes back from the backend as `aiGroupName is exist` (code `124025`) - the
+ pre-flight check above is what keeps you from hitting it.
- **Already-managed campaigns (checkable).** A campaign already in another managed
group shows a non-empty `aiGroupId` in its metadata - flag those, let the user
decide.
- **Budget-management conflict (NOT pre-checkable).** Campaign metadata does not
expose budget-management membership, so you cannot verify this up front - only
the backend create can reject it. Don't claim conflicts are fully cleared; say
the budget-management check happens server-side.
4. **Confirm before creating - show everything that will take effect.** Echo the
**complete** config, not just the basics: ad type, group name, the campaigns (by
name), `targetType`/`optimizeType`, target ACOS, budget settings, `aiPersonality`,
`campaignNameSign`, and **every supported action-space switch you're enabling**
(bid / budget / target / struct optimization). For anything you're not
setting, say it will use the platform default - but **don't invent specific default
values** (the tool schema doesn't define them); only state a concrete default if
you've read it back or it's documented. Get an explicit go-ahead - and note that **the
user answering an earlier clarification question is not itself authorization to create**;
you still need an explicit yes on this full preview before calling the create tool. This
matters most when AI will start on (`aiStatus=1`) - those switches immediately affect
live delivery and spend.
- **Turn AI on only if the user explicitly asked to start it.** If they said "create
and start" / "启动", set AI on. If they only asked to set up / create the group or
place campaigns into it (or didn't say), default AI **off** (`aiStatus` / `status`
= 0) and state that in your confirmation. Don't start automation on settings the
user didn't confirm.
5. **Build and call the routed tool** using the exact **write** field names + enum
values (ad-type reference + `field-reference.md`; write names != read names).
> **Create is non-idempotent - never blind-retry.** On any failure, timeout, or
> missing response, the group **may already have been created**. Before retrying,
> re-query by name (`get_entity_metadata entity='aiGroup'`, exact-match the
> `smartCreationName`/`aiGroupName`); only create again if it truly does not exist.
> A blind retry creates a duplicate group.
**Before sending, self-validate the front-end-only rules MCP bypasses** (see
platform-notes "MCP bypasses the platform UI's validation"):
- **Action-space support** - only enable a capability that supports AI for this ad
type ([`references/action-space-matrix.md`](references/action-space-matrix.md));
if the user asked for one that isn't supported for their ad type, tell them and
skip it - don't send a silently-ignored field.
- **Budget** - sanity-check what you reliably can (positive; JP integer-only;
multi-campaign minimum scales with campaign count). Exact per-site/account ranges
are only partly known and the backend may enforce them, so relay backend range
errors rather than hard-blocking on an incomplete table
([`references/budget-limits.md`](references/budget-limits.md)).
- **aiPersonality** `1`-`5`, and **>=3 when `targetType=3` (volume / 冲量)**.
- **Coupled fields** - enabling a switch requires its companion fields, and any
range must have min <= max (see [`references/coupling-rules.md`](references/coupling-rules.md)).
- **Invalid values are rejected by the backend now - but pre-validate anyway** so the
user gets a clear message instead of a downstream error (prod-confirmed 2026-08-13):
`acos` must be > 0 and in range (`0`, negatives, and over-limit are all rejected);
`aiPersonality` outside `1`-`5` is rejected; `campaignIds` is capped at **1000** per
group; and a coupled field sent without its companion is rejected. At **create** the
real budget couplings are: **SD budget** = `budgetChange` + `budget`; **SD dynamic
budget** = `budgetDynamicStatus` + `numType` + `num`; **SP/SB dynamic budget** = the
action-space switch + `budgetNumType` + `budgetNum`. (`acosType`/`budgetType`/
`budgetRatio` are **edit/batch** fields - do **not** put them in a create call.)
Catch these up front rather than leaning on the backend error.
- **Word-list settings are not supported.** Do not send branded, non-branded,
competitor, harvest-blacklist, or negative-target-blacklist fields, even if the
routed schema exposes them. Tell the user to configure word lists in the platform.
6. **Verify it landed - group AND campaigns.** Don't trust the envelope alone:
- Re-read the group (`entity='aiGroup'`) -> confirm it exists with the intended
top-level settings.
- Re-read `entity='campaign'` and check each intended campaign's `aiGroupId` now
points at the new group - the group can exist with fewer campaigns than you sent.
- **SP/SB: a `success` response can still leave an EMPTY group.** `save_sp_sb_ai_managed_group`
may create the group without immediately binding `campaignIds`. So after create,
count how many of your campaigns actually have `aiGroupId` = the new group. **If the
bound count is 0 (or short), re-attach via edit mode**: call `save_sp_sb_ai_managed_group`
again with the returned `aiGroupId` (> 0) and the full `campaignIds`, then re-verify.
- **Reading back binding: query per campaign, not one big `in` list.** In some
environments an `campaignId: {"in":[...]}` filter throws a backend type error.
If a batched filter errors, fall back to per-id `campaignId = <id>` reads (or another
confirmed-usable field). This applies to both the pre-create mapping and this check.
- - Nested `aiActionSettings`/`aiAutomation` values may not be independently
- readable; if you can't read one back, say "created, but this setting couldn't be
- independently confirmed" rather than implying it's verified.
+ - `aiActionSettings` / `aiAutomation` read back as a projection of what's currently
+ effective, not as the raw write payload: disabled dependencies and AI-mode rules can
+ be omitted. Verify the paired action-space switch first, then interpret retained rule
+ config. If the projection cannot prove a requested setting, say "created, but this
+ setting couldn't be independently confirmed" rather than treating omission as a
+ failed write.
- If operation-log read access is available, query `get_operation_log` and confirm
the create is recorded against an identifiable token user. The server supplies
`changedBy`; never send or fabricate it. If logs cannot be read, state that audit
verification was not performed.
- The current write schemas do not expose managed-group scheduling fields. Do not invent
- `scheduleType` or schedule-date parameters; scheduling must be done in the platform.
+ ## Scheduling is a separate tool (not a create-time field)
- The current tools also cannot create a managed group from a platform template. Build
- the supported configuration explicitly from the user's requirements, or tell the user
- to use the platform when a template-based setup is required.
+ There are still **no** `scheduleType` / `scheduleDate` / `scheduleStartDate` /
+ `scheduleEndDate` fields on the create tools - don't invent them. But scheduling itself is
+ now available: **`save_sp_sb_ai_group_schedule`** creates, updates, and deletes SP/SB group
+ schedules, and `get_entity_metadata(entity='aiGroup_schedule')` reads them.
+
+ So when a user says "create the group and have it run this promo window":
+
+ 1. Create the group first (this skill), capture the returned `aiGroupId`.
+ 2. Then call `save_sp_sb_ai_group_schedule` with that `aiGroupId` (see
+ `xnurta-edit-ai-group` for the parameter contract).
+
+ Two things to state up front rather than discovering mid-flow: schedules are **SP/SB only**
+ (there is no SD schedule tool), and a **weekly** schedule (`timeType=2`) inherits
+ `optimizeType` / `acos` / `aiPersonality` from the group - passing those on a weekly
+ schedule is rejected. A fixed-window schedule (`timeType=1`) carries its own values.
+
+ ## Creating from a template
+
+ A managed group **can** now be created from a platform template via `templateId`.
+
+ - **Read templates with `get_ai_group_template`** - no args returns the list (`searchName`
+ for a fuzzy name match, `createdBy`, `page`, `pageLimit` default 50, `applyFlag=1` to
+ include system presets); pass `templateId` to get one template's full detail. Note this
+ read sits behind the **write** scope.
+ - **Apply it** by passing `templateId` (>0) to `create_sd_ai_managed_group` or
+ `save_sp_sb_ai_managed_group`. The template supplies defaults for `acos`, `optimizeType`,
+ `status`, `budgetDynamicStatus`, `numType`, `num`, `campaignNameSign`,
+ `targetHarvestStatus`, `budgetRedistributeStatus`, `aiPersonality`, plus the action-space
+ and automation config.
+ - **Anything you pass explicitly wins over the template value.** Fields you omit fall back
+ to the template. So "use template X but with a 25% ACOS target" is one call: `templateId`
+ plus `acos: 25`.
+ - **You still supply the identity and membership yourself**: `profileId`,
+ `smartCreationName`, `campaignIds`. Templates don't carry those. `budget` /
+ `budgetChange` are also **not** template-controlled on SD.
+ - **One template restriction is a hard error.** If the template's target-harvest (rule 4) or
+ negative-target (rule 5) config is bound to *specific campaigns and ad groups*
+ (`isSelf=2` with the rule enabled), the call is rejected - this tool can't carry those
+ bindings. The error names the offending rules. Tell the user to either apply that template
+ in the platform UI, or pick a template whose rules use "current object" scope.
+ - **Templates are not tied to an ad type, and a cross-type apply is handled for you.**
+ Applying an SP template to an SB group works: the server zeroes the SP-only fields the
+ template carries (`bidAmazonBusinessStatus`, `btbRangeStatus`/`btbMin`/`btbMax`,
+ `bidDaypartStatus`, `bidPerformanceStrictAcosStatus`,
+ `bidAdPlaceStatus`/`bidAdPlaceRangeStatus`, `tos`/`pdp`/`ros` bounds,
+ `structPauseProductStatus`/`structPauseCampaignStatus`) instead of erroring.
+ **But this only happens when you leave `aiActionSettings` out of your call.** If you send
+ `aiActionSettings` yourself, the template's action-space config is skipped entirely (yours
+ wins, it is not merged) and the normal SB compatibility check applies - an SP-only field
+ with a non-zero value then fails the whole request. So when applying a template
+ cross-type, don't also hand-build `aiActionSettings`; and tell the user those SP-only
+ parts of the template won't take effect on an SB group.
+ - **Templates are read-only through MCP.** You cannot create, edit, or delete a template,
+ and you cannot save a group's settings back as one - that's platform-only. Say so rather
+ than attempting a workaround.
+
+ Before applying a template, it's worth reading its detail and telling the user what it will
+ set - especially the AI on/off (`status`) value, since a template can start AI immediately.
## AI on vs off at creation
`aiStatus` (SP/SB) / `status` (SD) decides whether AI starts optimizing immediately.
Turn it on **only when the user explicitly asked to create-and-start**. If they just
want the group set up (or didn't say), default to AI **off** and say so in your
confirmation - turning AI on means it starts adjusting bids/budgets and spending against
the target right away.
> Note: an "off" group reads back as `aiStatus=2` ("AI Turned Off"), not `0`. Don't
> treat a non-zero `aiStatus` on read as "it's on" - `1` = running, `2` = off.
## Enum discipline
`optimizeType` / `targetType` / `status` / `aiStatus` / `targetHarvestStatus` /
`numType` / `aiPersonality` and the `aiActionSettings` switches are closed enums.
Use only the values listed in
[`references/field-reference.md`](references/field-reference.md) - do not invent or
infer values. Passing an unlisted value makes the call fail, and the error comes back
generic (no field-level hint), so validate against the dictionary **before** sending
rather than relying on the error to tell you what was wrong. For mapping the user's
Chinese wording to these codes (and back), use
[`references/enum-i18n.md`](references/enum-i18n.md).
## Response & errors
Success looks like `{ "isError": false, "data": { "status": "success", "result": {
"aiGroupId": <new id> } } }` - capture `aiGroupId` for the verify step.
Errors come back as `{ "isError": true, "data": { "error": "...", "recoveryHint":
"..." } }`. Relay `recoveryHint` when present, but it isn't always populated - some
come back generic - so still map the common ones yourself:
| Symptom | Likely cause | What to do |
|---|---|---|
| duplicate-name / "Duplicate group name" | name already used in this profile | ask for a different name |
| "Campaign conflict" | a campaign is already in another AI group / budget mgmt | surface which campaign; drop it or free it first |
| generic `business_error` | often an out-of-range/invalid field value | re-check every value against `field-reference.md` |
| timeout (~30s, no response) | the create may have already applied downstream | **verify with a read before retrying** - a blind retry can create a duplicate group |
## Reference files
- [`references/create-sd.md`](references/create-sd.md) - SD create (`create_sd_ai_managed_group`) fields + example
- [`references/create-sp-sb.md`](references/create-sp-sb.md) - SP/SB create (`save_sp_sb_ai_managed_group`): core fields, SP-vs-SB differences, action-space **coupling rules** + example
- [`references/field-reference.md`](references/field-reference.md) - exact **write** field names + enum values (write names != read names)
- [`references/action-space-matrix.md`](references/action-space-matrix.md) - which action-space capabilities are supported (AI / Rule / none) per SP / SB / SD
- [`references/coupling-rules.md`](references/coupling-rules.md) - companion-field couplings, the 按表现调预算 / 预算重新分配 scope relationship, and group-total-budget rescale behavior
- [`references/budget-limits.md`](references/budget-limits.md) - site/account-type budget ranges (front-end rules MCP bypasses)
- [`references/enum-i18n.md`](references/enum-i18n.md) - 中文 <-> English <-> code mapping (parse Chinese requests -> codes; render codes -> Chinese)
- [`references/platform-notes.md`](references/platform-notes.md) - shared write-tool behavior (auth, response envelope, timeout, error shape)