{
  "schemaVersion": "1.0",
  "item": {
    "slug": "miro-workshop-assistant",
    "name": "Miro board",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/SimoneFerrario/miro-workshop-assistant",
    "canonicalUrl": "https://clawhub.ai/SimoneFerrario/miro-workshop-assistant",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/miro-workshop-assistant",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=miro-workshop-assistant",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "miro-push.mjs",
      "miro-ready.json",
      "README.txt",
      "SKILL.md",
      "_out/.state.json"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/miro-workshop-assistant"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/miro-workshop-assistant",
    "agentPageUrl": "https://openagent3.xyz/skills/miro-workshop-assistant/agent",
    "manifestUrl": "https://openagent3.xyz/skills/miro-workshop-assistant/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/miro-workshop-assistant/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Goal",
        "body": "Produce a workshop output on Miro that is:\n\nreadable as a diagram (not “scattered post-its”)\neasy to edit (real containers)\nidempotent (no duplicates)\ncorrectable (undo / delete / update)"
      },
      {
        "title": "Security (mandatory)",
        "body": "Never print MIRO_ACCESS_TOKEN\nUse only env vars: MIRO_ACCESS_TOKEN and MIRO_BOARD_ID\nNever use browser cookies/session tokens"
      },
      {
        "title": "Key rule: a container = a FRAME (not a shape)",
        "body": "A “workshop container” must be a FRAME when:\n\nthere is a large rectangle/square with a clear title (e.g., “Easy vision”, “Milestone”, “VMS”, “Data Hub”, “Vico Insider”)\nor there is a swimlane/column with a title\nor a box is clearly grouping multiple elements (stickies or sub-boxes)\n\nDo NOT create a frame if:\n\nit’s just blank space without a title\nit’s only a decorative border without grouping meaning"
      },
      {
        "title": "HARD REQUIREMENT (do not violate)",
        "body": "You MUST create frames[] when the board contains categories/areas.\nYou MUST assign a non-null frameId to each sticky (except explicit \"outside notes\").\nIf frames[] is empty OR if >10% stickies have frameId=null:\n\nDO NOT run the push command.\nRegenerate the structure (max 2 attempts)."
      },
      {
        "title": "Quality Gate — Container sanity check (mandatory)",
        "body": "If the image contains >=2 titled containers:\n\nframes.length MUST be >= 2\nat least 95% of stickies MUST have a non-null frameId\nIf not satisfied:\nDO NOT push\nRegenerate structure (max 2 attempts)"
      },
      {
        "title": "Mandatory planning (do not print)",
        "body": "Before generating JSON and before running DIRECT PUSH:\n\nIdentify candidate FRAMES:\n\nany large rectangle with a title\nany area labeled on the side or centered above/below\n\n\nAssign every sticky to a candidate frame.\nIf a sticky is ambiguous, add a warning and assign it to the closest/most plausible frame.\nOnly after that, generate the final JSON."
      },
      {
        "title": "Quality Gate (mandatory)",
        "body": "Before executing node ... apply:\n\nAt least 1 frame must exist.\nAt least 90% of stickies must have a non-null frameId.\nNo frame should be “giant” if the image clearly contains multiple distinct areas.\nIf the gate fails, DO NOT push: regenerate the structure (max 2 attempts)."
      },
      {
        "title": "Dedup / Idempotency (mandatory)",
        "body": "Every push must include a STABLE meta.sessionKey for the same diagram/topic (e.g., \"easy-vision-workshop\").\nEvery push must include a unique meta.runId (timestamp).\nIf the sessionKey is the same:\n\nfirst remove the previous run (automatic undo)\nthen apply the new one\nThis prevents duplicates and repeated runs."
      },
      {
        "title": "A) DIRECT PUSH (default if the user asks)",
        "body": "Generate a Miro-ready JSON (schema below) including:\n\nmeta.sessionKey (stable)\nmeta.runId (unique)\n\n\nSave the JSON to:\n\n...\\workshop-miro\\_out\\miro-ready-YYYYMMDD-HHMMSS.json\n\n\nExecute:\n\nnode ...\\miro-push.mjs apply <PATH_JSON>\n\n\nReply with:\n\nframes created: N\nstickies created: N\nconnectors created: N\nsessionKey + runId\nwarnings (if any)"
      },
      {
        "title": "B) CORRECTIONS (when the user wants changes)",
        "body": "UNDO (per session): node ...\\miro-push.mjs undo <sessionKey>\nIf the user says “redo it better / wrong category / move things”:\n\nregenerate a corrected JSON with the same sessionKey\nrun APPLY again (it replaces the previous run)\n\nNote: fine-grained edits (delete/update a single sticky) are a next step if the script supports them.\nOtherwise, recommended: full regeneration with the same sessionKey (cleaner and usually faster)."
      },
      {
        "title": "Smart layout rules",
        "body": "Inside each frame:\n\nleft: inputs/sources\ncenter: processing / API / platforms\nright: outputs/UI/external integrations\n\n\nSpacing guideline: x += 420, y += 260\nIf there is a long arrow crossing the whole diagram:\n\nprefer 2 shorter connectors via an intermediate node (e.g., sticky “API” or “Integration”) if it improves readability"
      },
      {
        "title": "Connector / relationship rules",
        "body": "Create a connector when:\n\nyou see an arrow/line on the whiteboard\nor the text implies a flow: \"API\", \"sensoren\", \"data\", \"->\", \"integration\"\nconnector label: use the word that describes the flow (e.g., “API”, “Sensoren”, “Data”, “Milestone”)\n\nDefault connector shape: \"elbowed\" (more readable for architecture diagrams)."
      },
      {
        "title": "Anti-overlap rules (clean arrows)",
        "body": "Goal: avoid connectors crossing over stickies/notes.\n\nUse default connector shape = \"elbowed\".\nAlways keep a free “routing lane”:\n\nDo not place stickies close to frame borders.\nMinimum inner frame padding: 160px.\n\n\nIf a connector would be long or would cross a cluster:\n\ncreate one or more “router nodes” (gray sticky with \".\" or empty text) placed outside clusters\nsplit the connection into segments: A -> R1 -> R2 -> B\n\n\nFor connections between different frames:\n\nuse a router node near the right border of the source frame\nand a router node near the left border of the target frame"
      },
      {
        "title": "JSON Output (FRAME-based)",
        "body": "{\n\"meta\": {\n\"title\": \"string\",\n\"source\": \"photo|notes\",\n\"language\": \"it|de|en\",\n\"createdAt\": \"ISO-8601\",\n\"sessionKey\": \"string (stable)\",\n\"runId\": \"string (unique)\"\n},\n\"frames\": [\n{ \"id\": \"F1\", \"title\": \"string\", \"x\": 0, \"y\": 0, \"w\": 1400, \"h\": 900 }\n],\n\"stickies\": [\n{\n\"id\": \"S1\",\n\"frameId\": \"F1|null\",\n\"text\": \"string\",\n\"color\": \"light_yellow|light_blue|light_green|light_pink|gray\",\n\"x\": 0,\n\"y\": 0,\n\"unclear\": false\n}\n],\n\"connectors\": [\n{ \"from\": \"S1\", \"to\": \"S2\", \"label\": \"string|null\", \"shape\": \"straight|elbowed|curved\" }\n],\n\"warnings\": [ \"string\" ]\n}"
      },
      {
        "title": "HARD Containment Detection (mandatory)",
        "body": "A \"container\" is a large rectangle that encloses other notes and has a title (e.g. \"Product A\", \"Product B\").\n\nYou MUST do this:\n\nCreate one FRAME per container rectangle (title = the container title).\nAssign EVERY inner note to that frame via frameId.\nOnly outer notes (explicitly outside all containers) may have frameId=null.\n\nContainment must be interpreted literally:\n\nIf an element is visually inside the container boundaries, it belongs to that container.\nIf unsure, assign to the nearest container and add a warning."
      },
      {
        "title": "Quality checklist (before pushing)",
        "body": "sessionKey present and stable\nno giant “Workshop” frame unless the photo truly shows a single big box\nevery sticky belongs to the correct frame (category)\nno duplicate stickies with identical text inside the same frame\nconnectors only where they make sense (not between every pair)"
      }
    ],
    "body": "Workshop → Miro (Top Mode vNext)\nGoal\n\nProduce a workshop output on Miro that is:\n\nreadable as a diagram (not “scattered post-its”)\neasy to edit (real containers)\nidempotent (no duplicates)\ncorrectable (undo / delete / update)\nSecurity (mandatory)\nNever print MIRO_ACCESS_TOKEN\nUse only env vars: MIRO_ACCESS_TOKEN and MIRO_BOARD_ID\nNever use browser cookies/session tokens\nKey rule: a container = a FRAME (not a shape)\n\nA “workshop container” must be a FRAME when:\n\nthere is a large rectangle/square with a clear title (e.g., “Easy vision”, “Milestone”, “VMS”, “Data Hub”, “Vico Insider”)\nor there is a swimlane/column with a title\nor a box is clearly grouping multiple elements (stickies or sub-boxes)\n\nDo NOT create a frame if:\n\nit’s just blank space without a title\nit’s only a decorative border without grouping meaning\nHARD REQUIREMENT (do not violate)\nYou MUST create frames[] when the board contains categories/areas.\nYou MUST assign a non-null frameId to each sticky (except explicit \"outside notes\").\nIf frames[] is empty OR if >10% stickies have frameId=null:\nDO NOT run the push command.\nRegenerate the structure (max 2 attempts).\nQuality Gate — Container sanity check (mandatory)\n\nIf the image contains >=2 titled containers:\n\nframes.length MUST be >= 2\nat least 95% of stickies MUST have a non-null frameId If not satisfied:\nDO NOT push\nRegenerate structure (max 2 attempts)\nMandatory planning (do not print)\n\nBefore generating JSON and before running DIRECT PUSH:\n\nIdentify candidate FRAMES:\nany large rectangle with a title\nany area labeled on the side or centered above/below\nAssign every sticky to a candidate frame.\nIf a sticky is ambiguous, add a warning and assign it to the closest/most plausible frame.\nOnly after that, generate the final JSON.\nQuality Gate (mandatory)\n\nBefore executing node ... apply:\n\nAt least 1 frame must exist.\nAt least 90% of stickies must have a non-null frameId.\nNo frame should be “giant” if the image clearly contains multiple distinct areas.\nIf the gate fails, DO NOT push: regenerate the structure (max 2 attempts).\nDedup / Idempotency (mandatory)\nEvery push must include a STABLE meta.sessionKey for the same diagram/topic (e.g., \"easy-vision-workshop\").\nEvery push must include a unique meta.runId (timestamp).\nIf the sessionKey is the same:\nfirst remove the previous run (automatic undo)\nthen apply the new one This prevents duplicates and repeated runs.\nOperating modes\nA) DIRECT PUSH (default if the user asks)\nGenerate a Miro-ready JSON (schema below) including:\nmeta.sessionKey (stable)\nmeta.runId (unique)\nSave the JSON to:\n...\\workshop-miro\\_out\\miro-ready-YYYYMMDD-HHMMSS.json\nExecute:\nnode ...\\miro-push.mjs apply <PATH_JSON>\nReply with:\nframes created: N\nstickies created: N\nconnectors created: N\nsessionKey + runId\nwarnings (if any)\nB) CORRECTIONS (when the user wants changes)\nUNDO (per session): node ...\\miro-push.mjs undo <sessionKey>\nIf the user says “redo it better / wrong category / move things”:\nregenerate a corrected JSON with the same sessionKey\nrun APPLY again (it replaces the previous run)\n\nNote: fine-grained edits (delete/update a single sticky) are a next step if the script supports them. Otherwise, recommended: full regeneration with the same sessionKey (cleaner and usually faster).\n\nSmart layout rules\nInside each frame:\nleft: inputs/sources\ncenter: processing / API / platforms\nright: outputs/UI/external integrations\nSpacing guideline: x += 420, y += 260\nIf there is a long arrow crossing the whole diagram:\nprefer 2 shorter connectors via an intermediate node (e.g., sticky “API” or “Integration”) if it improves readability\nConnector / relationship rules\n\nCreate a connector when:\n\nyou see an arrow/line on the whiteboard\nor the text implies a flow: \"API\", \"sensoren\", \"data\", \"->\", \"integration\"\nconnector label: use the word that describes the flow (e.g., “API”, “Sensoren”, “Data”, “Milestone”)\n\nDefault connector shape: \"elbowed\" (more readable for architecture diagrams).\n\nAnti-overlap rules (clean arrows)\n\nGoal: avoid connectors crossing over stickies/notes.\n\nUse default connector shape = \"elbowed\".\nAlways keep a free “routing lane”:\nDo not place stickies close to frame borders.\nMinimum inner frame padding: 160px.\nIf a connector would be long or would cross a cluster:\ncreate one or more “router nodes” (gray sticky with \".\" or empty text) placed outside clusters\nsplit the connection into segments: A -> R1 -> R2 -> B\nFor connections between different frames:\nuse a router node near the right border of the source frame\nand a router node near the left border of the target frame\nJSON Output (FRAME-based)\n\n{ \"meta\": { \"title\": \"string\", \"source\": \"photo|notes\", \"language\": \"it|de|en\", \"createdAt\": \"ISO-8601\", \"sessionKey\": \"string (stable)\", \"runId\": \"string (unique)\" }, \"frames\": [ { \"id\": \"F1\", \"title\": \"string\", \"x\": 0, \"y\": 0, \"w\": 1400, \"h\": 900 } ], \"stickies\": [ { \"id\": \"S1\", \"frameId\": \"F1|null\", \"text\": \"string\", \"color\": \"light_yellow|light_blue|light_green|light_pink|gray\", \"x\": 0, \"y\": 0, \"unclear\": false } ], \"connectors\": [ { \"from\": \"S1\", \"to\": \"S2\", \"label\": \"string|null\", \"shape\": \"straight|elbowed|curved\" } ], \"warnings\": [ \"string\" ] }\n\nHARD Containment Detection (mandatory)\n\nA \"container\" is a large rectangle that encloses other notes and has a title (e.g. \"Product A\", \"Product B\").\n\nYou MUST do this:\n\nCreate one FRAME per container rectangle (title = the container title).\nAssign EVERY inner note to that frame via frameId.\nOnly outer notes (explicitly outside all containers) may have frameId=null.\n\nContainment must be interpreted literally:\n\nIf an element is visually inside the container boundaries, it belongs to that container.\nIf unsure, assign to the nearest container and add a warning.\nQuality checklist (before pushing)\nsessionKey present and stable\nno giant “Workshop” frame unless the photo truly shows a single big box\nevery sticky belongs to the correct frame (category)\nno duplicate stickies with identical text inside the same frame\nconnectors only where they make sense (not between every pair)"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/SimoneFerrario/miro-workshop-assistant",
    "publisherUrl": "https://clawhub.ai/SimoneFerrario/miro-workshop-assistant",
    "owner": "SimoneFerrario",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/miro-workshop-assistant",
    "downloadUrl": "https://openagent3.xyz/downloads/miro-workshop-assistant",
    "agentUrl": "https://openagent3.xyz/skills/miro-workshop-assistant/agent",
    "manifestUrl": "https://openagent3.xyz/skills/miro-workshop-assistant/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/miro-workshop-assistant/agent.md"
  }
}