From monday-com
Creates, reads, edits, and comments on monday.com docs - the rich-content surface inside monday for meeting notes, RFCs, runbooks, weekly updates, postmortems, and any work-adjacent writing. Goes beyond markdown shuffling by embedding live board column values inline (so the doc reflects real-time status), tagging users / docs / boards via mentions, scaffolding common doc shapes, and routing each edit through the correct update_doc operation. Use when user asks to "create a doc", "make a monday doc", "draft meeting notes", "write an RFC", "scaffold a runbook", "summarize a meeting in a doc", "add a section to my doc", "edit my doc", "update the doc", "comment on a doc", "tag someone in a doc", "embed a status in a doc", "show live board data in a doc", "rename a doc", or "show me my docs".
How this skill is triggered — by the user, by Claude, or both
Slash command
/monday-com:docs-collaboratorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Create, read, edit, and comment on monday.com docs. **The skill is a capability surface, not a template engine.** Every doc is a stream of typed blocks (headings, paragraphs, lists, tables, code, dividers, notice boxes, layouts, embedded boards / widgets / docs / images / videos / GIFs). The named shapes listed below are starting points - compose and extend freely. The differentiators (live col...
Create, read, edit, and comment on monday.com docs. The skill is a capability surface, not a template engine. Every doc is a stream of typed blocks (headings, paragraphs, lists, tables, code, dividers, notice boxes, layouts, embedded boards / widgets / docs / images / videos / GIFs). The named shapes listed below are starting points - compose and extend freely. The differentiators (live column-value embeds, inline mentions, notice boxes, layouts) apply to any shape, named or invented.
The platform-native value over a raw markdown editor lives in three things most builders miss: inline mentions of users / docs / boards, live column-value embeds that reflect the current state of a board item, and a closed-loop edit pattern that prevents corrupting the doc's block graph.
Never edit a block you have not read. monday's update_doc API is block-ID-based, and block IDs are only knowable through read_docs with include_blocks: true. Skipping the read leads to operations referencing IDs that do not exist (silent failure) or - worse - reusing an ID from another doc. The closed-loop pattern is non-negotiable:
read_docs with include_blocks: true to get block IDs, types, and positions.update_doc with the operation that matches the target block's type (see the routing rule below).Each block type has a different set of allowed mutations. Picking the wrong operation is the #1 cause of "the call succeeded but the doc looks wrong" bugs.
| Target block type | Use this operation | Why |
|---|---|---|
| text (any subtype: NORMAL_TEXT, LARGE_TITLE, MEDIUM_TITLE, SMALL_TITLE, QUOTE) | update_block for content edits; replace_block to change the subtype (e.g. promote a paragraph to H2) | Subtype is set on creation; update_block cannot change it |
| code | update_block | Content and language editable in place |
| list_item (BULLETED_LIST, NUMBERED_LIST, CHECK_LIST) | update_block for content edits; replace_block to switch between bulleted / numbered / check | List variant is set on creation |
| divider | replace_block only | No mutable properties |
| table | replace_block only | Row / column count and column widths immutable; table cell content not addressable via API after creation - see "Tables" below |
| image | replace_block to swap source | URL / asset_id immutable after creation |
| video | replace_block to swap source | raw_url immutable after creation |
| notice_box | replace_block to change theme | theme immutable; content lives in child blocks (see "Notice boxes" below) |
| layout | replace_block only | Cell content cannot be populated via API at all - see "Layouts" below |
| BOARD embed, WIDGET embed, DOC embed, GIPHY | delete_block only | No public API to create or modify these block types |
Rendering quirk - list_item + mention via update_block. When adding an inline mention to a list_item that previously contained only text, update_block may save the mention blot correctly (data confirms) but Cowork can fail to render the pill (text-prefix-before-mention case). Workaround: use replace_block with a fresh list_item containing the same delta. Same pattern in a normal_text block renders correctly; the quirk appears specific to list_item updates.
Full per-block-type detail with worked examples lives in references/block-operations-matrix.md. Read it before authoring any non-trivial structural edit.
monday docs live in one of two places:
workspace_id. Optional doc_kind: public (default), private (only the creator), share (specific people). Optional folder_id to nest under a folder.item_id. Optional column_id if the user picked a specific doc column; otherwise the tool auto-creates one.Cell-limit preflight for item-attached docs. Doc-type cells hold one doc per cell - hard API limit. Before calling create_doc location=item, preflight the target column via get_board_items_page with columnIds: [<doc_col_id>] to check whether the cell is already populated. If populated, do NOT attempt the create - it will fail with CellLimitExceededException. Fall back to creating a workspace-level doc and adding a bi-directional DOC mention cross-link between the new doc and the existing attached doc. Never auto-detach the existing doc.
If the user does not name a workspace, fall back to the user's primary workspace via get_user_context. Ask once if it's still ambiguous; do not guess across multiple workspaces.
Free and Basic plans cap at 3 docs per account. Before calling create_doc on a Free / Basic account, check whether this would be the 4th doc. There is no direct doc-count tool, so the practical guard is: if the user has hit this limit before or asks "can I create more than 3 docs?", warn them - upgrade to Standard+ removes the cap. Treat plan-tier as an open question rather than blocking the create call; the platform itself will reject if the cap is hit.
create_doc takes a markdown parameter that is parsed into blocks on import. This is the most efficient way to scaffold a doc in one call. Reach for one of these common shapes as a starting point when the user names a use case, then extend freely:
@mentions), agenda bullets, decisions, action items table, follow-ups.When the user invents a shape ("partner enablement page", "AI readiness snapshot", "Q3 onboarding context"), compose with judgment - sections, tables, notice boxes, embeds - rather than forcing a named template. The differentiators apply to any shape.
Default mode: passive scaffold. Reserve visible slots for embeds and mentions in the markdown body using machine-readable markers. Skill (and downstream agents) can later detect and fill these slots when the user names the underlying items / users.
| Slot type | Marker format | Example |
|---|---|---|
| Live column-value embed | _[embed: <column> of <item-ref>]_ | _[embed: status of <top-priority item>]_ |
| User mention | _[mention: <user-ref>]_ | _[mention: <owner>]_ |
| Doc / board mention | _[mention-doc: <doc-name>]_ / _[mention-board: <board-name>]_ | _[mention-board: Project Tracker]_ |
Italic styling on slot markers gives visual signal that the content is dynamic. The bracket-keyword format is grep-able for downstream automation.
Active mode: escalate when intent signals are present. Switch from passive scaffold to wiring real embeds / mentions / cross-links when the user's prompt signals intent through name-based references. Never on item IDs - users speak in names.
Triggers that escalate to active mode:
Resolution chain (name -> ID, never ask the user for IDs):
get_board_items_page with searchTerm scoped to the named boardsearch with searchType: BOARDlist_users_and_teams with name: (scoped per cross-skill rule)Active mode communication contract. When the skill picks items / users in active mode, always state the choice and the reasoning: "Picked items X, Y, Z because . Override by naming different items."
Markdown notes that matter:
#, ##, ###) map to LARGE_TITLE / MEDIUM_TITLE / SMALL_TITLE blocks.update_doc with create_block and block_type: "image" plus asset_id after creation - markdown cannot reference assets.update_doc after the doc is created.create_doccreate_doc({
doc_name: "<title>",
location: "workspace",
workspace_id: <id>,
doc_kind: "public" | "private" | "share", // optional
folder_id: <id>, // optional
markdown: "<full markdown body>"
})
For item-attached (after preflight):
create_doc({
doc_name: "<title>",
location: "item",
item_id: <id>,
column_id: "<doc_column_id>", // optional
markdown: "<full markdown body>"
})
Capture the returned doc_id, object_id, and doc_url. The user wants the URL to share or open; the doc_id is the primary key for every subsequent edit.
Mentions, live column-value embeds, notice boxes, layouts, and asset images all need a follow-up update_doc call. In active mode, wire them now using the resolved IDs from Step 3. In passive mode, leave the slot markers in place - the user fills slots later by naming items. See "Common edit patterns" below.
Plain-language confirmation: name, workspace, doc URL. State the mode used (passive scaffold or active). Then 2-3 follow-ups appropriate to the shape:
Three ways the user might point at a doc:
41302579) - the API's primary key, returned by create_doc and read_docs.18411484379) - the numeric segment of the doc URL: https://monday.monday.com/docs/{object_id}.read_docs with type: "workspace_ids" to list docs in a workspace, then match by name.read_docs is forgiving: if you call it with type: "ids" and the value is actually an object_id, it auto-retries as object_ids. Lean on this rather than guessing.
Two modes:
include_blocks: true is mandatory if any edit will follow. Do not omit it.include_comments: true to fetch all comments and replies. Use comments_limit to cap (default 50).object_id, not the id. Set version_history_limit for "last N changes" requests; set include_diff: true to see what changed (slower).The API's blocks_as_markdown projection renders mentions as @{USER-XXX} placeholders and live column-value embeds as empty space. This is not the right rendering for a "show me what's in this doc" prompt - the user sees pills and live chips when they open the doc; the textual rendering should mirror that.
For read responses to "show me / what's in / read this doc" prompts:
list_users_and_teams or a scoped lookup). Map every DOC mention to its doc name. Map every BOARD mention to its board name. Render inline as **@Alex Polonsky** (or similar) rather than @{USER-38288909}.get_board_items_page scoped to the specific items + columns. Render as the resolved column value ("Working on it", "No value", "2026-05-15") inline. Skip resolution only if it would require many extra MCP calls for a long doc.Do not use show-table for doc content - the doc itself is the UI. Render in chat with markdown.
read_docs with include_blocks: true. This is the closed-loop precondition. Capture every block's id, type, and position.
Reach for the simplest one that does the job:
add_markdown_content (no block IDs needed; supports text, lists, tables, code).create_block with block_type: "image" and asset_id (markdown does not support asset images).update_block with the matching block_content_type (text, code, or list_item).replace_block. Subtypes are set on creation only.create_block with after_block_id set. There is no before_block_id operation - to insert at the very top of a doc, the only path is to insert after the doc's first block.delete_block. The only path for BOARD / WIDGET / DOC embed / GIPHY blocks.add_comment (see "Comments" below).set_name.The full type-to-operation routing lives in references/block-operations-matrix.md.
update_block and create_block for content blocks take a delta_format array of insert ops. Three rules govern every delta:
{insert: {text: "\n"}}. Always. No exceptions.{insert: {text: "..."}} with optional attributes (bold, italic, underline, strike, code, link, color, background).{insert: {mention: {id: <numeric-id>, type: "USER" | "DOC" | "BOARD"}}}. Resolve user IDs via list_users_and_teams (always pass name to scope the call).{insert: {column_value: {item_id: <id>, column_id: "<column_id>"}}}. Renders the current value of that column on that item, live, every time the doc is opened.Worked examples and the full attribute table live in references/delta-format-cheatsheet.md.
update_doc accepts up to 25 operations in one call, executed in order, stopping at the first failure. Four gotchas:
parent_block_id in a later operation in the same call. Create the notice_box, capture the returned ID, then make a second update_doc call to nest children.block_id, surface the conflict to the user before executing - "last write wins" is the observed behavior. Example: update_block adds a mention to paragraph X, then a later update_block replaces paragraph X entirely. The second wins; the mention is lost.attributes.comments: [<update_id>, ...] on the relevant text insert. update_block replaces the entire delta_format, so a clean rewrite detaches the comment from the block (the comment itself survives on the backing item but loses its block link). To preserve anchored comments through an edit, include the comments attribute on the matching text insert in the new delta.After a non-trivial edit, re-read with include_blocks: true to confirm the blocks landed as intended. Plain-language confirmation: what changed, the doc URL. Do not narrate the API calls.
The table block type is supported but constrained:
add_markdown_content or the initial create_doc markdown body. Markdown table syntax populates cells in one shot.create_block: possible, but cells cannot be populated via the API after creation. The user has to fill cells from the monday UI.replace_block - the new table can be pre-filled if you replace it via add_markdown_content instead, by deleting the old table and appending a new markdown table after the deletion target.When the user asks to "edit cell B2", explain the constraint and offer the closest workaround: rewrite the whole table via markdown.
A notice_box is a styled callout container. Creating one with content takes two update_doc calls:
create_block with block_type: "notice_box" and theme: "INFO" | "TIPS" | "WARNING" | "GENERAL". Capture the returned block ID.create_block with parent_block_id: "<notice_box_id>" and the child block content (typically text).Theme cannot be changed after creation - use replace_block to swap themes, but child content does not transfer; recreate the children inside the new notice_box.
The layout block type creates a multi-column layout (2-6 columns). Cell content cannot be populated via the API at all. No markdown shortcut, no parent_block_id support. Layouts created via the API are empty shells the user fills from the monday UI.
If the user asks for "a two-column section with a summary on the left and metrics on the right", call this out: build the layout shell via create_block, then ask the user to fill the cells in the UI, or fall back to a different shape (heading + sub-headings, or a single-column with a separator).
{insert: {mention: {id, type}}} tags a user, doc, or board inline. Three types:
USER (most common). id is the numeric user ID from list_users_and_teams.DOC. id is the doc's object_id.BOARD. id is the board ID.Resolution rules:
list_users_and_teams with name: "Daniel" to get the ID. Confirm the match if multiple results.daniel.h for [email protected]); fall back to asking for the display name.list_users_and_teams without a name or userIds parameter. The unfiltered call returns the entire account user list (hundreds of KB on real tenants) and breaks token limits.Mention blots ignore attributes. Do not try to bold or color a mention.
{insert: {column_value: {item_id, column_id}}} embeds the current value of a column on a specific board item, rendered live every time the doc is opened. This is the capability ecosystem builders should reach for - it turns a static doc into a living dashboard fragment.
Use cases worth scaffolding:
Resolution rules:
item_id exists via get_board_items_page or get_full_board_data before writing.column_id matches a real column on the item's board via get_board_info. Wrong column IDs produce silent rendering gaps - the embed shows as empty space.color_mm2x25ey), never a generic literal like "status". Cross-skill rule.add_comment operates at three scopes:
block_id. The comment is attached to the doc as a whole.block_id (or an array of block IDs to highlight several at once). Only works on text, code, list_item, title, and quote blocks - not on divider, table, layout, notice_box, image, video, or giphy blocks.block_id plus selection_from (0-indexed start) and selection_length. Only valid on text / code / list_item.Threading: pass parent_update_id (the comment's update ID, returned by add_comment or read_docs with include_comments: true) to reply.
Comment body uses HTML, not markdown. To tag a user in a comment, do not put @ in the body - use mentions_list with a JSON array: [{"id":"38288909","type":"User"}]. Valid types: User, Team, Board, Project.
Deleting a comment via delete_update does NOT auto-clean the anchored reference on the host block's text insert (attributes.comments still lists the dead update_id). For full cleanup, separately update the block's delta to drop the comments attribute.
When the user does not specify all values:
get_user_context. State the default. Ask once if multiple workspaces are plausible.public (the platform default).State every default in the response so the user can override.
read_docs succeeded for the target ID before any write.block_id in the operations array came from the most recent read_docs call.list_users_and_teams (always with a name or userIds filter).get_board_info and get_board_items_page confirm both before the write. Status column IDs are always board-specific (e.g. color_mm2x25ey), never the generic literal "status".list_workspaces if the user named one but did not provide an ID.get_board_items_page before create_doc location=item (see Step 1).Before any create_block, add_markdown_content, add_comment, or content-replacing update_block, compare the proposed content against existing blocks in the doc. Default to skip + report on match; surface options to the user; never silently duplicate.
Match heuristics by block type:
| Block type | Match heuristic |
|---|---|
| text / heading / quote / code | exact delta text + same subtype |
| list_item | exact text + same list type + adjacency (multi-bullet sections matched as a group) |
| notice_box | same theme + same child text |
| table | same dimensions + same cell content |
| mention | same user_id at same block position |
| column_value embed | same item_id + column_id at same block position |
| comment | same body text + same anchor (excluded by default - see below) |
Skill behavior on match found:
Exclusions where duplication is normal and detection should NOT trigger:
This rule is lifted to SKILL_QUALITY_PRINCIPLES.md as a cross-skill rule. Every write path in the plugin honors it.
Common failures and how to remediate:
include_blocks: true and use the actual block IDs returned.include_blocks: true and retry. Block IDs change when blocks are deleted and recreated (e.g. via replace_block).replace_block.create_doc location=item - the target doc column cell is already populated (1-doc-per-cell limit). Fall back to a workspace-level doc with a bi-directional DOC mention cross-link to the existing attached doc. See Step 1 preflight.get_board_info. If it's a permissions issue, suggest moving the source data to a less-restricted board.create_doc - Free / Basic 3-doc cap. Suggest upgrading to Standard+ or deleting an unused doc.add_markdown_content with a board URL).read_docs shows attributes.comments: [<update_id>] on a block but the comment is missing from the comments array, the comment was deleted but the anchor remained. Separately update the block's delta to drop the comments attribute for full cleanup.Require explicit confirmation for:
Single block edits, single block creates, and single comments need no extra confirmation - the user already asked.
The doc is the UI. Do not render show-table or show-chart to display doc content. Plain-text confirmations and markdown summaries are the right output.
Never tell the user "I called read_docs then update_doc with an update_block operation." Tell them what changed in human terms: "Updated the second paragraph of your runbook with the new escalation contact." Always include the doc URL.
get_user_context - resolve the user's primary workspacelist_workspaces - find a workspace by name when not providedcreate_doc - create a doc in a workspace or attached to an item; markdown body imported as blocks on creationread_docs - fetch one or more docs (content mode) or version history; include_blocks: true is mandatory before any edit; include_comments: true for comment threadsupdate_doc - sequential operations: set_name, add_markdown_content, update_block, create_block, delete_block, replace_block, add_commentlist_users_and_teams - resolve user IDs for mentions and mentions_list (always pass name or userIds to scope)get_board_info - validate column IDs before writing live column-value embeds; preflight board structure for active-mode embed wiringget_board_items_page - validate item IDs before writing live column-value embeds; preflight doc-column cells for item-attached create; resolve item names to IDs in active modesearch - fuzzy-resolve a doc by name or a board by name in active modereferences/block-operations-matrix.md - per-block-type allowed operations, gotchas, and example payloads.references/delta-format-cheatsheet.md - delta_format insert ops, attributes, mentions, column_value embeds, the terminator rule, common patterns, and the passive-mode slot marker format.npx claudepluginhub ai-integr8tor/anthropics-knowledge-work-plugins --plugin monday-comProvides C# and .NET testing patterns using xUnit, FluentAssertions, NSubstitute, Testcontainers, and WebApplicationFactory for unit and integration tests.