Apache-2.0updated 7d ago
A signals agent serves audience segments to buyers for campaign targeting. Two tools: getsignals (discovery) and activatesignal (push to DSPs or sales agents). The business model — marketplace vs owned data — shapes every implementation decision. Determine that first.
O que dá para fazer com Build Signals Agent?
name: build-signals-agent description: Use when building an AdCP signals agent, creating an audience data server, or standing up a data provider agent that serves targeting segments to buyers.
Build a Signals Agent
Overview
A signals agent serves audience segments to buyers for campaign targeting. Two tools: get_signals (discovery) and activate_signal (push to DSPs or sales agents). The business model — marketplace vs owned data — shapes every implementation decision. Determine that first.
When to Use
- User wants to build an agent that serves audience/targeting data
- User mentions signals, segments, audiences, data provider, or CDP in the context of AdCP
- User references
get_signals,activate_signal, or the signals protocol
Not this skill:
- Selling ad inventory (products, packages, media buys) →
skills/build-seller-agent/ - Rendering creatives from briefs → that's a creative agent
- Building a client that calls a signals agent → see
docs/getting-started.md
Before Writing Code
Determine these four things. Ask the user — don't guess.
1. Marketplace or Owned?
These are fundamentally different businesses.
Marketplace — aggregates third-party data providers (LiveRamp, Oracle Data Cloud, Lotame). Each signal traces to a data_provider_domain that buyers can verify via adagents.json. signal_type: "marketplace", signal_id.source: "catalog".
Owned — first-party data (retailer CDP, publisher contextual, CRM). Buyers trust your agent directly. signal_type: "owned" or "custom", signal_id.source: "agent".
2. What Segments?
Get specifics: names, definitions, what each represents. Push for 3-5 segments with variety. Each needs:
- Clear behavioral/demographic definition
- Realistic
coverage_percentage(typically 5-30%) - Value type:
binary(in/out),categorical(tier levels — define the categories), ornumeric(score range — define min/max)
3. Pricing
At least one pricing option per signal. Signals use VendorPricingOption (field: model), distinct from product PricingOption (field: pricing_model).
cpm—{ pricing_option_id: "po_cpm", model: "cpm", cpm: 2.50, currency: "USD" }percent_of_media—{ pricing_option_id: "po_pom", model: "percent_of_media", percent: 15, currency: "USD" }flat_fee—{ pricing_option_id: "po_flat", model: "flat_fee", amount: 5000, period: "monthly", currency: "USD" }
4. Activation Destinations
If implementing activate_signal:
- Platform (DSP):
type: "platform", returnsactivation_key: { type: "segment_id", segment_id: "..." } - Agent (sales agent):
type: "agent", returnsactivation_key: { type: "key_value", key: "...", value: "..." }
Tools and Required Response Shapes
get_adcp_capabilities — register first, empty {} schema
capabilitiesResponse({
adcp: { major_versions: [3] },
supported_protocols: ['signals'],
})
get_signals — GetSignalsRequestSchema.shape
Two discovery modes — support both:
signal_spec— natural language. Match against segment names and descriptions.signal_ids— exact lookup by{ source, data_provider_domain, id }or{ source, agent_url, id }.
Plus filtering via filters.catalog_types, filters.max_cpm, filters.min_coverage_percentage, and max_results.
getSignalsResponse({
signals: [{
signal_agent_segment_id: string, // required - key for activate_signal
name: string, // required
description: string, // required
signal_type: 'marketplace' | 'owned' | 'custom', // required
data_provider: string, // required - your company name
coverage_percentage: number, // required - 0 to 100
deployments: [], // required - empty array (not live until activated)
pricing_options: [{ // required - at least one
pricing_option_id: string, // required
model: 'cpm', // required - discriminator
cpm: number, // required for cpm model
currency: 'USD', // required
}],
// signal_id is critical — shape depends on marketplace vs owned:
signal_id: {
source: 'catalog', // marketplace
data_provider_domain: string, // marketplace — domain for provenance verification
id: string, // unique segment ID
},
// OR for owned:
signal_id: {
source: 'agent', // owned
agent_url: string, // your agent URL
id: string,
},
value_type: 'binary' | 'categorical' | 'numeric', // optional but recommended
}],
sandbox: true, // for mock data
})
activate_signal — ActivateSignalRequestSchema.shape
Look up by signal_agent_segment_id. Validate pricing_option_id. Return deployments matching the requested destinations.
activateSignalResponse({
deployments: [{
// Match the destination type from the request:
type: 'platform', // for platform destinations
platform: string, // echo from request destination
account: string | null, // echo from request
is_live: true, // signal is now active
activation_key: {
type: 'segment_id',
segment_id: string, // platform-specific segment ID
},
}],
// OR for agent destinations:
deployments: [{
type: 'agent',
agent_url: string,
is_live: true,
activation_key: {
type: 'key_value',
key: string,
value: string,
},
}],
sandbox: true,
})
SDK Quick Reference
| SDK piece | Usage |
|---|---|
serve(createAgent) |
Start HTTP server on :3001/mcp |
createTaskCapableServer(name, version, { taskStore }) |
Create MCP server with task support |
server.tool(name, Schema.shape, handler) |
Register tool — .shape unwraps Zod |
capabilitiesResponse(data) |
Build get_adcp_capabilities response |
getSignalsResponse(data) |
Build get_signals response |
activateSignalResponse(data) |
Build activate_signal response |
taskToolResponse(data, summary) |
Build generic tool response (for tools without a dedicated builder) |
adcpError(code, { message }) |
Structured error (SIGNAL_NOT_FOUND, INVALID_DESTINATION) |
GetSignalsRequestSchema.shape |
Zod schema for get_signals input |
ActivateSignalRequestSchema.shape |
Zod schema for activate_signal input |
type Signal = GetSignalsResponse['signals'][number] |
Type for a single signal object |
Import everything from @adcp/sdk. Types from @adcp/sdk with import type.
Setup
npm init -y
npm install @adcp/sdk
npm install -D typescript @types/node
Minimal tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"skipLibCheck": true,
"outDir": "dist"
}
}
skipLibCheck: true avoids false-positive errors from transitive .d.ts files (e.g., @opentelemetry/api).
Implementation
- Single
.tsfile — all tools in one file - Always register
get_adcp_capabilitiesas the first tool with empty{}schema - Use
Schema.shape(notSchema) when registering tools - Set
sandbox: truefor mock/demo data - Use
ServeContextpattern:function createAgent({ taskStore }: ServeContext)
The skill contains everything you need. Do not read additional docs before writing code.
Validation
After writing the agent, validate it. Fix failures. Repeat.
Full validation (if you can bind ports):
npx tsx agent.ts &
npx @adcp/sdk@latest storyboard run http://localhost:3001/mcp signal_owned --json # for owned data
npx @adcp/sdk@latest storyboard run http://localhost:3001/mcp signal_marketplace --json # for marketplace
Sandbox validation (if ports are blocked):
npx tsc --noEmit agent.ts
Keep iterating until all steps pass.
Common Mistakes
| Mistake | Fix |
|---|---|
Pass Schema instead of Schema.shape |
MCP SDK needs unwrapped Zod fields |
Skip get_adcp_capabilities |
Must be the first tool registered |
Missing signal_agent_segment_id on signals |
Buyers can't activate without it |
Wrong signal_id shape |
Marketplace: { source: "catalog", data_provider_domain, id }. Owned: { source: "agent", agent_url, id } |
Missing data_provider field |
Required on every signal — your company/brand name |
Empty pricing_options array |
Must have at least one pricing option per signal |
is_live: true in get_signals deployments |
Signals aren't live until activate_signal — use empty deployments: [] |
| Activation doesn't match destination type | If request has type: "platform", deployment must be type: "platform" |
sandbox: false on mock data |
Buyers may treat mock data as real |
Reference
examples/signals-agent.ts— complete runnable examplestoryboards/signal_marketplace.yaml— buyer call sequences for marketplace agentstoryboards/signal_owned.yaml— call sequences for owned data agentdocs/guides/BUILD-AN-AGENT.md— SDK patternsdocs/TYPE-SUMMARY.md— curated type signaturesdocs/llms.txt— full protocol reference
Instalação
Adicione Build Signals Agent ao seu cliente. Escolha o que você usa.
npx skills add adcontextprotocol/adcp-clientInstalls every skill in the repository, then prompts for which to keep.
/plugin marketplace add adcontextprotocol/adcp-clientAdds the repository as a plugin marketplace; install individual plugins with `/plugin install`.
git clone https://github.com/adcontextprotocol/adcp-client
cp -r .claude/skills/build-signals-agent ~/.claude/skills/A skill is a plain directory. Copy it into `.claude/skills/` in a project or in your home directory.
Pontuação
78 / 100
Boa