Context
adcontextprotocol/adcp#3097 (merged) bundles agent-facing skills (skills/call-adcp-agent/SKILL.md plus per-protocol task skills) into the published protocol tarball at /protocol/<version>.tgz alongside schemas and compliance. Companion PR adcontextprotocol/adcp-client#965 wires the JS SDK to extract them on sync.
This issue tracks the equivalent for the Python SDK.
What's in the tarball
The tarball's manifest.json now enumerates protocol-managed skills:
{
"contents": {
"schemas": true,
"compliance": true,
"skills": ["adcp-brand", "adcp-creative", "adcp-governance", "adcp-media-buy", "adcp-si", "adcp-signals", "call-adcp-agent"],
...
}
}
The seven directories live at adcp-{version}/skills/<name>/, each containing a SKILL.md (the agent-facing wire contract). Per-protocol skills also bundle a schemas/ subdir which should be filtered out — the SDK already has those in schemas/cache/<version>/.
Proposal
Extend the Python SDK's schema-sync path (or add a new sync_skills step) to:
- After extracting the tarball, read
manifest.json.
- For each name in
manifest.contents.skills (when present and an array), copy <extract>/skills/<name>/ into the SDK's local skills/<name>/, excluding nested schemas/ subdirs.
- Snapshot the previous tree as
<dst>.previous (matches the pattern used for schemas/compliance).
- Manifest-driven means SDK-local skills (anything not enumerated) stay untouched — preserves any Python-SDK-specific skill packaging.
Reference implementation
JS sync: scripts/sync-schemas.ts in adcontextprotocol/adcp-client#965. The function syncSkillsFromBundle is ~30 lines; copySkillTree + copyTreeFiltered add another ~30. Translate to Python idiomatically.
Why now
Without this sync, the buyer-side call-adcp-agent skill (the canonical wire contract: idempotency replay, account oneOf variants, async submitted polling, error recovery via adcp_error.issues[]) doesn't reach Python SDK consumers. Coding agents (Claude Code, Cursor, Cline) using the Python SDK package would see no skill content at all — they'd fall back to training-data hallucinations of AdCP shapes, which we've already observed (anonymous Addie tier hallucinated account_name+account_email for the oneOf instead of the correct {account_id} OR {brand:{domain}, operator}).
Out of scope
- Adding new skills (those are tracked as separate issues in adcp-client and the spec repo)
- Changing the manifest format (already settled upstream)
Co-tracked: adcontextprotocol/adcp-go (same ask, different SDK).
Context
adcontextprotocol/adcp#3097 (merged) bundles agent-facing skills (
skills/call-adcp-agent/SKILL.mdplus per-protocol task skills) into the published protocol tarball at/protocol/<version>.tgzalongside schemas and compliance. Companion PR adcontextprotocol/adcp-client#965 wires the JS SDK to extract them on sync.This issue tracks the equivalent for the Python SDK.
What's in the tarball
The tarball's
manifest.jsonnow enumerates protocol-managed skills:{ "contents": { "schemas": true, "compliance": true, "skills": ["adcp-brand", "adcp-creative", "adcp-governance", "adcp-media-buy", "adcp-si", "adcp-signals", "call-adcp-agent"], ... } }The seven directories live at
adcp-{version}/skills/<name>/, each containing aSKILL.md(the agent-facing wire contract). Per-protocol skills also bundle aschemas/subdir which should be filtered out — the SDK already has those inschemas/cache/<version>/.Proposal
Extend the Python SDK's schema-sync path (or add a new
sync_skillsstep) to:manifest.json.manifest.contents.skills(when present and an array), copy<extract>/skills/<name>/into the SDK's localskills/<name>/, excluding nestedschemas/subdirs.<dst>.previous(matches the pattern used for schemas/compliance).Reference implementation
JS sync: scripts/sync-schemas.ts in adcontextprotocol/adcp-client#965. The function
syncSkillsFromBundleis ~30 lines;copySkillTree+copyTreeFilteredadd another ~30. Translate to Python idiomatically.Why now
Without this sync, the buyer-side
call-adcp-agentskill (the canonical wire contract: idempotency replay, account oneOf variants, async submitted polling, error recovery viaadcp_error.issues[]) doesn't reach Python SDK consumers. Coding agents (Claude Code, Cursor, Cline) using the Python SDK package would see no skill content at all — they'd fall back to training-data hallucinations of AdCP shapes, which we've already observed (anonymous Addie tier hallucinatedaccount_name+account_emailfor the oneOf instead of the correct{account_id}OR{brand:{domain}, operator}).Out of scope
Co-tracked: adcontextprotocol/adcp-go (same ask, different SDK).