Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
1b3f1aa
Add Content Standards Protocol for content safety evaluation
bokelley Jan 5, 2026
43f98e1
Simplify content standards policy model
bokelley Jan 5, 2026
004c6df
Fix broken links in content standards docs
bokelley Jan 5, 2026
6d21696
Align content standards with property protocol patterns
bokelley Jan 5, 2026
2ddcbac
Clarify buyer-managed scope selection model
bokelley Jan 5, 2026
dc5fbf8
Address review comments on content standards
bokelley Jan 5, 2026
41a1ab0
Refine content standards schema and examples
bokelley Jan 5, 2026
86d79a4
Integrate robust content-context schema from sit/adcp
bokelley Jan 5, 2026
212bac5
Update changeset to list all 8 tasks
bokelley Jan 7, 2026
dee7861
Rename check_content to calibrate_content for collaborative calibration
bokelley Jan 7, 2026
a0fe830
Use protocol-level context for calibration dialogue
bokelley Jan 7, 2026
d6576ad
Rename content-context to content with assets array
bokelley Jan 7, 2026
f12b35c
Rename content to artifact with property_id + artifact_id
bokelley Jan 7, 2026
59cfe75
Remove signals field, add secured asset access
bokelley Jan 7, 2026
d993487
Add artifacts page, restructure overview with strategic framework
bokelley Jan 7, 2026
69511fc
Simplify artifact schema: assets required, title as asset, add varian…
bokelley Jan 7, 2026
2ba4772
Address review comments on content standards overview
bokelley Jan 7, 2026
a317d96
Simplify calibrate_content response schema and examples
bokelley Jan 7, 2026
a8bab27
Clarify validate_content_delivery data flow: buyer as intermediary
bokelley Jan 7, 2026
be23208
Add get_media_buy_artifacts task for separate content retrieval
bokelley Jan 7, 2026
a920df1
Address review comments on validate_content_delivery schema
bokelley Jan 8, 2026
d7a85a4
Address PR review comments on Content Standards Protocol
bokelley Jan 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changeset/content-standards-protocol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"adcontextprotocol": minor
---

Add Content Standards Protocol for content safety and suitability evaluation.

Discovery tasks:
- `list_content_features`: Discover available content safety features
- `list_content_standards`: List available standards configurations
- `get_content_standards`: Retrieve content safety policies

Management tasks:
- `create_content_standards`: Create a new standards configuration
- `update_content_standards`: Update an existing configuration
- `delete_content_standards`: Delete a configuration

Calibration & Validation tasks:
- `calibrate_content`: Collaborative dialogue to align on policy interpretation
- `validate_content_delivery`: Batch validate delivery records
21 changes: 21 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,27 @@
}
]
},
{
"group": "Content Standards Protocol",
"pages": [
"docs/governance/content-standards/index",
"docs/governance/content-standards/artifacts",
{
"group": "Tasks",
"pages": [
"docs/governance/content-standards/tasks/list_content_features",
"docs/governance/content-standards/tasks/list_content_standards",
"docs/governance/content-standards/tasks/get_content_standards",
"docs/governance/content-standards/tasks/create_content_standards",
"docs/governance/content-standards/tasks/update_content_standards",
"docs/governance/content-standards/tasks/delete_content_standards",
"docs/governance/content-standards/tasks/calibrate_content",
"docs/governance/content-standards/tasks/get_media_buy_artifacts",
"docs/governance/content-standards/tasks/validate_content_delivery"
]
}
]
},
{
"group": "Curation Protocol",
"pages": [
Expand Down
304 changes: 304 additions & 0 deletions docs/governance/content-standards/artifacts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
---
title: Artifacts
sidebar_position: 2
---

# Artifacts

An **artifact** is a unit of content adjacent to an ad placement. When evaluating brand safety and suitability, you're asking: "Is this artifact appropriate for my brand's ads?"

## What Is an Artifact?

Artifacts represent the content context where an ad appears:

- A **news article** on a website
- A **podcast segment** between ad breaks
- A **video chapter** in a YouTube video
- A **social media post** in a feed
- A **scene** in a CTV show
- An **AI-generated image** in a chat conversation

Artifacts are identified by `property_id` + `artifact_id` - the property defines where the content lives, and the artifact_id is an opaque identifier for that specific piece of content. The artifact_id scheme is flexible - it could be a URL path, a platform-specific ID, or any consistent identifier the property owner uses internally.

## Structure

**Schema**: [artifact.json](https://adcontextprotocol.org/schemas/v2/content-standards/artifact.json)

```json
{
"property_id": {"type": "domain", "value": "reddit.com"},
"artifact_id": "r_fitness_post_abc123",
"assets": [
{"type": "text", "role": "title", "content": "Best protein sources for muscle building", "language": "en"},
{"type": "text", "role": "paragraph", "content": "Looking for recommendations on high-quality protein sources...", "language": "en"},
{"type": "image", "url": "https://cdn.reddit.com/fitness-image.jpg", "alt_text": "Person lifting weights"}
]
}
```

### Required Fields

| Field | Description |
|-------|-------------|
| `property_id` | Where this artifact lives - uses standard identifier types (`domain`, `app_id`, `apple_podcast_id`, etc.) |
| `artifact_id` | Unique identifier within the property - the property owner defines their scheme |
| `assets` | Content in document order - text blocks, images, video, audio |

### Optional Fields

| Field | Description |
|-------|-------------|
| `variant_id` | Identifies a specific variant (A/B test, translation, temporal version) |
| `format_id` | Reference to format registry (same as creative formats) |
| `url` | Web URL if the artifact has one |
| `metadata` | Artifact-level metadata (Open Graph, JSON-LD, author info) |
| `published_time` | When the artifact was published |
| `last_update_time` | When the artifact was last modified |

## Variants

The same artifact may have multiple variants:

- **Translations** - English version vs Spanish version
- **A/B tests** - Different headlines being tested
- **Temporal versions** - Content that changed on Wednesday

Use `variant_id` to distinguish between them:

```json
// English version
{
"property_id": {"type": "domain", "value": "nytimes.com"},
"artifact_id": "article_12345",
"variant_id": "en",
"assets": [
{"type": "text", "role": "title", "content": "Breaking News Story", "language": "en"}
]
}

// Spanish translation
{
"property_id": {"type": "domain", "value": "nytimes.com"},
"artifact_id": "article_12345",
"variant_id": "es",
"assets": [
{"type": "text", "role": "title", "content": "Noticia de última hora", "language": "es"}
]
}

// A/B test variant
{
"property_id": {"type": "domain", "value": "nytimes.com"},
"artifact_id": "article_12345",
"variant_id": "headline_test_b",
"assets": [
{"type": "text", "role": "title", "content": "Alternative Headline Being Tested", "language": "en"}
]
}
```

The combination of `artifact_id` + `variant_id` must be unique within a property. This lets you track which variant a user saw and correlate it with delivery reports.

## Asset Types

Assets are the actual content within an artifact. Everything is an asset - titles, paragraphs, images, videos.

### Text

```json
{"type": "text", "role": "title", "content": "Article Title", "language": "en"}
{"type": "text", "role": "paragraph", "content": "The article body text...", "language": "en"}
{"type": "text", "role": "description", "content": "A summary of the article", "language": "en"}
{"type": "text", "role": "heading", "content": "Section Header", "heading_level": 2}
{"type": "text", "role": "quote", "content": "A quoted statement"}
```

Roles: `title`, `description`, `paragraph`, `heading`, `caption`, `quote`, `list_item`

Each text asset can have its own `language` tag for mixed-language content.

### Image

```json
{
"type": "image",
"url": "https://cdn.example.com/photo.jpg",
"alt_text": "Description of the image"
}
```

### Video

```json
{
"type": "video",
"url": "https://cdn.example.com/video.mp4",
"transcript": "Full transcript of the video content...",
"duration_ms": 180000
}
```

### Audio

```json
{
"type": "audio",
"url": "https://cdn.example.com/podcast.mp3",
"transcript": "Today we're discussing...",
"duration_ms": 3600000
}
```

## Metadata

Artifact-level metadata describes the artifact as a whole, not individual assets:

```json
{
"metadata": {
"author": "Jane Smith",
"canonical": "https://example.com/article/12345",
"open_graph": {
"og:type": "article",
"og:site_name": "Example News"
},
"json_ld": [
{
"@type": "NewsArticle",
"datePublished": "2025-01-15"
}
]
}
}
```

This is separate from assets because it's about the artifact container, not the content itself.

## Secured Asset Access

Many assets aren't publicly accessible - AI-generated images, private conversations, paywalled content. The artifact schema supports authenticated access.

### Pre-Configuration (Recommended)

For ongoing partnerships, configure access once during onboarding rather than per-request:

1. **Service account sharing** - Grant the verification agent access to your cloud storage
2. **OAuth client credentials** - Set up machine-to-machine authentication
3. **API key exchange** - Share long-lived API keys during setup

This happens during the activation phase when the seller first receives content standards from a buyer.

### Per-Asset Authentication

When pre-configuration isn't possible, include access credentials with individual assets:

```json
{
"type": "image",
"url": "https://cdn.openai.com/secured/img_abc123.png",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could consider distinguishing the published official URL from some internal access URL (e.g.,a GCS bucket or something).

"access": {
"method": "bearer_token",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
Comment on lines +199 to +202
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of tokens (e.g., we've seen web pages where we extract hundreds of images... whether or not that's a good idea).

I'd consider extracting an auth mechanism that could be referenced, either within the response or outside the workflow.

}
```

**Note on token size**: For artifacts with many assets, per-asset tokens can significantly increase payload size. Consider:

1. **Pre-configured access** - Set up service account access once during onboarding
2. **Shared token reference** - Define tokens at the artifact level and reference by ID
3. **Signed URLs** - Use pre-signed URLs where the URL itself is the credential

The `url` field is the access URL - it may differ from the artifact's canonical/published URL. For example, a published article at `https://news.example.com/article/123` might have assets served from `https://cdn.example.com/secured/...`.

### Access Methods

| Method | Use Case |
|--------|----------|
| `bearer_token` | OAuth2 bearer token in Authorization header |
| `service_account` | GCP/AWS service account credentials |
| `signed_url` | Pre-signed URL with embedded credentials (URL itself is the credential) |

### Service Account Setup

For GCP:

```json
{
"access": {
"method": "service_account",
"provider": "gcp",
"credentials": {
"type": "service_account",
"project_id": "my-project",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...",
"client_email": "[email protected]"
}
}
}
```

For AWS:

```json
{
"access": {
"method": "service_account",
"provider": "aws",
"credentials": {
"access_key_id": "AKIAIOSFODNN7EXAMPLE",
"secret_access_key": "...",
"region": "us-east-1"
}
}
}
```

### Pre-Signed URLs

For one-off access without sharing credentials:

```json
{
"type": "video",
"url": "https://storage.googleapis.com/bucket/video.mp4?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=...&X-Goog-Signature=...",
"access": {
"method": "signed_url"
}
}
```

The URL itself contains the credentials - no additional authentication needed.

## Property Identifier Types

The `property_id` uses standard identifier types from the AdCP property schema:

| Type | Example | Use Case |
|------|---------|----------|
| `domain` | `reddit.com` | Websites |
| `app_id` | `com.spotify.music` | Mobile apps |
| `apple_podcast_id` | `1234567890` | Apple Podcasts |
| `spotify_show_id` | `4rOoJ6Egrf8K2IrywzwOMk` | Spotify podcasts |
| `youtube_channel_id` | `UCddiUEpeqJcYeBxX1IVBKvQ` | YouTube channels |
| `rss_url` | `https://feeds.example.com/podcast.xml` | RSS feeds |

## Artifact ID Schemes

The property owner defines their artifact_id scheme. Examples:

| Property Type | Artifact ID Pattern | Example |
|---------------|---------------------|---------|
| News website | `article_{id}` | `article_12345` |
| Reddit | `r_{subreddit}_{post_id}` | `r_fitness_abc123` |
| Podcast | `episode_{num}_segment_{num}` | `episode_42_segment_2` |
| CTV | `show_{id}_s{season}e{episode}_scene_{num}` | `show_abc_s3e5_scene_12` |
| Social feed | `post_{id}` | `post_xyz789` |

The verification agent doesn't need to understand the scheme - it's opaque. The property owner uses it to correlate artifacts with their content.

## Related

- [Content Standards Overview](/docs/governance/content-standards) - How artifacts fit into the content standards workflow
- [calibrate_content](/docs/governance/content-standards/tasks/calibrate_content) - Sending artifacts for calibration
Loading