Skip to content

RFC: competence advertisement for AdCP agents — declare what an agent can do within its capabilities #6287

Description

@lukasz-pubx

Summary

get_adcp_capabilities tells a counterparty what an agent's deployment supports — feature
flags and compliance claims. Nothing on the wire tells a counterparty what the agent can
do in a conversation: whether the free-text asks the protocol already carries (refine
asks, briefs) will land on an agent that can reason about them. This proposes an optional,
non-breaking competence advertisement — a get_adcp_competences task returning name +
description pairs (e.g. price-negotiation, signal-selection) — so buyers can match
conversational asks to declared competence instead of discovering incapability by wasted
round-trips. The layering is the point: a capability says the agent processes refinement
requests; a competence says what the agent can do inside them — negotiate price, reason
about what "similar" means. Competences sit on top of capabilities; they never substitute
for them.

Current state (as of 298d99c85, docs build 3.1.2)

  • Capabilities are feature flags. get_adcp_capabilities returns deployment facts —
    e.g. media_buy.features.inline_creative_management: true — which gate which requests are
    accepted
    , not which conversations are understood.
  • Specialisms are compliance claims, not competence hints.
    protocol/get-adcp-capabilities-response.json defines specialisms as "specialized
    compliance claims this agent supports. Values MUST be kebab-case enum IDs" — a closed enum
    (enums/specialism.json) wired to the AAO compliance runner's storyboard bundles. It
    verifies protocol conformance per domain; it says nothing about conversational depth
    within a domain.
  • The refinement surface already invites conversation it cannot scope.
    media-buy/get-products-request.json defines refine[] entries with
    action: ["include", "omit", "more_like_this"] plus free-text ask fields at entry and
    request level. The docs say the quiet part:

    "But for campaigns involving multiple products, proposals with budget allocations, or
    iterative negotiation, refinement is where the value is."
    (docs/media-buy/product-discovery/refinement.mdx)
    Nothing tells the buyer whether the seller can actually negotiate — the ask is free text,
    and any handling of it is conformant.

  • Runtime discovery was considered and deferred — for schemas. Known limitations records:
    "A runtime tool was considered in Spec: standardize a get_schema capability tool for transport-symmetric schema discovery #3057 and deferred — the SKILL.md path covers coding-agent
    discoverability, the schema-bundle URLs cover SDK builders." That reasoning holds for
    schemas because every conformant agent has the same shapes, so out-of-band distribution
    works. Conversational competence is per-agent: no spec-packaged file can say whether
    this seller negotiates. The out-of-band escape hatch that justified deferring Spec: standardize a get_schema capability tool for transport-symmetric schema discovery #3057 does
    not exist for this problem.

Problem

A buyer in buying_mode: "refine" sends a request-level ask: "this plan, but at $12 CPM
rather than $15 — willing to drop the CTV package for it."
Two conformant sellers:

  • Seller A reasons about margins and data costs and returns a counter-proposal.
  • Seller B is a mechanical refiner: it matches no product_id change request, treats the ask
    as unactionable free text, and returns the same products at $15.

Both are conformant — ask is advisory free text. The buyer cannot distinguish "no" from
"didn't understand": it may burn further refinement rounds negotiating with an agent that
cannot negotiate ("blind luck"), or worse, an orchestrator treats the returned $15 plan as
seller A-style considered output and proceeds toward create_media_buy on terms the ask was
specifically trying to move. The same failure shape applies to more_like_this (an agent
that cannot reason about what "similar" means, versus one that can ask "similar in cost, or
a lookalike audience?") and to signal selection conversations.

The general form: the protocol's free-text surfaces assume a sophistication the protocol
gives agents no way to declare.
Smart agents can figure things out; less sophisticated
agents need explicit, strict requests — and the buyer can't tell which it is facing until
after the tokens (and rounds, and sometimes commitments) are spent.

Proposed change

Optional, additive, advisory. Three parts:

  1. New optional task get_adcp_competences (schema pair under
    static/schemas/source/protocol/). Request: empty object, optionally
    { "domain": "media_buy" } to filter. Response:

    {
      "competences": [
        {
          "name": "price-negotiation",
          "description": "Can negotiate price and terms on refine asks: reasons about margins, data costs, and package trade-offs, and returns counter-proposals."
        },
        {
          "name": "signal-selection",
          "description": "Can discuss signal and signal-provider choices and recommend alternatives against a brief."
        }
      ]
    }

    name: free-form kebab-case (open vocabulary — deliberately not an enum; see
    Alternatives). description: what the counterparty can expect the agent to understand and
    do, in one to three sentences. The shape is directly inspired by what agent-skill
    ecosystems expose as frontmatter (name + description, per the agentskills.io
    specification) — enough for a counterparty LLM to route on, without exposing
    implementation. The wire vocabulary is deliberately competence, not "skill": this repo
    already ships skills/ — coding-agent skills bundled with the protocol tarball
    (feat(skills): hoist call-adcp-agent + bundle skills/ into protocol tarball #3097/release: re-cut 3.0.0 tarball with skills/ + manifest.contents.skills #3116, and the SKILL.md path in known limitations) — and overloading the noun would
    invite exactly the confusion this task exists to remove.

  2. Discovery pointer in get_adcp_capabilities: one optional boolean (e.g.
    adcp.competence_discovery: true) advertising that the task is available. Two calls
    rather than inlining, deliberately: it keeps the capabilities response lean for the
    majority of callers that never need competences, and progressive disclosure matches the
    protocol's existing discovery chain (capabilities first, detail tools on demand).

  3. Explicit non-goals, stated normatively in the doc page:

    • Declaring a competence is advisory, not a compliance claim — no storyboard
      verification, no conformance semantics; absence of a competence means undeclared, not
      incapable.
    • No competence-body exposure on the wire: names and descriptions only. Whether an agent's
      internal implementation is an Anthropic-style SKILL.md (the inspiration for this
      mechanism), a fine-tune, or hardcoded logic is the implementor's business.
    • No new request semantics: a declared competence grants no new fields and changes no
      handling rules; asks remain asks. The declaration only informs the counterparty's choice
      of what to attempt.

Normativity/optionality per addition: get_adcp_competences — optional task, response
shape normative when implemented; competence_discovery flag — optional; competence
semantics — advisory.

Rationale and evidence

Alternatives considered

  • Extend specialisms. Rejected: specialisms are closed-enum compliance claims with
    runner semantics (an agent omitting one is skipped by compliance tracks). Overloading them
    with open-vocabulary advisory hints would weaken both meanings. The three surfaces layer
    cleanly: capability = "I accept these requests"; specialism = verified "I conform to X";
    competence = advisory "I can converse about Y".
  • Inline competences[] in the capabilities response. Workable, and acceptable if maintainers
    prefer one surface — the cost is response bloat on every capabilities call for data most
    callers need rarely; the two-call shape preserves progressive disclosure.
  • Per-proposal negotiability declaration (proposal.negotiable, from reviewer feedback). An optional
    typed field on core/proposal.json declaring which dimensions of a specific offer are open
    (e.g. "negotiable": ["pricing", "allocation"]). Strictly better than a competence claim on
    proposal surfaces
    : it anchors to the object being negotiated, is per-deal rather than
    per-agent (no drift, no RFC: capability-change notifications for get_adcp_capabilities #5794 staleness question), and proposal_status gives it a substrate
    for default semantics (committed + absent negotiable = firm) that no agent-level mechanism
    can offer. Not adopted as a substitute because it cannot cover pre-proposal surfaces —
    seller selection, brief mode, request-level asks, more_like_this, signal-selection — where
    the "no vs. didn't understand" failure begins and no proposal object exists. Proposed instead
    as a companion addition: proposal-level negotiable is authoritative for in-deal
    negotiation; competences cover pre-engagement routing. See discussion in the issue thread.
  • A standardized competence taxonomy (enum) from day one. Premature: the useful vocabulary is
    unknown until agents advertise in the open. Open vocabulary now; if names converge,
    standardization can follow the same path specialisms took (free practice → enum + bundles).
  • Do nothing. The cost is the failure narrative above, recurring: wasted refinement
    rounds, misread non-responses, and orchestrators proceeding on terms an ask tried to move.

Compatibility and migration

Purely additive: a new optional task plus one optional boolean. Agents that implement
neither behave exactly as today; callers that don't check the flag lose nothing. No changes
to any existing schema's required fields; no version-boundary framing needed (3.x-compatible).

Files affected (as of 298d99c85 — re-verify at implementation time)

  • static/schemas/source/protocol/get-adcp-competences-request.json (new)
  • static/schemas/source/protocol/get-adcp-competences-response.json (new)
  • static/schemas/source/protocol/get-adcp-capabilities-response.json (optional
    competence_discovery flag)
  • A docs page (plausibly the docs/building/implementation/agent-capabilities.mdx that
    docs: knowledge gap (critical) — Distinguishing Refinement from Negotiation Skills #6101 proposes, giving its patch the mechanism it currently lacks)
  • No enum changes; no changes to refinement or any existing task schemas

Open questions

  1. Terminology: "competence" is chosen deliberately — this repo already ships skills/
    (coding-agent skills bundled with the protocol tarball, feat(skills): hoist call-adcp-agent + bundle skills/ into protocol tarball #3097/release: re-cut 3.0.0 tarball with skills/ + manifest.contents.skills #3116, and the SKILL.md path
    in known limitations), so reusing "skill" on the wire would overload the noun. It also
    reads well next to specialisms: the capabilities response would carry two Latinate
    declaration surfaces with cleanly split semantics — verified conformance versus advisory
    depth — rather than one Latinate term and one borrowed from a different ecosystem's
    jargon. If maintainers prefer a different term (agent_skills, soft_capabilities), the
    mechanism matters more than the noun.
  2. Should competence entries carry an optional task_scope (e.g. get_products.refine) anchoring
    where the competence applies, or stay free-form until practice shows the need?
  3. Is there appetite for an optional richer exposure later (full competence descriptions,
    akin to public skill registries), or does name + description remain the ceiling on the
    wire?

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-triagedIssue has been triaged by the Claude Code triage routine. Remove to re-triage.needs-wg-reviewBlocked on a working-group decision — surface in WG meeting agendasrfcProtocol change — auto-adds to roadmap boardspec / protocol

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions