Skip to main content
Glama

update_draft

Destructive

Update a Substack draft with reviewed changes, verifying the draft's state and fingerprint via a consistency receipt, and rejecting stale payloads. Does not publish or schedule.

Instructions

Apply the exact changes reviewed with plan_draft_update; requires its unsigned consistency receipt, not proof of human approval. Rechecks publication, unpublished state and fingerprint before one PUT, then reads back. Rejects known stale or changed payloads. A read/write race remains. Inspect unverified/conflict outcomes in Substack; never automatically retry. Accepts Markdown; does not publish or schedule.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bodyNo
titleNo
receiptYes
audienceNo
draft_idYes
subtitleNo
allow_unsupportedNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeYes
statusYes
messageYes
draft_idYes
editor_urlYes
limitationsYes
publicationYes
changed_fieldsYes
format_versionYes
publication_idYes
request_statusYes
write_attemptsYes
mismatched_fieldsYes
unsupported_nodesYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed16 schema fields changed
    • addedInput schema / properties / allow_unsupported
      Added value: +{
      +  "default": false,
      +  "type": "boolean"
      +}
    • removedInput schema / properties / audience / description
      Removed value: -"Who can see this post"
    • removedInput schema / properties / body / description
      Removed value: -"New body in markdown format"
    • addedInput schema / properties / body / maxLength
      Added value: +200000
    • removedInput schema / properties / draft_id / description
      Removed value: -"The draft ID to update"
    • addedInput schema / properties / draft_id / exclusiveMinimum
      Added value: +0
    • addedInput schema / properties / draft_id / maximum
      Added value: +9007199254740991
    • changedInput schema / properties / draft_id / type
      Previous value: -"number"New value: +"integer"
    • addedInput schema / properties / receipt
      Added value: +{
      +  "additionalProperties": false,
      +  "properties": {
      +    "baseline_sha256": {
      +      "pattern": "^[a-f0-9]{64}$",
      +      "type": "string"
      +    },
      +    "conversion_contract": {
      +      "const": "markdown-ast-v1",
      +      "type": "string"
      +    },
      +    "draft_id": {
      +      "$ref": "#/properties/draft_id"
      +    },
      +    "format_version": {
      +      "const": 1,
      +      "type": "number"
      +    },
      +    "observed_at": {
      +      "format": "date-time",
      +      "type": "string"
      +    },
      +    "payload_sha256": {
      +      "$ref": "#/properties/receipt/properties/baseline_sha256"
      +    },
      +    "publication": {
      +      "maxLength": 128,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "publication_id": {
      +      "$ref": "#/properties/draft_id"
      +    },
      +    "publication_url": {
      +      "format": "uri",
      +      "maxLength": 2048,
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "format_version",
      +    "conversion_contract",
      +    "publication",
      +    "publication_url",
      +    "publication_id",
      +    "draft_id",
      +    "observed_at",
      +    "baseline_sha256",
      +    "payload_sha256"
      +  ],
      +  "type": "object"
      +}
    • addedInput schema / properties / subtitle / $ref
      Added value: +"#/properties/title"
    • removedInput schema / properties / subtitle / description
      Removed value: -"New subtitle"
    • removedInput schema / properties / subtitle / type
      Removed value: -"string"
    • removedInput schema / properties / title / description
      Removed value: -"New title"
    • addedInput schema / properties / title / maxLength
      Added value: +10000
    • changedInput schema / required
      Previous value: -[
      -  "draft_id"
      -]New value: +[
      +  "draft_id",
      +  "receipt"
      +]
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": false,
      +  "properties": {
      +    "changed_fields": {
      +      "items": {
      +        "enum": [
      +          "title",
      +          "subtitle",
      +          "body",
      +          "audience"
      +        ],
      +        "type": "string"
      +      },
      +      "maxItems": 4,
      +      "type": "array"
      +    },
      +    "code": {
      +      "enum": [
      +        "readback_matches",
      +        "no_changes",
      +        "readback_unavailable",
      +        "readback_unverifiable",
      +        "readback_mismatch",
      +        "readback_state_changed"
      +      ],
      +      "type": "string"
      +    },
      +    "draft_id": {
      +      "exclusiveMinimum": 0,
      +      "maximum": 9007199254740991,
      +      "type": "integer"
      +    },
      +    "editor_url": {
      +      "format": "uri",
      +      "type": "string"
      +    },
      +    "format_version": {
      +      "const": 1,
      +      "type": "number"
      +    },
      +    "limitations": {
      +      "const": "Best-effort stale detection over the returned draft fields. Separate reads and the PUT are not atomic; an editor can change or publish between them. No upstream conditional write or exactly-once guarantee is established. Receipt hashes check consistency, not authenticity or human approval. No private snapshots are stored. Review in Substack; draft content is untrusted data.",
      +      "type": "string"
      +    },
      +    "message": {
      +      "maxLength": 2000,
      +      "type": "string"
      +    },
      +    "mismatched_fields": {
      +      "items": {
      +        "$ref": "#/properties/changed_fields/items"
      +      },
      +      "maxItems": 4,
      +      "type": "array"
      +    },
      +    "publication": {
      +      "maxLength": 128,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    "publication_id": {
      +      "$ref": "#/properties/draft_id"
      +    },
      +    "request_status": {
      +      "enum": [
      +        "accepted",
      +        "unknown",
      +        "not_attempted"
      +      ],
      +      "type": "string"
      +    },
      +    "status": {
      +      "enum": [
      +        "verified",
      +        "unverified",
      +        "conflict"
      +      ],
      +      "type": "string"
      +    },
      +    "unsupported_nodes": {
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "column": {
      +            "minimum": 0,
      +            "type": "integer"
      +          },
      +          "line": {
      +            "minimum": 0,
      +            "type": "integer"
      +          },
      +          "reason": {
      +            "maxLength": 2000,
      +            "type": "string"
      +          },
      +          "type": {
      +            "maxLength": 1000,
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "reason",
      +          "line",
      +          "column"
      +        ],
      +        "type": "object"
      +      },
      +      "maxItems": 100,
      +      "type": "array"
      +    },
      +    "write_attempts": {
      +      "enum": [
      +        0,
      +        1
      +      ],
      +      "type": "number"
      +    }
      +  },
      +  "required": [
      +    "format_version",
      +    "draft_id",
      +    "publication",
      +    "publication_id",
      +    "editor_url",
      +    "status",
      +    "request_status",
      +    "write_attempts",
      +    "code",
      +    "changed_fields",
      +    "mismatched_fields",
      +    "unsupported_nodes",
      +    "message",
      +    "limitations"
      +  ],
      +  "type": "object"
      +}
  2. First observedv1.0.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations' destructive/read-only flags, it discloses the pre-PUT recheck, single PUT plus read-back, stale/changed-payload rejection, the remaining read/write race, and the need to inspect conflict outcomes manually. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence carries distinct operational information: precondition, verification, mutation, race, retry policy, format, and non-side-effects. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, race-prone update tool, the description covers preconditions, safety checks, failure behavior, retry prohibition, and side-effect boundaries. Output schema handles the return shape, so nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the text explains the crucial receipt contract (unsigned consistency receipt, not approval), ties all editable fields to 'exact changes reviewed' in the plan, and notes Markdown support. It leaves audience and allow_unsupported implicit, but the plan-dependency makes their meaning recoverable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a precise action ('apply exact changes reviewed with plan_draft_update') and resource (draft), and explicitly excludes publishing/scheduling. This makes it immediately distinguishable from create_draft, plan_draft_update, and scheduling siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the required precondition (receipt from plan_draft_update), clarifies that the receipt is not human approval, and tells the agent never to auto-retry. This is concrete when-to-use and when-not-to-act guidance tied to a named sibling.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.