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"
+ ]
+ }
}
}
},