Install
$ agentstack add skill-mondaycom-skills-docs-collaborator ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Docs Collaborator
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.
Core constraint - read this first
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_docswithinclude_blocks: trueto get block IDs, types, and positions.- Identify the target block(s) by type and position or by content.
update_docwith the operation that matches the target block's type (see the routing rule below).
Block operation routing - the non-obvious part
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: NORMALTEXT, LARGETITLE, MEDIUMTITLE, SMALLTITLE, 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 | | listitem (BULLETEDLIST, NUMBEREDLIST, CHECKLIST) | 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 / assetid immutable after creation | | video | replace_block to swap source | rawurl 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 - listitem + mention via update_block. When adding an inline mention to a listitem 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 listitem containing the same delta. Same pattern in a normal_text block renders correctly; the quirk appears specific to listitem 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.
Workflow: Create a doc
Step 1: Decide the location
monday docs live in one of two places:
- Workspace (most common). Requires
workspace_id. Optionaldoc_kind:public(default),private(only the creator),share(specific people). Optionalfolder_idto nest under a folder. - Item-attached. The doc lives in a doc-type column on a specific board item. Requires
item_id. Optionalcolumn_idif 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: [] 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.
Step 2: Plan-tier guard before creating a 4th doc
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.
Step 3: Compose the body - shapes are examples, not boundaries
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:
- Meeting notes: title, date, attendees (with
@mentions), agenda bullets, decisions, action items table, follow-ups. - Weekly update: highlights, key metrics, risks, next-week plan.
- RFC: problem, proposed solution, alternatives considered, open questions, decision log.
- Runbook: trigger, prerequisites, numbered procedure, rollback steps, escalation path.
- Postmortem: incident summary, timeline, root cause, what went well, what did not, action items.
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: of ]_ | _[embed: status of ]_ | | User mention | _[mention: ]_ | _[mention: ]_ | | Doc / board mention | _[mention-doc: ]_ / _[mention-board: ]_ | _[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:
- Item names ("the Q3 plan", "the launch milestone", "the blocker we discussed")
- Board names ("from the project tracker", "in the bug board")
- Owner names ("Daniel's tasks", "my items", "the design team's")
- Positional refs ("the top 3 priorities", "the most recent stuck items")
- Imperative wiring ("embed live status from", "show current status of", "pull from ", "wire up the embeds", "tag me as owner")
Resolution chain (name -> ID, never ask the user for IDs):
- Item name ->
get_board_items_pagewithsearchTermscoped to the named board - Board name ->
searchwithsearchType: BOARD - Owner name ->
list_users_and_teamswithname:(scoped per cross-skill rule) - Ambiguous match -> ask once with the top 3 candidates; do not silently pick
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:
- Markdown headings (
#,##,###) map to LARGETITLE / MEDIUMTITLE / SMALL_TITLE blocks. - Markdown tables work and the cells will be populated with the values you put in. This is the only way to get pre-filled table content. Cell-level API population after creation is not supported.
- Markdown images and links work. For asset-based images (uploaded files in monday), use
update_docwithcreate_blockandblock_type: "image"plusasset_idafter creation - markdown cannot reference assets. - Markdown does not have notice_box, layout, embed, divider-with-spacing, mention, or live column-value syntax. Add those via
update_docafter the doc is created.
Step 4: Call create_doc
create_doc({
doc_name: "",
location: "workspace",
workspace_id: ,
doc_kind: "public" | "private" | "share", // optional
folder_id: , // optional
markdown: ""
})
For item-attached (after preflight):
create_doc({
doc_name: "",
location: "item",
item_id: ,
column_id: "", // optional
markdown: ""
})
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.
Step 5: Layer in the rich-content extras
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.
Step 6: Confirm and suggest next steps
Plain-language confirmation: name, workspace, doc URL. State the mode used (passive scaffold or active). Then 2-3 follow-ups appropriate to the shape:
- "Want me to tag the attendees with @mentions?"
- "Want me to embed live status from the project board?"
- "Should I add a notice box at the top with the meeting outcome?"
- "Want me to share the doc URL in a Slack channel?"
Workflow: Read a doc
Step 1: Resolve the doc identifier
Three ways the user might point at a doc:
- doc_id (e.g.,
41302579) - the API's primary key, returned bycreate_docandread_docs. - object_id (e.g.,
18411484379) - the numeric segment of the doc URL:https://monday.monday.com/docs/{object_id}. - doc name or fuzzy reference ("the Q3 retro doc") - resolve via
read_docswithtype: "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.
Step 2: Decide what to read
Two modes:
- content (default) - returns the doc's blocks and / or markdown projection.
include_blocks: trueis mandatory if any edit will follow. Do not omit it.include_comments: trueto fetch all comments and replies. Usecomments_limitto cap (default 50).- version_history - returns the doc's edit history (restoring points). Pass the
object_id, not theid. Setversion_history_limitfor "last N changes" requests; setinclude_diff: trueto see what changed (slower).
Step 3: Render with resolved mentions and embeds, not placeholders
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:
- Always resolve mentions. Map every USER mention id to a display name (via cached
list_users_and_teamsor 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}. - Resolve embeds when data is cached or cheap to fetch. If the doc references items / columns already touched in the conversation, use the cached value. If not, fetch with
get_board_items_pagescoped 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. - Always keep the structured enumeration table as a secondary affordance. List every inline non-text element (mentions, embeds, notice_boxes, code blocks, tables) with block IDs and IDs. Useful for downstream edit operations and for users who want to target a specific element.
Do not use show-table for doc content - the doc itself is the UI. Render in chat with markdown.
Workflow: Edit a doc
Step 1: Read first
read_docs with include_blocks: true. This is the closed-loop precondition. Capture every block's id, type, and position.
Step 2: Pick the right operation
Reach for the simplest one that does the job:
- Add new content at the end:
add_markdown_content(no block IDs needed; supports text, lists, tables, code). - Add asset-based images:
create_blockwithblock_type: "image"andasset_id(markdown does not support asset images). - Edit existing text / code / list_item content in place:
update_blockwith the matchingblock_content_type(text,code, orlist_item). - Change a block's subtype (paragraph -> H2, bulleted -> numbered, INFO notice -> WARNING notice):
replace_block. Subtypes are set on creation only. - Insert a block at a precise position:
create_blockwithafter_block_idset. There is nobefore_block_idoperation - to insert at the very top of a doc, the only path is to insert after the doc's first block. - Delete:
delete_block. The only path for BOARD / WIDGET / DOC embed / GIPHY blocks. - Comment:
add_comment(see "Comments" below). - Rename the doc:
set_name.
The full type-to-operation routing lives in references/block-operations-matrix.md.
Step 3: Compose the deltaformat (for text / code / listitem)
update_block and create_block for content blocks take a delta_format array of insert ops. Three rules govern every delta:
- The last op MUST be
{insert: {text: "\n"}}. Always. No exceptions. - Plain text uses
{insert: {text: "..."}}with optionalattributes(bold, italic, underline, strike, code, link, color, background). - Two non-text inserts unlock the differentiators:
- Mention:
{insert: {mention: {id: , type: "USER" | "DOC" | "BOARD"}}}. Resolve user IDs vialist_users_and_teams(always passnameto scope the call). - Live column-value embed:
{insert: {column_value: {item_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.
Step 4: Batch operations carefully
update_doc accepts up to 25 operations in one call, executed in order, stopping at the first failure. Four gotchas:
- Notice box nesting requires two calls. A noticebox created in the same call cannot be referenced by
parent_block_idin a later operation in the same call. Create the noticebox, capture the returned ID, then make a secondupdate_doccall to nest children. - Position dependencies. If operation B references the position of a block created by operation A, prefer two calls. Failures partway through the array leave the doc in a partial state.
- Same-block conflict detection. When
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mondaycom
- Source: mondaycom/skills
- License: MIT
- Homepage: https://developer.monday.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.