Build brand rights agent
Skill adcontextprotocol/adcp-client/skills/build-brand-rights-agent
Use when building an AdCP brand rights agent — a platform that represents brand identity, licenses rights (image usage, logo placement, AI generation), and approves creatives.From its SKILL.md
npx -y skills add adcontextprotocol/adcp-client --skill build-brand-rights-agentAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 18 stars18 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.5 KB, as published. Nobody here has run it
Build a Brand Rights Agent
A brand rights agent represents a brand's identity and licensing. Buyers discover the brand, browse available rights (image usage, logo placement, AI generation), acquire licenses, and submit generated creatives for approval. The agent enforces brand guidelines.
Pick your fork target
| Specialism | Status | Fork this | Storyboard |
|---|---|---|---|
brand-rights | stable | hello_seller_adapter_multi_tenant.ts — brandRights block | brand_rights |
The multi-tenant adapter is the canonical fork target. Its brandRights block implements all five operations (getBrandIdentity, getRights, acquireRights, updateRights, reviewCreativeApproval) plus the cross-specialism governance check (enforceGovernance) called from acquireRights.
What to delete if you're single-specialism brand-rights
Forking the multi-tenant adapter for a single specialism? Delete these blocks first — leaning on stable symbol names rather than line numbers (the adapter evolves; greppable identifiers don't):
- The
campaignGovernance = defineCampaignGovernancePlatform({ ... })block (the entiresync_plans/check_governance/report_plan_outcome/get_plan_audit_logssurface) - The
propertyLists = definePropertyListsPlatform({ ... })block (property-lists CRUD) - The
private async enforceGovernance(...)helper method and its call site insideacquireRights— the two linesconst denial = await this.enforceGovernance(tenant, ctx, offering, req); if (denial) return denial;. WithoutcampaignGovernanceco-resident, the in-process dispatch has nothing to call. Single-specialism adopters who need governance dial out to a registered governance agent's URL via the@adcp/sdkclient. - The
governanceBindings: Map<string, GovernanceBinding>field onTenantState, theinterface GovernanceBinding, and thesyncGovernanceRowcallback oncreateTenantStore(governance bindings have nothing to register against). - The validation seam block in
acquireRightsthat requirescampaign.estimated_impressionswhen a governance binding exists — without bindings this constraint never fires.
Keep: the accounts / createTenantStore block (translates to single-tenant by passing one tenant entry — needed for tenant isolation), agentRegistry, the brandRights block, getTenant(ctx) resolution.
The storyboard tests identity discovery → rights search → acquisition → enforcement (including expired-campaign denial).
For exact response shapes, error codes, and optional fields, docs/llms.txt is the canonical reference.
When to use this skill
- User wants to build an agent that manages brand identity and licensing
- User mentions brand rights, brand guidelines, creative approval, or licensing (Warner Bros Discovery, Disney rights pipelines)
- User references
get_brand_identity,get_rights,acquire_rights,update_rights, orcreative_approval
Not this skill:
- Selling ad inventory →
skills/build-seller-agent/ - Managing creative formats/library →
skills/build-creative-agent/ - Evaluating media buys →
skills/build-governance-agent/
Cross-cutting rules
Every brand-rights agent hits the cross-cutting rules in ../cross-cutting.md. The high-traffic ones for brand-rights (deep-linked to the rule):
idempotency_keyonacquire_rightsandupdate_rights- Authentication —
serve({ authenticate })baseline - Webhooks —
creative_approval.${creative_id}operation_id must be stable across retries; thecreative_approvalwebhook receiver itself validates idempotency manually (the framework's auto-idempotency middleware applies to MCP/A2A tools, not arbitrary HTTP receivers)
One brand-rights-specific note:
creative_approval is webhook-only
The spec models creative approval as an HTTP POST from the buyer to the approval_webhook URL the seller returned in acquire_rights. There is no inbound MCP/A2A tool for creative_approval — wire an HTTP receiver and dispatch to brandRights.reviewCreativeApproval.
The receiver must validate idempotency_key itself (the framework's auto-idempotency middleware applies to MCP/A2A tools, not arbitrary HTTP receivers) and replay the cached verdict on resubmission.
Tool surface
| Operation | How to implement |
|---|---|
get_brand_identity | brandRights.getBrandIdentity handler — locale-keyed brand name, domain, logos, house identity |
get_rights | brandRights.getRights handler — list licensable rights with pricing + use cases |
acquire_rights | brandRights.acquireRights handler (mutating) — returns approval_webhook URL |
update_rights | brandRights.updateRights handler (mutating) — for campaign-end revocation, scope changes |
creative_approval | HTTP receiver at the approval_webhook URL; dispatch to brandRights.reviewCreativeApproval |
Specialism deltas
brand-rights —
- Brand definition: name (locale-keyed for i18n), domain, logos, house identity, languages/markets
- Rights catalog: image usage, AI generation, logo placement, talent likeness; each with pricing (flat_rate, cpm) and uses (likeness, voice, commercial, ai_generated_image)
- Approval criteria: auto-approve (basic checks), guidelines check (brand standards), human review (queue for manual)
- Revocation webhook: emit when a campaign ends or rights are revoked mid-campaign — same
operation_idstability rules as other webhooks (see../cross-cutting.md) - Governance denial: the storyboard exercises
GOVERNANCE_DENIEDonacquire_rightswhen the requested use exceeds the licensed scope; map this error code, don't substitute a genericINVALID_REQUEST
Validate locally
# Run the fork-matrix gate (tsc strict)
npm run compliance:fork-matrix -- --test-name-pattern="hello-seller-adapter-multi-tenant"
# Run your forked agent against the brand_rights storyboard
adcp storyboard run http://127.0.0.1:3003/mcp brand_rights \
--bearer "$ADCP_AUTH_TOKEN" --include-bundles --json
The fork-matrix gate is the three-gate contract from docs/guides/EXAMPLE-TEST-CONTRACT.md. The multi-tenant adapter currently runs the strict-tsc gate only (no brand-rights mock-server today); storyboard-grader gates land alongside the next mock-server family.
For deeper validation: docs/guides/VALIDATE-YOUR-AGENT.md.
Common shape gotchas
acquire_rights response includes approval_webhook URL — buyer POSTs to this to submit creatives, you don't pull. sync_accounts rows require action: 'created' | 'updated' | 'unchanged' | 'failed'. Brand name is locale-keyed ({ "en-US": "...", "es-MX": "..." }), not a bare string. See ../SHAPE-GOTCHAS.md.
Migration notes
- 6.6 → 6.7:
update_rightswired as a first-class tool +creative_approvalwebhook builders shipped in #1349. Seedocs/migration-6.6-to-6.7.md. - 4.x → 5.x:
docs/migration-4.x-to-5.x.md