← back to A2a Lab
generate A2A agent cards from cabinet.yaml (12 VPs / 166 skills), round-trip verified
9ea5e3d9199ba64df7bdd7e982026239149d977f · 2026-08-01 21:09:33 -0700 · Steve
Tolerant line parser (cabinet.yaml is not strict-YAML); each director owns -> AgentSkill.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M README.mdA cabinet_cards.pyA cards/vp-abramsego.agent-card.jsonA cards/vp-cncp.agent-card.jsonA cards/vp-compliance-policy.agent-card.jsonA cards/vp-consulting.agent-card.jsonA cards/vp-directories.agent-card.jsonA cards/vp-dw-commerce.agent-card.jsonA cards/vp-dw-marketing.agent-card.jsonA cards/vp-engineering.agent-card.jsonA cards/vp-operations.agent-card.jsonA cards/vp-research-content.agent-card.jsonA cards/vp-security.agent-card.jsonA cards/vp-special-projects.agent-card.jsonM requirements.txt
Diff
commit 9ea5e3d9199ba64df7bdd7e982026239149d977f
Author: Steve <steve@designerwallcoverings.com>
Date: Sat Aug 1 21:09:33 2026 -0700
generate A2A agent cards from cabinet.yaml (12 VPs / 166 skills), round-trip verified
Tolerant line parser (cabinet.yaml is not strict-YAML); each director owns -> AgentSkill.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
README.md | 19 ++
cabinet_cards.py | 152 +++++++++++++
cards/vp-abramsego.agent-card.json | 78 +++++++
cards/vp-cncp.agent-card.json | 51 +++++
cards/vp-compliance-policy.agent-card.json | 69 ++++++
cards/vp-consulting.agent-card.json | 78 +++++++
cards/vp-directories.agent-card.json | 69 ++++++
cards/vp-dw-commerce.agent-card.json | 222 ++++++++++++++++++
cards/vp-dw-marketing.agent-card.json | 312 ++++++++++++++++++++++++++
cards/vp-engineering.agent-card.json | 276 +++++++++++++++++++++++
cards/vp-operations.agent-card.json | 150 +++++++++++++
cards/vp-research-content.agent-card.json | 348 +++++++++++++++++++++++++++++
cards/vp-security.agent-card.json | 69 ++++++
cards/vp-special-projects.agent-card.json | 60 +++++
requirements.txt | 1 +
15 files changed, 1954 insertions(+)
diff --git a/README.md b/README.md
index 33ffe04..6f53a57 100644
--- a/README.md
+++ b/README.md
@@ -101,6 +101,25 @@ A2A_BASE=http://127.0.0.1:41242 python client.py "dm vp-operations check the pg
# → sent M-00001 a2a-bridge→vp-operations: check the pg lock canary
```
+## Cabinet agent cards (generated, verified)
+
+`cabinet_cards.py` turns `~/Projects/agent-cabinet/cabinet.yaml` (the org chart:
+President → VP → Director → Skills) into one A2A `AgentCard` per VP — each director's
+`owns` line becomes an `AgentSkill`. Output: `cards/<vp>.agent-card.json`.
+
+```bash
+python cabinet_cards.py # → 12 cabinet cards / 166 skills in cards/
+```
+
+Verified: all 12 cards round-trip back into valid proto `AgentCard`s. This is the
+registry a live A2A directory would serve so officers/directors are **discoverable and
+callable over the protocol** (the `supportedInterfaces` URLs are a convention until a
+directory server assigns real ports — that's the next step).
+
+Note: `cabinet.yaml` is **not strictly-valid YAML** (its `owns: [...]` flow lists carry
+unquoted prose with `:` and `/`, which PyYAML rejects), so the generator uses a tolerant
+line parser. That invalidity is a latent bug for anything that YAML-loads the file.
+
## Next steps (not done — future work)
- Add an A2A *client-side* helper using the SDK's own `create_client` (proto
diff --git a/cabinet_cards.py b/cabinet_cards.py
new file mode 100644
index 0000000..2c66083
--- /dev/null
+++ b/cabinet_cards.py
@@ -0,0 +1,152 @@
+"""Generate A2A agent cards from Steve's cabinet.yaml.
+
+Turns ~/Projects/agent-cabinet/cabinet.yaml (the org chart: President → VP →
+Director → Skills) into one A2A `AgentCard` per VP, where each director's `owns`
+line becomes an `AgentSkill`. Writes cards/<vp>.agent-card.json (proto→JSON).
+
+NOTE: cabinet.yaml is NOT strictly-valid YAML — its `owns: [...]` flow lists carry
+unquoted prose with ':' and '/', which PyYAML rejects. So this uses a tolerant,
+shallow line parser for exactly the fields we need rather than a YAML load.
+
+Run: . .venv/bin/activate && python cabinet_cards.py
+"""
+from __future__ import annotations
+
+import json
+import re
+from pathlib import Path
+
+from google.protobuf.json_format import MessageToDict
+
+from a2a.types import AgentCard, AgentInterface, AgentCapabilities, AgentSkill
+
+CABINET = Path.home() / "Projects" / "agent-cabinet" / "cabinet.yaml"
+OUT = Path(__file__).parent / "cards"
+# Convention only — these cards describe capabilities; a live directory server would
+# assign real ports. Base kept explicit so it's obvious they aren't served yet.
+BASE = "http://127.0.0.1:41300"
+
+
+def slug(s: str) -> str:
+ return re.sub(r"[^a-z0-9]+", "-", (s or "").lower()).strip("-")[:40]
+
+
+def parse_cabinet(text: str) -> list[dict]:
+ """Shallow, tolerant parse: vp / domain / triggers[] / directors[{name,kind,owns}]."""
+ vps: list[dict] = []
+ cur: dict | None = None
+ section: str | None = None # 'triggers' | 'directors' | None
+ pending_dir: dict | None = None
+
+ for raw in text.splitlines():
+ if not raw.strip() or raw.lstrip().startswith("#"):
+ continue
+ m_vp = re.match(r"^\s{2}-\s+vp:\s*(.+?)\s*$", raw)
+ if m_vp:
+ if cur:
+ if pending_dir:
+ cur["directors"].append(pending_dir)
+ pending_dir = None
+ vps.append(cur)
+ cur = {"vp": m_vp.group(1).strip(), "domain": "", "triggers": [], "directors": []}
+ section = None
+ continue
+ if cur is None:
+ continue
+ m_dom = re.match(r"^\s{4}domain:\s*(.+?)\s*$", raw)
+ if m_dom:
+ cur["domain"] = m_dom.group(1).strip()
+ section = None
+ continue
+ if re.match(r"^\s{4}triggers:\s*$", raw):
+ section = "triggers"
+ continue
+ if re.match(r"^\s{4}directors:\s*$", raw):
+ if pending_dir:
+ cur["directors"].append(pending_dir)
+ pending_dir = None
+ section = "directors"
+ continue
+ if section == "triggers":
+ m = re.match(r"^\s{6}-\s+(.+?)\s*$", raw)
+ if m:
+ cur["triggers"].append(m.group(1).strip())
+ continue
+ if section == "directors":
+ m_d = re.match(r"^\s{6}-\s+(skill|subagent):\s*(.+?)\s*$", raw)
+ if m_d:
+ if pending_dir:
+ cur["directors"].append(pending_dir)
+ pending_dir = {"kind": m_d.group(1), "name": m_d.group(2).strip(), "owns": ""}
+ continue
+ m_o = re.match(r"^\s{8}owns:\s*\[?(.*?)\]?\s*$", raw)
+ if m_o and pending_dir is not None:
+ pending_dir["owns"] = m_o.group(1).strip()
+ continue
+ # any other key at vp-field indent ends the current section
+ if re.match(r"^\s{4}\w", raw):
+ if pending_dir:
+ cur["directors"].append(pending_dir)
+ pending_dir = None
+ section = None
+
+ if cur:
+ if pending_dir:
+ cur["directors"].append(pending_dir)
+ vps.append(cur)
+ return vps
+
+
+def build_card(vp: dict) -> AgentCard:
+ trig = " · ".join(vp["triggers"][:4])
+ desc = vp["domain"] or vp["vp"]
+ if trig:
+ desc = f"{desc} (triggers: {trig})"
+ skills = []
+ for d in vp["directors"]:
+ owns = d["owns"] or d["name"]
+ skills.append(
+ AgentSkill(
+ id=slug(d["name"]),
+ name=d["name"],
+ description=owns[:300],
+ tags=[d["kind"], "cabinet"],
+ )
+ )
+ return AgentCard(
+ name=vp["vp"],
+ description=desc[:500],
+ version="0.1.0",
+ supported_interfaces=[
+ AgentInterface(
+ url=f"{BASE}/{vp['vp']}/",
+ protocol_binding="JSONRPC",
+ protocol_version="1.0",
+ )
+ ],
+ capabilities=AgentCapabilities(streaming=False, push_notifications=False),
+ default_input_modes=["text/plain"],
+ default_output_modes=["text/plain"],
+ skills=skills,
+ )
+
+
+def main() -> int:
+ vps = parse_cabinet(CABINET.read_text(encoding="utf-8"))
+ OUT.mkdir(exist_ok=True)
+ total_skills = 0
+ for vp in vps:
+ card = build_card(vp)
+ total_skills += len(card.skills)
+ path = OUT / f"{vp['vp']}.agent-card.json"
+ path.write_text(
+ json.dumps(MessageToDict(card, preserving_proto_field_name=False), indent=2),
+ encoding="utf-8",
+ )
+ print(f" {vp['vp']:24} {len(card.skills):2} skills → {path.name}")
+ print(f"\nGenerated {len(vps)} cabinet agent cards / {total_skills} skills → {OUT}/")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/cards/vp-abramsego.agent-card.json b/cards/vp-abramsego.agent-card.json
new file mode 100644
index 0000000..bd62af7
--- /dev/null
+++ b/cards/vp-abramsego.agent-card.json
@@ -0,0 +1,78 @@
+{
+ "name": "vp-abramsego",
+ "description": "The AbramsEgo command-center product (~/Projects/AbramsEgo, pm2 :9773) \u2014 build, operations, the autonomous build-loop, and MONETIZATION (sell/SaaS, affiliate, billable reports, ads). Everything money-facing is draft-to-approval only. (triggers: abramsego | abrams ego | the command center | ego dashboard | :9773 \u00b7 sell abramsego | abramsego revenue | self-funding | revenue engines \u00b7 abramsego loop | ego build queue | ego build \u00b7 abramsego go-live | abramsego stripe | abramsego waitlist)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-abramsego/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "abramsego-agent",
+ "name": "abramsego-agent",
+ "description": "AbramsEgo build/operate steward \u2014 server.js, panels, snapshot collectors, build-queue loop, revenue plumbing, landing page. Local-only; deploy/publish gated.",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "web-extract",
+ "name": "web-extract",
+ "description": "cross-officer \u2014 Hermes search-then-extract agent research over Exa + free local summarizer",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "ollama-model-eval",
+ "name": "ollama-model-eval",
+ "description": "cross-officer \u2014 benchmark a candidate local model (e.g. ornith:9b) on real tasks before it earns a fleet slot",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "design-trend-scout",
+ "name": "design-trend-scout",
+ "description": "standing market-research strategist \u2014 scouts top-sellers on Spoonflower/Etsy/Society6/Redbubble/Creative Market/Patternbank, gap-checks our WPB catalog, briefs ORIGINAL settlement-safe designs to run in the selling lanes \u2192 feeds the Pattern Vault licensing engine. Research read-only/metered; generat",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "abramsego-design-research",
+ "name": "abramsego-design-research",
+ "description": "design north-star research \u2014 @androoagi TikTok/X, dropped links (Nous Hermes, 0xRaduan/DeepWiki), Norma panel-tour videos on :9891; maintains references/design-notes.md",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "abramsego-golive",
+ "name": "abramsego-golive",
+ "description": "revenue-engine ops \u2014 Stripe TEST flows, waitlist digest, engine gated\u2192live flip checklist, go-live approval memos",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-cncp.agent-card.json b/cards/vp-cncp.agent-card.json
new file mode 100644
index 0000000..c97ebf2
--- /dev/null
+++ b/cards/vp-cncp.agent-card.json
@@ -0,0 +1,51 @@
+{
+ "name": "vp-cncp",
+ "description": ">- (triggers: cncp officer | drive cncp | run the operation | status of everything \u00b7 keep projects moving | keep everything flowing | nothing should stall \u00b7 clear the approvals | clear the queue | clear tasks | advance the tasks \u00b7 unstick the pipeline | who's stalled | what's blocked | who's idle)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-cncp/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "coordinating-agents",
+ "name": "coordinating-agents",
+ "description": "officer morning standup \u2014 who-helps-whom cross-help round; propose-only",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "officers-overnight",
+ "name": "officers-overnight",
+ "description": "end-of-shift officer synthesis + overnight project queue; propose-only",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "officer-idea-council",
+ "name": "officer-idea-council",
+ "description": "7-officer idea brainstorm \u2192 Top-5; the daily idea generator this officer composes with",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-compliance-policy.agent-card.json b/cards/vp-compliance-policy.agent-card.json
new file mode 100644
index 0000000..ed164fb
--- /dev/null
+++ b/cards/vp-compliance-policy.agent-card.json
@@ -0,0 +1,69 @@
+{
+ "name": "vp-compliance-policy",
+ "description": "Outbound comms compliance, best-practices pre-flight, legal posture (triggers: is this CAN-SPAM | tcpa | ccpa | dnc \u00b7 audit my mailer | compliance check \u00b7 best practices | pre-flight | violation \u00b7 california bar | \u00a76155 | rule 7)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-compliance-policy/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "security-auditor",
+ "name": "security-auditor",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-engineering)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-legal-compliance",
+ "name": "dw-legal-compliance",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-dw-commerce)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "comms-compliance",
+ "name": "comms-compliance",
+ "description": "comms-compliance",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "best-practices-reviewer",
+ "name": "best-practices-reviewer",
+ "description": "best-practices-reviewer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "best-practices-best-practices-alias",
+ "name": "best-practices # /best-practices alias",
+ "description": "best-practices # /best-practices alias",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-consulting.agent-card.json b/cards/vp-consulting.agent-card.json
new file mode 100644
index 0000000..8f7fe8a
--- /dev/null
+++ b/cards/vp-consulting.agent-card.json
@@ -0,0 +1,78 @@
+{
+ "name": "vp-consulting",
+ "description": ">- (triggers: consulting | officer consulting | consulting client | client portal \u00b7 onboard a consulting client | build a website and social for | intake questionnaire \u00b7 new consulting client | spin up a client portal | concept versions | growth command center)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-consulting/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "consulting-agent",
+ "name": "consulting-agent",
+ "description": "Consulting build/operate steward \u2014 runs the intake \u2192 scaffold.mjs \u2192 concept generation \u2192 verify \u2192 commit loop for each ~/Projects/consulting-<slug>/ portal; wires the integrated-social buckets via existing fleet skills. Local-only; deploy/DNS/social-post gated.",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "consulting",
+ "name": "consulting",
+ "description": "the engine \u2014 intake schema, scaffold.mjs (portal generator), templates, build.mjs concept skinner, the fused fantasea + prestige patterns",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "advertising-signals",
+ "name": "advertising-signals",
+ "description": "cross-officer \u2014 competitor ad-platform + social-profile intel to fill the command center's competitors/ads buckets",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "reels-producer",
+ "name": "reels-producer",
+ "description": "cross-officer \u2014 client social reels \u2192 the portal's media bucket (DRAFT)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "analytics",
+ "name": "analytics",
+ "description": "cross-officer \u2014 GA4 setup + traffic reporting for a client site",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "domain-setup",
+ "name": "domain-setup",
+ "description": "cross-officer \u2014 Kamatera + Cloudflare + SSL go-live for a client portal (Steve-gated)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-directories.agent-card.json b/cards/vp-directories.agent-card.json
new file mode 100644
index 0000000..50d9d6b
--- /dev/null
+++ b/cards/vp-directories.agent-card.json
@@ -0,0 +1,69 @@
+{
+ "name": "vp-directories",
+ "description": "Vertical directory businesses (lawyer, doctor, NPH, animals, lacountyeats, ventura) (triggers: lawyer | calbar | bar directory \u00b7 doctor | physician | professional-directory \u00b7 animals | pets | dogs | bowie | madison | humphrey \u00b7 paper hanger | wallcovering installer | NPH)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-directories/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "lawyer-build-agent",
+ "name": "lawyer-build-agent",
+ "description": "lawyer-build-agent",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "doctor-agent",
+ "name": "doctor-agent",
+ "description": "doctor-agent",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "ad-social-tracker",
+ "name": "ad-social-tracker",
+ "description": "paid-ad detection across directories",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "advertising-signals",
+ "name": "advertising-signals",
+ "description": "single-domain ad scan",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "la-research-agent",
+ "name": "la-research-agent",
+ "description": "LA public records \u2014 doubles as research and lawyer enrichment",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-dw-commerce.agent-card.json b/cards/vp-dw-commerce.agent-card.json
new file mode 100644
index 0000000..0032139
--- /dev/null
+++ b/cards/vp-dw-commerce.agent-card.json
@@ -0,0 +1,222 @@
+{
+ "name": "vp-dw-commerce",
+ "description": "Designer Wallcoverings catalog, vendor scrapers, Shopify, storefronts, marketing (triggers: shopify | dw_unified | metafield | sku | variant | catalog \u00b7 vendor | scrape | crawl | enrich \u00b7 storefront | dw site | philipperomano | flockedwallpaper | grasscloth \u00b7 marketing | seo | mailer | drops | instagram | tiktok)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-dw-commerce/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "pairs-well-with",
+ "name": "pairs-well-with",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-dw-marketing)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "new-arrivals-rotator",
+ "name": "new-arrivals-rotator",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-dw-marketing)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "collection-creator",
+ "name": "collection-creator",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-dw-marketing)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "aichat",
+ "name": "aichat",
+ "description": "Big Red \u2014 customer-facing AI chat on every DW microsite; lower-left woman avatar; retail/wholesale/admin personas; vendor-redacted in retail; pm2 process \"aichat\" :9935 in ~/Projects/big-red; embed widget at chat.designerwallcoverings.com/widget.js",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "front-page-steward",
+ "name": "front-page-steward",
+ "description": "single owner of customer-facing front-page correctness across 53 DW sister sites + standalone front-faces (novasuede, philipperomano, architecturalwallcoverings, wallco.ai, thesetdecorator, ventura-corridor, butlr, starsofdesign); enforces standing structural rules (logo UL, hamburger UR Gucci, hero",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-site-build",
+ "name": "dw-site-build",
+ "description": "universal DW storefront playbook",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "internal-line-viewer",
+ "name": "internal-line-viewer",
+ "description": "standing spec for INTERNAL basic-auth line viewers \u2014 left-panel collapsed field tables, card-field toggles to image-only, density-scaled type; reference astek-landing :9944; private-label /curate rail",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-shopify-theme-optimizer",
+ "name": "dw-shopify-theme-optimizer",
+ "description": "Liquid perf, image opts, Core Web Vitals",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-marketing-copy",
+ "name": "dw-marketing-copy",
+ "description": "titles, body, SEO, descriptions",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-seo-optimizer",
+ "name": "dw-seo-optimizer",
+ "description": "meta + structured data",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-purchasing-vendor",
+ "name": "dw-purchasing-vendor",
+ "description": "vendor emails, POs, supplier pricing",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-sku-analyst",
+ "name": "dw-sku-analyst",
+ "description": "SKU normalization, dedup audits \u2014 like NCW + PR",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-legal-compliance",
+ "name": "dw-legal-compliance",
+ "description": "vendor contracts, settlement compliance",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "commercial-quote",
+ "name": "commercial-quote",
+ "description": "B2B quote requests for design professionals on premium lines (Koroseal); role-gated button + modal form + email handler",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "room-setting-generator",
+ "name": "room-setting-generator",
+ "description": "photorealistic room renders",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "commercial-room-setting-generator",
+ "name": "commercial-room-setting-generator",
+ "description": "contract / hospitality renders",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "shopify-vendor-bulk-updater",
+ "name": "shopify-vendor-bulk-updater",
+ "description": "bulk title/SKU/spec rewrites with progress UI",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "weekend-csv-products",
+ "name": "weekend-csv-products",
+ "description": "Sat\u2013Mon ordered-SKU CSV export",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "tiktok",
+ "name": "tiktok",
+ "description": "TikTok Shop sync + posting",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "instagram-post-template",
+ "name": "instagram-post-template",
+ "description": "IG post template",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "instagram-account-manager",
+ "name": "instagram-account-manager",
+ "description": "Norma single-account control",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "instagram-post-scheduler",
+ "name": "instagram-post-scheduler",
+ "description": "trigger post via Norma",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-dw-marketing.agent-card.json b/cards/vp-dw-marketing.agent-card.json
new file mode 100644
index 0000000..15912cc
--- /dev/null
+++ b/cards/vp-dw-marketing.agent-card.json
@@ -0,0 +1,312 @@
+{
+ "name": "vp-dw-marketing",
+ "description": "DW Marketing Command Center (Designer Wallcoverings BRAND ONLY) \u2014 copy, SEO, social (all platforms), video, creative, advertising intel, GA4 analytics, merchandising, landings, GTM. NOT Wallpaper's Back (\u2192 wallpapersback-marketing under vp-special-projects) or any non-DW brand. Social triggers below apply to DW's own accounts; a request naming a WPB handle routes to wallpapersback-marketing. (triggers: marketing | campaign | brand | awareness | demand gen | command center \u00b7 social | instagram |",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-dw-marketing/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "dw-instagram",
+ "name": "dw-instagram",
+ "description": "DW Instagram \u2014 feed/reels/stories via Norma instagram-agent :9810 (Meta Graph)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-tiktok",
+ "name": "dw-tiktok",
+ "description": "DW TikTok \u2014 short-form video + TikTok Shop sync",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-linkedin",
+ "name": "dw-linkedin",
+ "description": "DW + Abrams LinkedIn \u2014 B2B/trade posts + outreach drafts (MANUAL+TOOLING, no TOS automation)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-facebook",
+ "name": "dw-facebook",
+ "description": "DW Facebook/Meta Page + Shop + Meta ads planning (shares Meta Graph w/ IG)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-pinterest",
+ "name": "dw-pinterest",
+ "description": "DW Pinterest \u2014 boards/rich-pins/idea-pins (top interiors discovery channel; API not yet wired)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-youtube",
+ "name": "dw-youtube",
+ "description": "DW YouTube \u2014 Shorts + room walkthroughs + how-to + video SEO (API not yet wired)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-x-twitter",
+ "name": "dw-x-twitter",
+ "description": "DW on X/Twitter \u2014 posts/threads/launches (API not yet wired)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-marketing-copy",
+ "name": "dw-marketing-copy",
+ "description": "campaign copy, product descriptions, SEO titles, mailer/ad body",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-seo-optimizer",
+ "name": "dw-seo-optimizer",
+ "description": "meta + structured data",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "seo-analyzer",
+ "name": "seo-analyzer",
+ "description": "technical SEO audits",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "reels-producer",
+ "name": "reels-producer",
+ "description": "social reels/GIFs from product images",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "reviewed-demo-video",
+ "name": "reviewed-demo-video",
+ "description": "reviewed-demo-video",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "app-demo-video",
+ "name": "app-demo-video",
+ "description": "app-demo-video",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "what-landed-video",
+ "name": "what-landed-video",
+ "description": "what-landed-video",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "session-debrief",
+ "name": "session-debrief",
+ "description": "session-debrief",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "video-gallery",
+ "name": "video-gallery",
+ "description": "browse produced videos :9763",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "room-setting-generator",
+ "name": "room-setting-generator",
+ "description": "residential room renders for posts/pins",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "commercial-room-setting-generator",
+ "name": "commercial-room-setting-generator",
+ "description": "contract/hospitality renders",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "canvas-design",
+ "name": "canvas-design",
+ "description": "posters, print, social graphics",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "four-horsemen",
+ "name": "four-horsemen",
+ "description": "Figma/Magic/Paper/Canva design orchestration",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "four-horsemen-ui-orchestrator",
+ "name": "four-horsemen-ui-orchestrator",
+ "description": "four-horsemen-ui-orchestrator",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "stampede",
+ "name": "stampede",
+ "description": "3 wild elevated-graphic variants",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "logo-agent",
+ "name": "logo-agent",
+ "description": "tournament logo/brand-mark picker",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "ad-social-tracker",
+ "name": "ad-social-tracker",
+ "description": "paid-ad detection across a directory",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "advertising-signals",
+ "name": "advertising-signals",
+ "description": "single-domain \"where does X advertise\" scan",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "analytics-agent",
+ "name": "analytics-agent",
+ "description": "GA4 \u2014 properties, events, gtag injection, traffic reports (shared w/ vp-operations)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "collection-creator",
+ "name": "collection-creator",
+ "description": "AI curated-collection idea generator",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "new-arrivals-rotator",
+ "name": "new-arrivals-rotator",
+ "description": "auto-rotating New Arrivals / Trending Shopify collections",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "pairs-well-with",
+ "name": "pairs-well-with",
+ "description": "per-SKU \"pairs well with\" recommendations",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-vendor-landing",
+ "name": "dw-vendor-landing",
+ "description": "<vendor>.designerwallcoverings.com editorial lookbook",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-promo-banner",
+ "name": "dw-promo-banner",
+ "description": "text-first new-products promo banner across the DW sister-site/microsite network (reads each site data/products.json, no DB plumbing); LIVE deploy Steve-gated",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "product-strategist",
+ "name": "product-strategist",
+ "description": "positioning, GTM, roadmap (shared w/ vp-research-content)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-engineering.agent-card.json b/cards/vp-engineering.agent-card.json
new file mode 100644
index 0000000..78d52f8
--- /dev/null
+++ b/cards/vp-engineering.agent-card.json
@@ -0,0 +1,276 @@
+{
+ "name": "vp-engineering",
+ "description": "Backend, frontend, databases, code review, security, performance, testing (triggers: backend | api | rest | graphql | microservice \u00b7 frontend | react | typescript | tailwind \u00b7 database | sql | postgres | schema | migration | n+1 \u00b7 code review | refactor | pattern | architecture)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-engineering/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "backend-architect",
+ "name": "backend-architect",
+ "description": "backend-architect",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "frontend-developer",
+ "name": "frontend-developer",
+ "description": "frontend-developer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "fullstack-developer",
+ "name": "fullstack-developer",
+ "description": "fullstack-developer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "database-architect",
+ "name": "database-architect",
+ "description": "database-architect",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "database-optimizer",
+ "name": "database-optimizer",
+ "description": "database-optimizer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "api-documenter",
+ "name": "api-documenter",
+ "description": "api-documenter",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "code-reviewer",
+ "name": "code-reviewer",
+ "description": "code-reviewer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "architect-review-was-architect-reviewer-",
+ "name": "architect-review # was \"architect-reviewer\" \u2014 actual file name is architect-review.md",
+ "description": "architect-review # was \"architect-reviewer\" \u2014 actual file name is architect-review.md",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "security-auditor",
+ "name": "security-auditor",
+ "description": "security-auditor",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "performance-engineer",
+ "name": "performance-engineer",
+ "description": "performance-engineer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "test-engineer",
+ "name": "test-engineer",
+ "description": "test-engineer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "error-detective",
+ "name": "error-detective",
+ "description": "error-detective",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "debugger",
+ "name": "debugger",
+ "description": "debugger",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "javascript-pro",
+ "name": "javascript-pro",
+ "description": "javascript-pro",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "typescript-pro",
+ "name": "typescript-pro",
+ "description": "typescript-pro",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "python-pro",
+ "name": "python-pro",
+ "description": "python-pro",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "ios-developer",
+ "name": "ios-developer",
+ "description": "ios-developer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "mobile-developer",
+ "name": "mobile-developer",
+ "description": "mobile-developer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "ai-engineer-llm-apps-rag-prompt-pipeline",
+ "name": "ai-engineer # LLM apps, RAG, prompt pipelines",
+ "description": "ai-engineer # LLM apps, RAG, prompt pipelines",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "prompt-engineer-prompt-optimization",
+ "name": "prompt-engineer # prompt optimization",
+ "description": "prompt-engineer # prompt optimization",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "mcp-expert-mcp-server-integration",
+ "name": "mcp-expert # MCP server integration",
+ "description": "mcp-expert # MCP server integration",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "dw-agent-builder",
+ "name": "dw-agent-builder",
+ "description": "scaffold new DW-domain subagents + skills from a spec \u2014 generate the .md with name/description/triggers and register it in the cabinet",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "prompt-cache-optimization",
+ "name": "prompt-cache-optimization",
+ "description": "prompt-cache-optimization",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "claude-api-anthropic-sdk-migrations-prom",
+ "name": "claude-api # Anthropic SDK migrations + prompt caching",
+ "description": "Anthropic Claude API helper \u2014 SDK migrations, current model IDs, tool-use, streaming, and prompt-caching best practices",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "simplify-code-reuse-quality-review",
+ "name": "simplify # Code reuse/quality review",
+ "description": "refactor for simplicity + reuse \u2014 collapse needless abstraction, remove dead code, cut complexity without changing behavior",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "review-code-review",
+ "name": "review # Code review",
+ "description": "standard code-review pass \u2014 flags quality, security, and maintainability issues on changed files before commit",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "refactor-agent",
+ "name": "refactor-agent",
+ "description": "refactor-agent",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "mcp-builder",
+ "name": "mcp-builder",
+ "description": "mcp-builder",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-operations.agent-card.json b/cards/vp-operations.agent-card.json
new file mode 100644
index 0000000..04b8fcb
--- /dev/null
+++ b/cards/vp-operations.agent-card.json
@@ -0,0 +1,150 @@
+{
+ "name": "vp-operations",
+ "description": "Infrastructure, monitoring, secrets, domains, DNS, watchdogs (triggers: infra | infrastructure | devops | server | uptime | crashed \u00b7 watchdog | pm2 | launchd | cron | scheduler \u00b7 secret | token | api key | rotate \u00b7 domain | dns | ssl | mx | spf | dkim | dmarc | cloudflare | godaddy)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-operations/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "dw-yolo-loop",
+ "name": "dw-yolo-loop",
+ "description": "autonomous hourly DW catalog-health hunt \u2014 DTD decides each cycle, officer signs off, reversible fixes apply / hard-gated queue for Steve, self-reschedules; consolidates the uptime watch",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "secrets",
+ "name": "secrets",
+ "description": "add token, rotate token, audit secrets, fan out env",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "domain-setup",
+ "name": "domain-setup",
+ "description": "register, configure DNS, SSL, email auth",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "domain-name-agent",
+ "name": "domain-name-agent",
+ "description": "domain inventory, NS swap, WHOIS] # was misclassified as skill",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "cloudflare-manager",
+ "name": "cloudflare-manager",
+ "description": "zone DNS, proxy toggle",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "open-firewalls",
+ "name": "open-firewalls",
+ "description": "Mac2 + Kamatera firewall",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "process-hawk",
+ "name": "process-hawk",
+ "description": "auto-restart stuck pm2 processes",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "fleet-lifecycle-steward",
+ "name": "fleet-lifecycle-steward",
+ "description": "single owner of \"no DW agent sleeps silently, stale ones retire only with Steve's sign-off\"; reconciles the LIVE fleet (pm2 Mac2+Kamatera, launchd, cabinet roster, skills) against the centralized service-registry contract (expected_up, health_url, machine, owner, lifecycle_status \u2014 DTD verdict A 202",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "pm2-crash-watcher",
+ "name": "pm2-crash-watcher",
+ "description": "pm2-crash-watcher",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "deployment-engineer",
+ "name": "deployment-engineer",
+ "description": "deployment-engineer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "devops-engineer",
+ "name": "devops-engineer",
+ "description": "devops-engineer",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "onboard-domain-agent",
+ "name": "onboard-domain-agent",
+ "description": "onboard-domain-agent",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "secrets-manager",
+ "name": "secrets-manager",
+ "description": "secrets-manager",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "analytics-agent-ga4-fleet-also-relevant-",
+ "name": "analytics-agent # GA4 fleet, also relevant to vp-research-content",
+ "description": "analytics-agent # GA4 fleet, also relevant to vp-research-content",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-research-content.agent-card.json b/cards/vp-research-content.agent-card.json
new file mode 100644
index 0000000..e32f846
--- /dev/null
+++ b/cards/vp-research-content.agent-card.json
@@ -0,0 +1,348 @@
+{
+ "name": "vp-research-content",
+ "description": "Web research, LA records, video production, mockups, design, voice (triggers: research | exa | search the web | competitor analysis \u00b7 mockup | concept | variant | front page \u00b7 peer survey | competitors | site audit | website analysis \u00b7 video | demo | walkthrough | reel | session debrief | avatar)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-research-content/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "analytics-agent",
+ "name": "analytics-agent",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-operations)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "la-research-agent",
+ "name": "la-research-agent",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-directories)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "exa-agent",
+ "name": "exa-agent",
+ "description": "exa-agent",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "search-specialist",
+ "name": "search-specialist",
+ "description": "search-specialist",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "technical-researcher",
+ "name": "technical-researcher",
+ "description": "technical-researcher",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "data-analyst",
+ "name": "data-analyst",
+ "description": "data-analyst",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "data-scientist",
+ "name": "data-scientist",
+ "description": "data-scientist",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "website-analysis",
+ "name": "website-analysis",
+ "description": "website-analysis",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "seo-analyzer-technical-seo-audits",
+ "name": "seo-analyzer # technical SEO audits",
+ "description": "seo-analyzer # technical SEO audits",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "ui-ux-designer-design-systems-wireframes",
+ "name": "ui-ux-designer # design systems, wireframes, a11y",
+ "description": "ui-ux-designer # design systems, wireframes, a11y",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "graphic-designer-stage-2-advisory-typogr",
+ "name": "graphic-designer # Stage-2 advisory typography/wordmark/layout review",
+ "description": "graphic-designer # Stage-2 advisory typography/wordmark/layout review",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "product-strategist-roadmap-positioning-g",
+ "name": "product-strategist # roadmap, positioning, GTM",
+ "description": "product-strategist # roadmap, positioning, GTM",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "debate-team-fast-4-llm-consensus-engine",
+ "name": "debate-team-fast # 4-LLM consensus engine",
+ "description": "debate-team-fast # 4-LLM consensus engine",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "task-decomposition-expert-complex-goal-b",
+ "name": "task-decomposition-expert # complex goal breakdown",
+ "description": "task-decomposition-expert # complex goal breakdown",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "site-audit",
+ "name": "site-audit",
+ "description": "site-audit",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "peer-survey",
+ "name": "peer-survey",
+ "description": "peer-survey",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "competitors",
+ "name": "competitors",
+ "description": "competitors",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "mockups",
+ "name": "mockups",
+ "description": "mockups",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "tools-pack",
+ "name": "tools-pack",
+ "description": "tools-pack",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "info-hub",
+ "name": "info-hub",
+ "description": "info-hub",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "extension",
+ "name": "extension",
+ "description": "extension",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "reviewed-demo-video",
+ "name": "reviewed-demo-video",
+ "description": "reviewed-demo-video",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "app-demo-video",
+ "name": "app-demo-video",
+ "description": "app-demo-video",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "session-debrief",
+ "name": "session-debrief",
+ "description": "session-debrief",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "video-gallery",
+ "name": "video-gallery",
+ "description": "video-gallery",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "clone-voice",
+ "name": "clone-voice",
+ "description": "clone-voice",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "use-voice",
+ "name": "use-voice",
+ "description": "use-voice",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "reels-producer",
+ "name": "reels-producer",
+ "description": "reels-producer",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "four-horsemen",
+ "name": "four-horsemen",
+ "description": "four-horsemen",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "four-horsemen-ui-orchestrator",
+ "name": "four-horsemen-ui-orchestrator",
+ "description": "four-horsemen-ui-orchestrator",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "stampede",
+ "name": "stampede",
+ "description": "stampede",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "canvas-design",
+ "name": "canvas-design",
+ "description": "canvas-design",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "artifacts-builder",
+ "name": "artifacts-builder",
+ "description": "artifacts-builder",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "prism-show-prism-router-status-available",
+ "name": "prism # Show Prism router status, available models, endpoint map (plugin)",
+ "description": "show Prism LLM-router status \u2014 available models, endpoint map, and routing health (plugin/MCP-loaded, no on-disk SKILL.md)",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "gamify-sound-effects-on-claude-code-even",
+ "name": "gamify # Sound effects on Claude Code events",
+ "description": "gamify # Sound effects on Claude Code events",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "claude-control-center-new-9767-gamify-cr",
+ "name": "claude-control-center # NEW :9767 \u2014 gamify + cross-terminal session viewer",
+ "description": "claude-control-center # NEW :9767 \u2014 gamify + cross-terminal session viewer",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-security.agent-card.json b/cards/vp-security.agent-card.json
new file mode 100644
index 0000000..001d7ba
--- /dev/null
+++ b/cards/vp-security.agent-card.json
@@ -0,0 +1,69 @@
+{
+ "name": "vp-security",
+ "description": "Incident response, secret/API-key rotation, breach triage, firewall hardening, CVE audits, security-monitoring fleet (triggers: are we secure | did we get hacked | breach | intrusion | backdoor \u00b7 rotate keys | leaked secret | scan for secrets | credential exposure \u00b7 firewall | open port | harden | cve | dependency audit \u00b7 security dashboard | monitor drift | security-monitor)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-security/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "security-auditor",
+ "name": "security-auditor",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-engineering)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "secrets-manager",
+ "name": "secrets-manager",
+ "description": "cross-officer \u2014 approved via pyramid (primary: vp-operations)",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "security-dashboard",
+ "name": "security-dashboard",
+ "description": "security-monitoring fleet \u2014 :9889 + Kamatera security-monitor.sh",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "secrets",
+ "name": "secrets",
+ "description": "cross-officer \u2014 token registry / rotation / fan-out",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "open-firewalls",
+ "name": "open-firewalls",
+ "description": "cross-officer \u2014 Mac2 + Kamatera firewall audit",
+ "tags": [
+ "skill",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/cards/vp-special-projects.agent-card.json b/cards/vp-special-projects.agent-card.json
new file mode 100644
index 0000000..a2b20b7
--- /dev/null
+++ b/cards/vp-special-projects.agent-card.json
@@ -0,0 +1,60 @@
+{
+ "name": "vp-special-projects",
+ "description": "Non-DW side / product-builder projects \u2014 wallco.ai catalog (now wallpapersback.com retail), apartmentwallpaper.com, site-factory, small-business-builder, Abrams portfolio (triggers: wallpapersback agent | wallco agent (legacy alias) | wallpapersback | apartment wallpaper | peel and stick \u00b7 wallpapersback marketing | WPB social | @wallpapersback | @wallpaperisback | @WallpaperBack \u00b7 site-factory | small business builder | sdcc | side projects \u00b7 agentabrams | 4square)",
+ "supportedInterfaces": [
+ {
+ "url": "http://127.0.0.1:41300/vp-special-projects/",
+ "protocolBinding": "JSONRPC",
+ "protocolVersion": "1.0"
+ }
+ ],
+ "version": "0.1.0",
+ "capabilities": {
+ "streaming": false,
+ "pushNotifications": false
+ },
+ "defaultInputModes": [
+ "text/plain"
+ ],
+ "defaultOutputModes": [
+ "text/plain"
+ ],
+ "skills": [
+ {
+ "id": "wallpapersback-agent",
+ "name": "wallpapersback-agent",
+ "description": "Wallpaper's Back (wallpapersback.com) catalog end-to-end \u2014 gen, settlement gate, curators, rooms, deploy. Renamed from wallco-agent 2026-06-23 (wallco.ai retired).",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "wallpapersback-marketing",
+ "name": "wallpapersback-marketing",
+ "description": "Wallpaper's Back (wallpapersback.com) marketing ONLY \u2014 social (@wallpapersback / @wallpaperisback / @WallpaperBack), captions/copy, reels, brand kit, :9847 viewer. NOT the catalog (wallpapersback-agent), NOT Designer Wallcoverings (vp-dw-marketing). Split out of the dw-* social agents 2026-06-23 so ",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "apartment-wallpaper-agent",
+ "name": "apartment-wallpaper-agent",
+ "description": "apartmentwallpaper.com \u2014 peel-and-stick storefront",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ },
+ {
+ "id": "seam-debug-agent",
+ "name": "seam-debug-agent",
+ "description": "wallpapersback.com seam/joint scan + heal",
+ "tags": [
+ "subagent",
+ "cabinet"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index e9a6bbd..827a1a1 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -22,6 +22,7 @@ pyasn1_modules==0.4.2
pycparser==3.0
pydantic==2.13.4
pydantic_core==2.46.4
+PyYAML==6.0.3
requests==2.34.2
sse-starlette==3.4.6
starlette==1.3.1
← b4cdc89 TK Bridge: add gated dm-write skill (TK_BRIDGE_ALLOW_WRITE),
·
back to A2a Lab
·
A2A cabinet directory server (list/find/card) + fix block-sc d13a06a →