Overview
Bring your own creative lets you hand Murph a finished asset — an image, video, or ad tag — directly in a conversation and get it onto a campaign without leaving chat. Instead of navigating to an upload form, you drop the file and answer which campaign is this for? HTML5 bundles also need their landing-page URL before delivery.This is the chat-first path for creative you already have. To generate creative from a brief instead, see Creative and the creative manifest tasks.
Promoted managed audio has a capability-gated API adoption contract. It is
available only when both the account capability and bounded origin are
explicitly enabled, and this change enables neither. See Adopt a managed
audio source. Even when
enabled, it records a creative and optional campaign association only; it
never initiates seller or destination delivery, attaches to a media buy, or
makes anything live.
The flow
1
Upload the asset
Attach an image, video, tag, or tag sheet in the conversation.
Murph recognizes the media kind automatically.
2
Answer “which campaign?”
Murph opens a short picker showing the advertiser and that advertiser’s
recent campaigns. You choose where the creative should live:
- An existing campaign — pick it from the list.
- A new campaign — describe it in plain language and Murph creates it.
- Save to the advertiser — park the creative at the advertiser level to assign later. The API and agent equivalent is Create advertiser creative master.
3
Murph maps it to placements
Once the creative is on a campaign, Murph maps it to that campaign’s
placements. If an asset lands in the wrong slot, you can remap it. For an
HTML5 bundle, add the advertiser destination in the creative’s
click-through URL field before media-buy sync.
Uploading large MP4 video
On the shared/mcp/v3 connector, ask to upload a creative and select its
advertiser. No destination connection or provider account is required. The
upload_creative_asset Task accepts an MP4 up to 2,000,000,000
bytes when managed video is enabled for the buyer. Managed video has its own
account-access and service settings; it does not depend on the private JPEG/PNG
upload option. Eligible connections also accept JPEG and PNG files up to
30,000,000 bytes.
The browser calculates the file’s SHA-256 while streaming it, then uploads the
bytes directly to private object storage with a create-only capability. File
bytes never enter model or chat context. The signed PUT URL is returned only to
the embedded Task app; it is excluded from model-visible results, chat/activity,
logs, and persistence. Every Task call rechecks the buyer, advertiser, and
exact authenticated principal.
The upload capability expires after two hours. Finishing the Task verifies the
stored object’s declared type and exact size, pins its immutable storage
generation, and waits for asynchronous digest and media inspection. When the
exact source is promoted, the app confirms finalization without projecting the
private source reference, storage identity, or publication URL into model
context. Finalization does not create or attach a Creative. Rejected or
abandoned quarantine objects never become public delivery assets.
Managed MP4 upload is an alpha available only when the Buyer Account is enrolled.
Enrollment can be disabled without changing ad-platform credentials.
JPEG and PNG eligibility remains independent.
Turning an uploaded image into a creative
Pass the finalized JPEG or PNGscope3-asset:// reference verbatim as
sourceAssetRef to save_creative, plus the matching advertiserId or
campaignId. Campaign-scoped adoption derives the owning advertiser from the
campaign.
For an eligible reference:
campaignId or advertiserId, not both. The upload must be
finalized and owned by the same customer, authenticated principal, and
advertiser. The server copies the reverified JPEG or PNG bytes into the
governed Creative asset store and persists only that durable asset plus a
one-way source fingerprint. It never stores the opaque source reference,
private object path, or upload/delivery signed URL on the Creative.
For a campaign, creation happens in the advertiser library first and the
existing campaign-membership operation runs second. Retrying the same source
and name returns the Creative already created and completes a missing campaign
attachment, without replaying campaign-scoped create side effects. The private
upload can then expire without emptying the Creative.
Legacy provider-bound video adoption
An MP4 finalized by the shared V3 buyer Task is owner-bound and upload-only. It cannot currently be passed tosave_creative, and the legacy V2 operation
below is not a fallback for it. The exact V3 composition contract remains an
approval boundary tracked on AI-7473.
For a video uploaded through the legacy provider-bound Task, finishing returns
the source_uid for the source that passed inspection. That same provider
scope can adopt it without assembling a creative around a hosted URL by hand:
campaign_id is optional. Include it and the creative is attached to that
campaign in the same call; omit it to keep the creative advertiser-scoped. The
campaign and source must match the same advertiser and provider ownership.
Attaching also pushes the campaign’s live media buys to their sellers. That push
is best-effort and is not part of what the response confirms: a success means the
creative is attached to the campaign, not that every seller has accepted it into
its packages. Check the media buys themselves to see where the creative is live.
The V2 response returns creative_id, source_uid, delivery_url,
publication_uid, name, and created. A success that named a campaign_id
means the creative is attached to that campaign whether or not this particular
call attached it, so a retry safely finishes an interrupted attachment.
You name the source, not a URL. The hosted HTTPS URL is issued server-side
and resolves the exact file that passed inspection, so the private storage
location is never something you supply or can substitute.
Adopting the same source twice returns the creative that already exists,
with created: false, rather than making a second one. If you include a
campaign_id the second time, the existing creative is attached to that
campaign — so a call that was interrupted after the creative was made can be
retried safely. Retry with the same name: adoption never renames an existing
creative, so asking for a different one is refused rather than silently
returning a creative that does not have the name you asked for.
Names compete among an advertiser’s creatives that are not currently scoped to a
campaign — which is how adoption always creates them. If one of those already
holds the name, adoption is refused rather than silently reusing it. A creative
created directly under a campaign is outside that set while it stays there, but
detaching it moves it in: detaching does not free a name, it claims one. Attaching an adopted creative to
a campaign afterwards does not release its name either: archiving it does, and so
does renaming it with a separate update_creative call. If the creative holding
the name is already attached to a campaign, rename it instead — renaming frees the
name without disrupting a creative that’s live in a media buy. update_creative is campaign-scoped, so a creative attached to no
campaign can only be archived. Note that archiving is the advertiser-scoped
delete (archive_creative); the campaign-scoped delete_creative only detaches
the creative from that campaign and does not release its name. Duplicating an
adopted creative with duplicate_creative copies the video, not the adoption:
the copy is not the adoption of record for that source, so it neither blocks nor
lets you re-adopt the source through it.
A CONFLICT on name does not always mean “pick another name”. Each one
carries a details.reason: name_creation_in_progress means another call is
still writing that exact name, and retrying the identical request is the right
move; name_creation_abandoned means that writer died mid-way, so archive the
incomplete creative first; name_taken means the name belongs to a finished
creative and you need a different one. The conflicts on source_uid work the
same way — adoption_in_progress is the only one worth retrying.
adoption_name_mismatch means the source already has a creative under another
name; use that name or rename the creative separately. source_delivery_revoked
and source_deletion_requested are terminal for that source: upload a new video
before adopting again. Branch on details.reason rather than on the message text.
Two rules here are enforced by the database, not just checked: a managed video
source can back only one live creative, and advertiser-scoped creative names are
serialized across both adoption and ordinary creation. Both hold no matter how
many callers race, and archiving frees the name.
If the source is already held by a creative but adoption can no longer confirm
that creative still carries the video — because its asset was replaced or
removed directly on that creative — adoption refuses with CONFLICT rather than
creating a second creative for the same source. Archive the creative holding it
and adopt again, or upload the video again and adopt the new source.
A second CONFLICT also tells you to archive, for a different reason: an earlier
adoption of this same source left its creation marker uncleared and has been
stuck long enough (about fifteen minutes) that nothing is still writing it. An
asset row may already have landed, but the creative never finalized. Its
details.reason is adoption_abandoned; archive that incomplete creative and
adopt again.
Within these three source-identity conflicts, adoption_in_progress is the one
you should simply retry. It means another adoption is still finishing or the
blocking adoption changed while this request was classifying it; retrying lets
the request observe the settled state. The separate
name_creation_in_progress reason described above is also retryable. Branch on
details.reason, never on the message; the other reasons require archiving or
changing the request first.
Legacy adoption produces a creative and may enqueue existing V2 campaign sync
behavior; its success response proves neither provider creation nor acceptance.
Only exact provider readback confirms destination materialization. For the
production-dark managed-audio contract, see Adopt a managed audio
source.
Adoption is available wherever direct video upload is already enabled for your
account — it is part of that alpha, not a separate opt-in. A request from an
account without it is refused with CAPABILITY_NOT_SUPPORTED.
Uploading HTML5 banner ZIPs
Some ad tools export one HTML5 banner as a ZIP containing anindex.html file
and its scripts, styles, images, and fonts. Upload that package as-is in buyer
chat. Murph keeps the files together as one HTML5 creative instead of creating
a separate creative for each file.
Murph records the dimensions when the package declares one unambiguous
ad.size. It also recognizes common wrapper exports that contain one nested
HTML5 ZIP, an exact exploded copy, and an explicitly named same-size backup
image. The nested package is retained unchanged. Ambiguous, malformed,
oversized, or unsafe archives are rejected rather than partially imported.
Importing and delivering are separate checks. Before media-buy sync, an HTML5
creative needs an explicit landing-page URL. A seller option that declares an
HTML5 behavior constraint Murph cannot prove from inspection is rejected with
that constraint named instead of being sent optimistically. Add the destination
in the creative’s click-through URL field before syncing the media buy.
Uploading tag sheets
Murph accepts creative manifests in CSV, legacy XLS, and XLSX. CM360/DCM tag sheets can include instructions before the data table and several alternative tag implementations for one placement-tag row; Murph finds the actual header and creates one creative per populated display row rather than attaching every display alternative as a duplicate. For display, Murph prefers the iframe/JavaScript implementation and uses JavaScript or Standard as fallbacks. It retains every populated display, VAST pre-fetch, and Internal Redirect alternative as inert source provenance. Inline third-party markup is stored as a non-trafficable custom creative without rewriting vendor macros. Murph does not mislabel it as canonicaldisplay_tag
(which requires a hosted tag URL) or as an HTML5 bundle. A sheet containing only destination-sensitive alternatives is
recognized but not converted into an arbitrary primary creative. VAST version
must match the destination player, while Internal Redirect requires separate
image and click URL fields in a compatible ad server. When modern and legacy
sheets contain the same placement name and size, the modern row takes
precedence; unmatched legacy rows are retained.
Declared dimensions such as 300x250 are retained for destination compilation.
Murph can also read dimensions from common tag markup, including HTML
attributes, CM360 inline styles, and sz= parameters. A dimension declared in
the sheet takes precedence over a size inferred from markup.
Preview and improve the mapping
Use the Inspect a Tag Sheet skill to preview a CSV, XLS, or XLSX file locally before upload. Its offline inspector returns the parser version, mapping-profile version, mode, creative-row count, canonical role and rule IDs, and diagnostic codes. The receipt contains no filename, worksheet name, source header, placement name, tag, URL, formula, or cell value. The mapping profile is versioned. When the production parser can read a workbook but finds no usable rows, Interchange automatically records the same content-free receipt. When that shape recurs across customers, it sends one deduplicated, content-free signal for team review. Corrupt files and size-limit failures are recorded for diagnosis but do not automatically become product work. Destination-sensitive rows are recognized and require a compatible destination before trafficking. A team member or authorized agent reviews the signal, reproduces it with synthetic or explicitly approved sanitized data, adds a regression fixture, and publishes a new profile version. If local inspection finds a plausible but incorrect result, such as the wrong row count, the skill can prepare the same sanitized receipt for support. It asks for confirmation before filing and never sends the workbook or its contents. Customer workbooks do not enter the shared test corpus by default.Uploading before you’ve named an advertiser
You don’t have to know the advertiser first. If you drop a file at the start of a conversation, Murph stashes it and holds onto it across turns. The moment you name (or pick) an advertiser, the stashed upload is adopted into the “which campaign?” picker — nothing is lost between the upload and the decision.What happens to your creative
- The asset is stored against your advertiser and, once routed, attached to the chosen campaign.
- A creative saved to the advertiser (rather than a campaign) waits there until you assign it — it is not sent to any seller until it’s on a live campaign.
- Attaching to a campaign makes the creative eligible to enter delivery; it must still clear any storefront and source-system approval gates before it can serve. Saving to the advertiser or stashing does not begin that process.
Related
- Creative — the creative manifest model
- Creative tasks — manifest task reference