Skip to content

Proposals & Approval

What a commenter's write actually does

A commenter can call any canvas_* write tool, but the call never applies directly. It resolves to proposed, carrying a proposal id instead of a new revision. Nothing about the scene changes until someone with editor or above — a human, or another agent holding that role — acts on it. This is the one write path available to a role below editor, and today it is the only structured feedback mechanism a commenter has: there is no separate, freestanding comment tool. See MCP Tools for that gap stated plainly, and Canvas Roles for why — comments can't yet be persisted independent of a proposal, so nothing durable exists for a standalone comment to live in.

Seeing that a proposal is waiting

A pending proposal surfaces as a plain count next to the canvas in NEXUS's own canvas list — the number of changes awaiting review, with nothing else competing for attention at that spot. It's designed to be the one thing you're not meant to miss: proposals are work waiting on you, not a background detail.

Approving or rejecting

Two tools handle the decision: canvas_approve_proposal and canvas_reject_proposal. Either can be called by a human working in NEXUS directly, or by any agent whose role on that canvas is editor or owner — a commenter can raise a proposal but cannot approve its own or anyone else's. See MCP Tools for both tools' entries in the write-tool table.

A wire-level example: a commenter's write comes back proposed —

json
{
  "jsonrpc": "2.0",
  "id": 30,
  "result": {
    "resultType": "tools/call",
    "content": [{
      "type": "text",
      "text": "{\"outcome\":\"proposed\",\"proposalId\":\"a1b2c3\"}"
    }],
    "isError": false
  }
}

— and an editor approves it by id:

json
{
  "jsonrpc": "2.0",
  "id": 31,
  "method": "tools/call",
  "params": {
    "name": "canvas_approve_proposal",
    "arguments": {
      "workspaceId": "<workspace>",
      "canvasId": "<canvas>",
      "proposalId": "a1b2c3",
      "reason": "Matches the agreed layout"
    }
  }
}

Approval applies the original proposed change against the canvas's current state at approval time, not a stale snapshot from when it was raised — the same revision discipline every other write follows. See Revisions & Conflicts if the canvas moved on in the meantime.

Who asked, and who signed off, are recorded separately

The audit trail keeps the proposer and the approver as two distinct identities, even when both are agents and no human was ever in the loop for a particular approval. This means "who asked for this" and "who approved it" are always two separately answerable questions from the record itself — never collapsed into one, and never inferred. See Explanation: Canvas Model for why this distinction was worth keeping even when it adds no immediate value to the common case of a human approving an agent's proposal.

Rejecting a proposal

canvas_reject_proposal is the other side of the same decision — it exists so a proposal can be explicitly declined and closed out, rather than left pending indefinitely as unreviewed backlog. Like approval, it's available to editor and owner, not to the proposer itself.

Where to go next

  • Canvas Roles — the full role ladder and outcome contract.
  • Roles & Permissions — what a commenter can and can't do beyond proposing.
  • MCP Toolscanvas_approve_proposal and canvas_reject_proposal's exact entries.

Built with purpose.