{"id":46933,"plugin_id":"plugin_asdk_app_6ac9d7b951cc8191bfbfe7e42b070fce","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-24T13:31:39.143Z","digest":"87d54a889989b7ab6fae97da2dd731c580fd489acd9dd0008e74871f9f7a5c6d","against":null,"payload":{"description":"Simulator.Company reactions specialist — comments, events, approvals, ratings and other feedback attached under an actor. Use when the user wants to comment on an actor, reply in a thread, read/like/pin the discussion, mark comments read, or get reaction stats. Activate when the user says \"comment on this actor\", \"leave a note\", \"reply to\", \"show the comments/discussion\", \"pin this comment\", \"mark as read\", \"прокоментуй актор\", \"залиш коментар\", \"відповісти на коментар\", \"закріпи коментар\", \"оставь комментарий\", \"ответь в треде\", \"закрепи комментарий\". For attaching FILES to a reaction use `simulator-attachments`; for the actor's own fields use `simulator-actors`.\n","included_files":[],"name":"simulator-reactions","skill_md_contents":"---\nname: simulator-reactions\ndescription: >\n  Simulator.Company reactions specialist — comments, events, approvals, ratings and\n  other feedback attached under an actor. Use when the user wants to comment on an\n  actor, reply in a thread, read/like/pin the discussion, mark comments read, or get\n  reaction stats. Activate when the user says \"comment on this actor\", \"leave a note\",\n  \"reply to\", \"show the comments/discussion\", \"pin this comment\", \"mark as read\",\n  \"прокоментуй актор\", \"залиш коментар\", \"відповісти на коментар\", \"закріпи коментар\",\n  \"оставь комментарий\", \"ответь в треде\", \"закрепи комментарий\". For attaching FILES to a\n  reaction use `simulator-attachments`; for the actor's own fields use `simulator-actors`.\n---\n\n> **Curated tool names (v2 server):** `createReaction`, `updateReaction`, `deleteReaction`,\n> `getReactions`, `getReactionsStats`, `markReactionsRead`, `getPinnedReactions`,\n> `togglePinnedReaction`. Call them by these exact names.\n\n# Simulator.Company Reactions Specialist\n\n**Reactions** are the comments / events / approvals / ratings that live **under an actor**.\nThey are themselves actors, organised as a hierarchical (threaded) tree, so a reaction can\nreply to another reaction.\n\n> **Relationship to the other skills**\n> - **`simulator-actors`** — the actor's own `data` fields (a reaction is *about* an actor, not its data).\n> - **`simulator-attachments`** — files attached to a reaction or actor (a reaction can carry `attachments`).\n> - **`simulator-graph`** — graph structure (links/layers), unrelated to reactions.\n\n## The one rule that trips everyone up: `actorId` vs `reactionId`\n\nEvery reaction path is addressed by the **parent (root) actor**, while the reaction's **own\nid** travels separately:\n\n- **`actorId`** (path) = the **parent actor** whose reaction tree you are working in.\n- **`reactionId`** (body, on update/delete/pin) = the **specific reaction** to act on.\n- **`parentId`** (on create) = the reaction you are **replying to** (omit for a top-level comment).\n\nThe tools expose these as distinct arguments, so you never collide the two.\n\n## Workspace context\n\nReactions are addressed by `actorId` (a UUID), so no `accId` is needed. Make sure you have the\ntarget actor's UUID (use `simulator-actors` / `searchActors` to find it) before commenting.\n\n---\n\n## Comment on an actor\n\n```\ncreateReaction(\n  type=\"comment\",                 # everyday note; other types: view, rating, sign, ds, done, reject, freeze; ai = agent reply (see below)\n  actorId=\"<parent actor UUID>\",\n  description=\"Looks good to me\",  # the comment text\n  notify=true)                     # default true; set false to post quietly\n```\n\nReply in a thread — pass the parent reaction's id as `parentId`:\n\n```\ncreateReaction(type=\"comment\", actorId=\"<parent actor UUID>\",\n  description=\"Agreed\", parentId=\"<reaction UUID being replied to>\")\n```\n\nAttach files by passing `attachments` (ids from `uploadBase64` / `getAttachments`, see\n`simulator-attachments`):\n\n```\ncreateReaction(type=\"comment\", actorId=\"<actor UUID>\", description=\"see attached\",\n  attachments=[{ \"attachId\": 5521 }])\n```\n\n## Edit / delete a reaction\n\n```\nupdateReaction(actorId=\"<parent actor UUID>\", reactionId=\"<reaction UUID>\",\n  description=\"Updated note\")\ndeleteReaction(actorId=\"<parent actor UUID>\", reactionId=\"<reaction UUID>\")   # irreversible — confirm first\n```\n\n## Read reactions\n\n```\ngetReactions(actorId=\"<parent actor UUID>\", view=\"tree\", limit=30)   # view: tree | flat | thread\ngetReactionsStats(actorId=\"<parent actor UUID>\")                     # counts by type, etc.\n```\n\n- `view=tree` returns the nested reply tree; `flat` a flat list; `thread` a single thread.\n- `parentId` narrows to the replies under one reaction; `from`/`to` filter by created time.\n\n## AI agent reactions (`extra.mcp`)\n\nA reaction can be handed to the platform's **AI agent** by creating it with\n`extra.mcp = true`. The platform then runs the agent on that reaction **under the\nrequesting user's access** (the agent uses this same MCP server, so it can only\nread/write what the user can) and posts the answer back as a child **`ai`** reaction.\n\n```\ncreateReaction(type=\"comment\", actorId=\"<actor UUID>\",\n  description=\"Summarize this actor and flag anything unusual\",\n  extra={ \"mcp\": true })            # → triggers the AI agent; its reply appears as a child `ai` reaction\n```\n\nThe `ai` reply carries a `reasoning` object that the agent streams while it works:\n\n- `reasoning.inProgress` — `true` while the agent is still producing the answer.\n- `reasoning.thoughts` — `[{ id, text, createdAt }]`, a step log (e.g. tools it used).\n- `description` — fills with the answer text (streamed live over WebSocket, then finalized).\n\nSo when reading a discussion (`getReactions`), an `ai` reaction with\n`reasoning.inProgress = true` is still being written; treat its `description` as partial.\n\n> **Don't loop:** the agent already replies on its own. Only set `extra.mcp` on a\n> *human* request you want the agent to handle — not on the agent's own output. The\n> platform bounds runaway chains, but creating `extra.mcp` reactions from agent\n> output wastes turns.\n\nWhen the agent runs, the client also passes a **UI-context** object (`control-events-context`)\nthat says **where the user is** — `activeActor`, `activeReaction`, `activeLayer`, `activeGraph`,\n`page`, `hostOrigin`, `workspaceId`, `graphDiscovery`. Read it to resolve \"here\" / \"this actor\" /\n\"this layer\" and to default ids the user left implicit. See\n`$CLAUDE_PLUGIN_ROOT/docs/entities/ui-context.md`.\n\n> **Attachments: actor vs. message are two different sets.** Attachments are a per-actor linked\n> collection, and a reaction is itself an actor — so there are **two** places a file can live, each\n> read with `getActorAttachments(<id>)` → `readAttachment`:\n> - **The actor's own files** (\"files on this actor / the attachments tab\") → `getActorAttachments(activeActor)`.\n> - **A file the user attached to *their message*** (\"do you see the file I sent?\") → the triggering\n>   message **is a reaction** under `activeActor`, so its file lives on **that reaction**, not on the\n>   actor. Use the reaction's id: prefer **`activeReaction`** from the UI context; if absent, find the\n>   trigger via `getReactions(actorId=activeActor, view=\"flat\", orderValue=\"DESC\")` — the newest human\n>   reaction (the one with `extra.mcp`) — and pass **its** id to `getActorAttachments`.\n>\n> Pick the set the user means; if it's ambiguous, check **both** (the actor and the triggering reaction).\n\n## Embed a smart form, an actor card, or chips\n\nA reaction can carry more than text:\n\n- **Run a Smart Form (script) in the reaction** — set `appId` to a Smart Form (CDU/Script app)\n  actor id (+ optional `appSettings` `{autorun, expired, users, groups, fullWidth}`):\n  `createReaction(type=\"comment\", actorId=\"<actor>\", appId=\"<smartFormActorId>\", appSettings={autorun:true})`.\n  (The same `appId`/`appSettings` embed a smart form into a regular actor — see `simulator-smart-forms`.)\n- **Nested actor card** — `extra.linkedActorId` embeds another actor as a preview card:\n  `createReaction(..., extra={ \"linkedActorId\": \"<otherActorId>\" })`.\n- **Inline chips / rich text** — `description` renders **BBCode**: chips `[actor=<id>]Label[/actor]`,\n  `[application=<smartFormId>]Label[/application]`, `[user=…]`, `[event=…]`; formatting `[b]`,\n  `[color=…]`, `[h2]`, `[ul][*]…[/ul]`, `[url=…]`; and `[md]…[/md]` for markdown. Fetch the\n  environment's exact tag set with **`getBbcodeTags`**. **BBCode works only OUTSIDE `[md]`\n  blocks** — keep chips/BBCode out of any `[md]…[/md]` section. And the reverse: `description`\n  is BBCode by default, **not** markdown, so any markdown you write MUST be wrapped in\n  `[md]…[/md]` (e.g. `[md]## Title\\n- item[/md]`) or it renders as literal text. See\n  `docs/entities/reactions.md`.\n\n## Pin & read state\n\n```\ngetPinnedReactions(actorId=\"<parent actor UUID>\")\ntogglePinnedReaction(actorId=\"<parent actor UUID>\", reactionId=\"<reaction UUID>\", pinned=true)\nmarkReactionsRead(actorId=\"<parent actor UUID>\", count=12)   # clears the unread badge\n```\n\n---\n\n## Reference Documents\n\n| Path | When to read |\n|---|---|\n| `$CLAUDE_PLUGIN_ROOT/docs/entities/reactions.md` | Reaction model, types, tree structure, `data` shape |\n| `$CLAUDE_PLUGIN_ROOT/docs/entities/attachments.md` | Attaching files to a reaction |\n\n## Tips\n\n- `actorId` is always the **parent** actor; the reaction's own id is `reactionId` (update/delete/pin).\n- `type=\"comment\"` is the default note; the full set is `view`/`comment`/`ai`/`rating`/`sign`/`ds`/`done`/`reject`/`freeze` — reserve `sign`/`ds`/`done`/`reject` for real approval / sign-off / completion flows (there is no `approve` type).\n- Reply by setting `parentId`; omit it for a top-level comment.\n- `notify=false` posts without sending notifications (it is honoured — sent explicitly).\n- `deleteReaction` is irreversible — confirm with the user first.\n- To attach a file, upload it first (`uploadBase64` → `attachId`) then pass `attachments:[{attachId}]` — see `simulator-attachments`.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}