From 8b8763e0f8b30b2b05638bbbce84200acb71c5d4 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Fri, 13 Feb 2026 14:33:48 -0500 Subject: [PATCH] feat(governance): Add get_creative_features task for creative governance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces the creative analog of get_property_features — a general-purpose task for evaluating creatives and returning feature values. Supports security scanning (#1035), creative quality assessment, content categorization (#1036), and any other creative evaluation through the same feature-based pattern used by property governance. New schemas: - get-creative-features-request.json — accepts creative manifest + optional feature_ids - get-creative-features-response.json — discriminated union (success/error) - creative-feature-result.json — individual feature evaluation result Also adds creative_features to governance section of get_adcp_capabilities, allowing agents to advertise which creative features they can evaluate. Co-Authored-By: Claude Opus 4.6 --- .changeset/creative-governance.md | 14 ++ docs.json | 14 ++ .../creative/get_creative_features.mdx | 172 ++++++++++++++++++ docs/governance/creative/index.mdx | 157 ++++++++++++++++ docs/governance/overview.mdx | 2 +- .../creative/creative-feature-result.json | 55 ++++++ .../get-creative-features-request.json | 29 +++ .../get-creative-features-response.json | 59 ++++++ static/schemas/source/index.json | 10 + .../get-adcp-capabilities-response.json | 62 ++++++- 10 files changed, 572 insertions(+), 2 deletions(-) create mode 100644 .changeset/creative-governance.md create mode 100644 docs/governance/creative/get_creative_features.mdx create mode 100644 docs/governance/creative/index.mdx create mode 100644 static/schemas/source/creative/creative-feature-result.json create mode 100644 static/schemas/source/creative/get-creative-features-request.json create mode 100644 static/schemas/source/creative/get-creative-features-response.json diff --git a/.changeset/creative-governance.md b/.changeset/creative-governance.md new file mode 100644 index 000000000..aa31f1a35 --- /dev/null +++ b/.changeset/creative-governance.md @@ -0,0 +1,14 @@ +--- +"adcontextprotocol": minor +--- + +Add `get_creative_features` task for creative governance + +Introduces the creative analog of `get_property_features` — a general-purpose task for evaluating creatives and returning feature values. Supports security scanning, creative quality assessment, content categorization, and any other creative evaluation through the same feature-based pattern used by property governance. + +New schemas: +- `get-creative-features-request.json` — accepts a creative manifest and optional feature_ids filter +- `get-creative-features-response.json` — returns feature results with discriminated union (success/error) +- `creative-feature-result.json` — individual feature evaluation (value, confidence, expires_at, etc.) + +Also adds `creative_features` to the governance section of `get_adcp_capabilities` response, allowing agents to advertise which creative features they can evaluate. diff --git a/docs.json b/docs.json index bdfde32fc..732a8652d 100644 --- a/docs.json +++ b/docs.json @@ -143,6 +143,13 @@ ] } ] + }, + { + "group": "Creative Governance", + "pages": [ + "docs/governance/creative/index", + "docs/governance/creative/get_creative_features" + ] } ] }, @@ -593,6 +600,13 @@ ] } ] + }, + { + "group": "Creative Governance", + "pages": [ + "docs/governance/creative/index", + "docs/governance/creative/get_creative_features" + ] } ] }, diff --git a/docs/governance/creative/get_creative_features.mdx b/docs/governance/creative/get_creative_features.mdx new file mode 100644 index 000000000..3f820a31c --- /dev/null +++ b/docs/governance/creative/get_creative_features.mdx @@ -0,0 +1,172 @@ +--- +title: get_creative_features +--- + +# get_creative_features + + +**AdCP 3.0 Proposal** - This task is under development for AdCP 3.0. + + +Evaluates a creative manifest and returns feature values from a creative governance agent. The creative analog of `get_property_features`. + +## Use cases + +- **Security scanning**: Detect malware, auto-redirects, credential harvesting, cloaking +- **Creative quality**: Evaluate brand consistency, platform optimization, guideline adherence +- **Content categorization**: Classify creative content against IAB Content Taxonomy or other standards +- **Accessibility**: Check WCAG compliance, screen reader compatibility + +## Request + +```json +{ + "$schema": "/schemas/creative/get-creative-features-request.json", + "creative_manifest": { + "format_id": { + "agent_url": "https://creative.adcontextprotocol.org", + "id": "html5-display-300x250" + }, + "assets": { + "creative_html": { + "url": "https://cdn.agency.com/creative/abc123.html" + } + } + }, + "feature_ids": ["auto_redirect", "credential_harvest", "cloaking"] +} +``` + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `creative_manifest` | object | Yes | Creative manifest with `format_id` and `assets` | +| `feature_ids` | string[] | No | Filter to specific features. If omitted, evaluates all features the agent supports. | + +## Response + + +```json Security scanner (clean) +{ + "$schema": "/schemas/creative/get-creative-features-response.json", + "results": [ + { "feature_id": "auto_redirect", "value": false }, + { "feature_id": "credential_harvest", "value": false }, + { "feature_id": "cloaking", "value": false } + ], + "detail_url": "https://scanner.example.com/reports/ctx_abc123" +} +``` + +```json Security scanner (threat detected) +{ + "$schema": "/schemas/creative/get-creative-features-response.json", + "results": [ + { "feature_id": "auto_redirect", "value": true, "confidence": 0.97 }, + { "feature_id": "credential_harvest", "value": true, "confidence": 0.91 }, + { "feature_id": "cloaking", "value": false } + ], + "detail_url": "https://scanner.example.com/reports/ctx_def456" +} +``` + +```json Creative quality platform +{ + "$schema": "/schemas/creative/get-creative-features-response.json", + "results": [ + { "feature_id": "brand_consistency", "value": 87, "unit": "percentage" }, + { "feature_id": "platform_optimized", "value": true }, + { "feature_id": "creative_quality_score", "value": 92, "unit": "score" } + ], + "detail_url": "https://quality.example.com/reports/ctx_ghi789" +} +``` + +```json Content categorizer +{ + "$schema": "/schemas/creative/get-creative-features-response.json", + "results": [ + { "feature_id": "iab_casinos_gambling", "value": true, "confidence": 0.95 }, + { "feature_id": "iab_automotive", "value": false, "confidence": 0.12 } + ], + "detail_url": "https://categorizer.example.com/reports/ctx_jkl012" +} +``` + + +### Response fields + +| Field | Description | +|-------|-------------| +| `results` | Array of feature evaluation results | +| `results[].feature_id` | Which feature was evaluated | +| `results[].value` | Feature value: boolean (binary), number (quantitative), or string (categorical) | +| `results[].confidence` | Confidence score (0-1), when applicable | +| `results[].unit` | Unit for quantitative values (e.g., `percentage`, `score`) | +| `results[].expires_at` | When this evaluation expires and should be refreshed | +| `results[].measured_at` | When this feature was evaluated | +| `results[].methodology_version` | Version of methodology used | +| `results[].details` | Vendor-specific details | +| `detail_url` | URL to vendor's full assessment. Access-controlled by the vendor. | + +### Error response + +```json +{ + "errors": [ + { + "code": "CREATIVE_INACCESSIBLE", + "message": "Could not retrieve creative assets for evaluation" + } + ] +} +``` + +## Async evaluation + +Some evaluations (e.g., sandboxed malware scanning) take time. The agent returns `status: "working"` and delivers results via webhook when complete. This uses the standard [async task pattern](/docs/building/implementation/async-operations) — no custom status values needed. + +## Orchestrator logic + +The orchestrator applies feature requirements on the client side, the same way property list feature requirements work: + +```javascript +const result = await agent.getCreativeFeatures({ + creative_manifest: manifest +}); + +if (result.errors) { + // Handle error - reject or retry + return; +} + +// Apply security requirements +const threats = result.results.filter( + f => ['auto_redirect', 'credential_harvest', 'cloaking'].includes(f.feature_id) + && f.value === true +); +if (threats.length > 0) { + // Reject - security threat detected + return; +} + +// Apply quality requirements +const quality = result.results.find(f => f.feature_id === 'brand_consistency'); +if (quality && quality.value < 80) { + // Reject - below quality threshold + return; +} +``` + +## Relationship to property governance + +Creative governance follows the same pattern as property governance: + +| Concept | Property governance | Creative governance | +|---------|-------------------|-------------------| +| **What's evaluated** | Properties (websites, apps) | Creatives (manifests) | +| **Feature declarations** | `governance.property_features` | `governance.creative_features` | +| **Evaluation task** | `get_property_features` | `get_creative_features` | +| **Feature values** | `property-feature-value` schema | Same fields (value, confidence, expires_at, etc.) | +| **Detailed intelligence** | Behind `detail_url` / `methodology_url` | Behind `detail_url` / `methodology_url` | diff --git a/docs/governance/creative/index.mdx b/docs/governance/creative/index.mdx new file mode 100644 index 000000000..e1d025683 --- /dev/null +++ b/docs/governance/creative/index.mdx @@ -0,0 +1,157 @@ +--- +title: Creative Governance +sidebarTitle: Overview +--- + + +**AdCP 3.0 Proposal** - This protocol is under development for AdCP 3.0. Feedback welcome via [GitHub Discussions](https://github.com/adcontextprotocol/adcp/discussions). + + +Creative Governance standardizes how creatives are evaluated by specialized governance agents. It applies the same feature-based pattern as [Property Governance](../property/index) — agents declare features they can evaluate, accept creative manifests, and return feature values. + +## Overview + +Creative governance agents evaluate creatives and return feature values. Different agents evaluate different features: + +| Agent type | Example features | Feature type | +|------------|-----------------|--------------| +| **Security scanner** | `auto_redirect`, `credential_harvest`, `cloaking` | Binary | +| **Creative quality** | `brand_consistency`, `platform_optimized`, `creative_quality_score` | Quantitative, binary | +| **Content categorization** | `iab_casinos_gambling`, `iab_automotive` | Binary (with confidence) | + +The protocol doesn't define a fixed feature taxonomy. Vendors declare what they evaluate via [`get_adcp_capabilities`](/docs/protocol/get_adcp_capabilities) and compete on coverage. + +## How it works + +### 1. Agent declares features + +A creative governance agent advertises its capabilities using the same feature definition pattern as property governance: + + +```json Security scanner +{ + "governance": { + "creative_features": [ + { + "feature_id": "auto_redirect", + "type": "binary", + "description": "Unauthorized navigation away from publisher context without user interaction", + "methodology_url": "https://scanner.example.com/methodology" + }, + { + "feature_id": "credential_harvest", + "type": "binary", + "description": "Phishing techniques to gather user credentials or PII", + "methodology_url": "https://scanner.example.com/methodology" + }, + { + "feature_id": "cloaking", + "type": "binary", + "description": "Creative masks or misrepresents content to evade detection", + "methodology_url": "https://scanner.example.com/methodology" + } + ] + } +} +``` + +```json Creative quality platform +{ + "governance": { + "creative_features": [ + { + "feature_id": "brand_consistency", + "type": "quantitative", + "range": { "min": 0, "max": 100 }, + "description": "Adherence to brand guidelines including logo placement, colors, and typography", + "methodology_url": "https://quality.example.com/methodology" + }, + { + "feature_id": "platform_optimized", + "type": "binary", + "description": "Creative meets platform-specific best practices (aspect ratio, text overlay limits)", + "methodology_url": "https://quality.example.com/methodology" + } + ] + } +} +``` + +```json Content categorizer +{ + "governance": { + "creative_features": [ + { + "feature_id": "iab_casinos_gambling", + "type": "binary", + "description": "Creative contains casinos or gambling content (IAB Content Taxonomy 3.1, ID 181)", + "methodology_url": "https://categorizer.example.com/methodology" + }, + { + "feature_id": "iab_automotive", + "type": "binary", + "description": "Creative contains automotive content (IAB Content Taxonomy 3.1, ID 1)", + "methodology_url": "https://categorizer.example.com/methodology" + } + ] + } +} +``` + + +### 2. Orchestrator evaluates a creative + +The orchestrator calls [`get_creative_features`](./get_creative_features) with a creative manifest: + +```json +{ + "creative_manifest": { + "format_id": { + "agent_url": "https://creative.adcontextprotocol.org", + "id": "html5-display-300x250" + }, + "assets": { + "creative_html": { + "url": "https://cdn.agency.com/creative/abc123.html" + } + } + } +} +``` + +### 3. Agent returns feature values + +The agent evaluates the creative and returns feature values. The response shape is the same regardless of agent type: + +```json +{ + "results": [ + { "feature_id": "auto_redirect", "value": true, "confidence": 0.97 }, + { "feature_id": "credential_harvest", "value": false }, + { "feature_id": "cloaking", "value": false } + ], + "detail_url": "https://scanner.example.com/reports/ctx_abc123" +} +``` + +### 4. Orchestrator applies requirements + +The orchestrator evaluates the feature values against buyer-defined requirements — the same pattern as property list feature requirements: + +- Security: reject if `auto_redirect` is `true` +- Quality: reject if `brand_consistency` is below 80 +- Categorization: reject if `iab_casinos_gambling` is `true` and campaign excludes gambling + +## Design principles + +**Reuses existing patterns.** Creative governance follows the same feature-based model as property governance. Agents declare features, return values, and keep detailed intelligence behind `detail_url` and `methodology_url`. + +**Vendor-agnostic features.** The protocol doesn't define which features exist. Vendors declare their own feature catalogs. A security vendor and a creative quality vendor both use `get_creative_features` — the protocol doesn't need to know the difference. + +**Opaque results.** Feature values on the wire are pass/fail (binary) or scores (quantitative). Detailed methodology, detection techniques, and threat intelligence stay behind the vendor's access-controlled URLs. + +**Orchestrator decides.** Agents return values, orchestrators evaluate against requirements. The separation of measurement from decision-making is the same as property governance. + +## Async evaluation + +If evaluation takes time (e.g., sandboxed execution for malware scanning), the agent returns `status: "working"` and delivers results via the standard webhook mechanism. No custom status values or webhook events needed — the existing [async task pattern](/docs/building/implementation/async-operations) handles this. diff --git a/docs/governance/overview.mdx b/docs/governance/overview.mdx index 48452fb71..f09a3d11e 100644 --- a/docs/governance/overview.mdx +++ b/docs/governance/overview.mdx @@ -22,7 +22,7 @@ The Governance Protocol covers four distinct governance domains: | **[Property Governance](./property/index)** | Where ads can run | Property lists, compliance filtering, adagents.json authorization | | **[Brand Protocol](/docs/brand-protocol/index)** | Brand identity & agents | brand.json discovery, brand agent authorization | | **[Content Standards](./content-standards/index)** | Brand suitability | Privacy-preserving content evaluation, calibration, validation | -| **Creative Governance** | What creatives are compliant | Format validation, content moderation, accessibility | +| **[Creative Governance](./creative/index)** | What creatives are safe and effective | Security scanning, creative quality, content categorization via `get_creative_features` | | **Campaign Governance** | What can be bought | Budget controls, approval workflows, policy compliance | Each domain has specialized governance agents that provide data, filtering, and scoring capabilities. diff --git a/static/schemas/source/creative/creative-feature-result.json b/static/schemas/source/creative/creative-feature-result.json new file mode 100644 index 000000000..f4fc0bc2d --- /dev/null +++ b/static/schemas/source/creative/creative-feature-result.json @@ -0,0 +1,55 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/creative/creative-feature-result.json", + "title": "Creative Feature Result", + "description": "A single feature evaluation result for a creative. Uses the same value structure as property-feature-value (value, confidence, expires_at, etc.).", + "type": "object", + "properties": { + "feature_id": { + "type": "string", + "description": "The feature that was evaluated (e.g., 'auto_redirect', 'brand_consistency', 'iab_casinos_gambling')" + }, + "value": { + "description": "The feature value. Type depends on feature definition: boolean for binary, number for quantitative, string for categorical.", + "oneOf": [ + { "type": "boolean" }, + { "type": "number" }, + { "type": "string" } + ] + }, + "unit": { + "type": "string", + "description": "Unit of measurement for quantitative values (e.g., 'percentage', 'score')" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score for this value (0-1)" + }, + "measured_at": { + "type": "string", + "format": "date-time", + "description": "When this feature was evaluated" + }, + "expires_at": { + "type": "string", + "format": "date-time", + "description": "When this evaluation expires and should be refreshed" + }, + "methodology_version": { + "type": "string", + "description": "Version of the methodology used to evaluate this feature" + }, + "details": { + "type": "object", + "description": "Additional vendor-specific details about this evaluation", + "additionalProperties": true + }, + "ext": { + "$ref": "/schemas/core/ext.json" + } + }, + "required": ["feature_id", "value"], + "additionalProperties": false +} diff --git a/static/schemas/source/creative/get-creative-features-request.json b/static/schemas/source/creative/get-creative-features-request.json new file mode 100644 index 000000000..4d186970e --- /dev/null +++ b/static/schemas/source/creative/get-creative-features-request.json @@ -0,0 +1,29 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/creative/get-creative-features-request.json", + "title": "Get Creative Features Request", + "description": "Request payload for get_creative_features task. Evaluates a creative manifest and returns feature values from a creative governance agent.", + "type": "object", + "properties": { + "creative_manifest": { + "$ref": "/schemas/core/creative-manifest.json", + "description": "The creative manifest to evaluate. Contains format_id and assets." + }, + "feature_ids": { + "type": "array", + "description": "Optional filter to specific features. If omitted, returns all available features.", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "context": { + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" + } + }, + "required": ["creative_manifest"], + "additionalProperties": false +} diff --git a/static/schemas/source/creative/get-creative-features-response.json b/static/schemas/source/creative/get-creative-features-response.json new file mode 100644 index 000000000..b7d28106a --- /dev/null +++ b/static/schemas/source/creative/get-creative-features-response.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/creative/get-creative-features-response.json", + "title": "Get Creative Features Response", + "description": "Response payload for get_creative_features task. Returns feature values for the evaluated creative.", + "type": "object", + "oneOf": [ + { + "type": "object", + "description": "Success response", + "properties": { + "results": { + "type": "array", + "description": "Feature values for the evaluated creative", + "items": { + "$ref": "/schemas/creative/creative-feature-result.json" + } + }, + "detail_url": { + "type": "string", + "format": "uri", + "description": "URL to the vendor's full assessment report. The vendor controls what information is disclosed and access control." + }, + "errors": { + "not": {}, + "description": "Field must not be present in success response" + }, + "context": { + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" + } + }, + "required": ["results"] + }, + { + "type": "object", + "description": "Error response", + "properties": { + "errors": { + "type": "array", + "items": { "$ref": "/schemas/core/error.json" } + }, + "results": { + "not": {}, + "description": "Field must not be present in error response" + }, + "context": { + "$ref": "/schemas/core/context.json" + }, + "ext": { + "$ref": "/schemas/core/ext.json" + } + }, + "required": ["errors"] + } + ] +} diff --git a/static/schemas/source/index.json b/static/schemas/source/index.json index 6fd56f340..6b26dbfba 100644 --- a/static/schemas/source/index.json +++ b/static/schemas/source/index.json @@ -993,6 +993,16 @@ "$ref": "/schemas/content-standards/get-media-buy-artifacts-response.json", "description": "Response payload with content artifacts for validation" } + }, + "get-creative-features": { + "request": { + "$ref": "/schemas/creative/get-creative-features-request.json", + "description": "Request parameters for evaluating creative features from a governance agent" + }, + "response": { + "$ref": "/schemas/creative/get-creative-features-response.json", + "description": "Response payload with feature values for the evaluated creative" + } } } }, diff --git a/static/schemas/source/protocol/get-adcp-capabilities-response.json b/static/schemas/source/protocol/get-adcp-capabilities-response.json index fd5bfcd4b..a983ba9da 100644 --- a/static/schemas/source/protocol/get-adcp-capabilities-response.json +++ b/static/schemas/source/protocol/get-adcp-capabilities-response.json @@ -376,7 +376,7 @@ }, "governance": { "type": "object", - "description": "Governance protocol capabilities. Only present if governance is in supported_protocols. Governance agents provide property data like compliance scores, brand safety ratings, and sustainability metrics.", + "description": "Governance protocol capabilities. Only present if governance is in supported_protocols. Governance agents provide property and creative data like compliance scores, brand safety ratings, sustainability metrics, and creative quality assessments.", "properties": { "property_features": { "type": "array", @@ -437,6 +437,66 @@ "type" ] } + }, + "creative_features": { + "type": "array", + "description": "Creative features this governance agent can evaluate. Each feature describes a score, rating, or assessment the agent can provide for creatives (e.g., security scanning, creative quality, content categorization).", + "items": { + "type": "object", + "properties": { + "feature_id": { + "type": "string", + "description": "Unique identifier for this feature (e.g., 'auto_redirect', 'brand_consistency', 'iab_casinos_gambling')" + }, + "type": { + "type": "string", + "enum": [ + "binary", + "quantitative", + "categorical" + ], + "description": "Data type: 'binary' for yes/no, 'quantitative' for numeric scores, 'categorical' for enum values" + }, + "range": { + "type": "object", + "description": "For quantitative features, the valid range", + "properties": { + "min": { + "type": "number", + "description": "Minimum value" + }, + "max": { + "type": "number", + "description": "Maximum value" + } + }, + "required": [ + "min", + "max" + ] + }, + "categories": { + "type": "array", + "description": "For categorical features, the valid values", + "items": { + "type": "string" + } + }, + "description": { + "type": "string", + "description": "Human-readable description of what this feature measures" + }, + "methodology_url": { + "type": "string", + "format": "uri", + "description": "URL to documentation explaining how this feature is calculated or measured." + } + }, + "required": [ + "feature_id", + "type" + ] + } } } },