changedInput schema / properties / calls / items / oneOf
Previous value: -[
- {
- "additionalProperties": false,
- "properties": {
- "arguments": {
- "additionalProperties": false,
- "properties": {
- "clientRequestId": {
- "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
- "pattern": "^[A-Za-z0-9_-]{8,80}$",
- "type": "string"
- },
- "content": {
- "description": "Used only when creating a new note draft.",
- "type": "string"
- },
- "firstReply": {
- "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
- "type": "string"
- },
- "imageUrls": {
- "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "instagramDestinations": {
- "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
- "items": {
- "additionalProperties": false,
- "properties": {
- "accountId": {
- "type": "string"
- },
- "caption": {
- "maxLength": 2200,
- "type": "string"
- },
- "label": {
- "type": "string"
- }
- },
- "required": [
- "accountId"
- ],
- "type": "object"
- },
- "maxItems": 5,
- "minItems": 1,
- "type": "array"
- },
- "linkedInAccountId": {
- "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
- "minLength": 1,
- "type": "string"
- },
- "linkedInOrganizationUrn": {
- "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
- "minLength": 1,
- "pattern": "^urn:li:organization:[^\\s]+$",
- "type": "string"
- },
- "platformVersions": {
- "additionalProperties": {
- "minLength": 1,
- "type": "string"
- },
- "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
- "type": "object"
- },
- "platforms": {
- "items": {
- "enum": [
- "SUBSTACK",
- "LINKEDIN",
- "X",
- "BLUESKY",
- "THREADS",
- "INSTAGRAM",
- "FACEBOOK",
- "TIKTOK",
- "PINTEREST"
- ],
- "type": "string"
- },
- "type": "array"
- },
- "publication": {
- "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
- "type": "string"
- },
- "scheduledFor": {
- "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
- "type": "string"
- },
- "socialAccountIds": {
- "additionalProperties": {
- "minLength": 1,
- "type": "string"
- },
- "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
- "type": "object"
- },
- "substackConnectionId": {
- "deprecated": true,
- "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
- "type": "string"
- },
- "threadsTopicTag": {
- "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
- "type": "string"
- },
- "timezone": {
- "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
- "type": "string"
- },
- "videoUrls": {
- "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
- "items": {
- "type": "string"
- },
- "type": "array"
- },
- "workspace": {
- "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
- "type": "string"
- },
- "writer": {
- "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
- "type": "string"
- }
- },
- "required": [
- "scheduledFor",
- "platforms",
- "timezone",
- "content",
- "clientRequestId"
- ],
- "type": "object"
- },
- "tool": {
- "const": "schedule_note",
- "type": "string"
- }
- },
- "required": [
- "tool",
- "arguments"
- ],
- "type": "object"
- },
- {
- "additionalProperties": false,
- "properties": {
- "arguments": {
- "additionalProperties": false,
- "properties": {
- "addSearchMetadata": {
- "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
- "type": "boolean"
- },
- "contentHtml": {
- "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
- "type": "string"
- },
- "coverImage": {
- "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
- "properties": {
- "data": {
- "description": "Data URI or raw base64 image bytes.",
- "type": "string"
- },
- "mimeType": {
- "description": "Required for raw base64. Example: image/png.",
- "type": "string"
- },
- "sourceType": {
- "enum": [
- "url",
- "data_uri",
- "base64"
- ],
- "type": "string"
- },
- "url": {
- "description": "Public HTTPS image URL.",
- "type": "string"
- }
- },
- "type": "object"
- },
- "freewall": {
- "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
- "type": "boolean"
- },
- "isPaidContent": {
- "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
- "type": "boolean"
- },
- "linkedinAuthorUrn": {
- "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
- "type": "string"
- },
- "linkedinNewsletterUrn": {
- "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
- "type": "string"
- },
- "linkedinPublicationType": {
- "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
- "enum": [
- "article",
- "newsletter"
- ],
- "type": "string"
- },
- "linkedinShareCommentary": {
- "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
- "type": "string"
- },
- "media": {
- "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
- "items": {
- "properties": {
- "data": {
- "type": "string"
- },
- "fileName": {
- "type": "string"
- },
- "kind": {
- "description": "Defaults to image when omitted.",
- "enum": [
- "image",
- "video"
- ],
- "type": "string"
- },
- "mimeType": {
- "type": "string"
- },
- "sourceType": {
- "enum": [
- "url",
- "data_uri",
- "base64"
- ],
- "type": "string"
- },
- "url": {
- "type": "string"
- }
- },
- "type": "object"
- },
- "type": "array"
- },
- "mediumNotifyFollowers": {
- "description": "Whether to email Medium subscribers about this story. Only valid when platforms includes MEDIUM. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
- "type": "boolean"
- },
- "mediumPublicationId": {
- "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
- "type": "string"
- },
- "paywallMarker": {
- "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
- "maxLength": 200,
- "type": "string"
- },
- "platforms": {
- "items": {
- "enum": [
- "SUBSTACK",
- "MEDIUM",
- "LINKEDIN",
- "X",
- "WORDPRESS",
- "GHOST"
- ],
- "type": "string"
- },
- "type": "array"
- },
- "publication": {
- "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
- "type": "string"
- },
- "publishMode": {
- "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
- "enum": [
- "publish",
- "draft"
- ],
- "type": "string"
- },
- "scheduledFor": {
- "description": "Required unless publishNow or platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
- "type": "string"
- },
- "sendToNewsletter": {
- "description": "Substack email delivery setting. Default true.",
- "type": "boolean"
- },
- "substackConnectionId": {
- "deprecated": true,
- "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
- "type": "string"
- },
- "subtitle": {
- "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
- "type": "string"
- },
- "tags": {
- "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
- "items": {
- "maxLength": 50,
- "type": "string"
- },
- "maxItems": 50,
- "type": "array"
- },
- "timezone": {
- "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
- "type": "string"
- },
- "title": {
- "description": "Required when creating a new draft.",
- "type": "string"
- }
- },
- "required": [
- "platforms",
- "scheduledFor",
- "timezone",
- "title",
- "contentHtml",
- "addSearchMetadata"
- ],
- "type": "object"
- },
- "tool": {
- "const": "schedule_article",
- "type": "string"
- }
- },
- "required": [
- "tool",
- "arguments"
- ],
- "type": "object"
- }
-]New value: +[
+ {
+ "additionalProperties": false,
+ "properties": {
+ "arguments": {
+ "additionalProperties": false,
+ "properties": {
+ "clientRequestId": {
+ "description": "Optional but recommended: your own id for this note, 8 to 80 letters, numbers, hyphens or underscores. Use a new one for each note and the same one when retrying it (for example after a timeout or a rate-limit pause): the retry returns the original result and schedules nothing again. Reusing it with different text, platforms or time is refused.",
+ "pattern": "^[A-Za-z0-9_-]{8,80}$",
+ "type": "string"
+ },
+ "content": {
+ "description": "Used only when creating a new note draft.",
+ "type": "string"
+ },
+ "firstReply": {
+ "description": "Optional first reply for supported destinations. An invalid reply is omitted per platform without cancelling the root post.",
+ "type": "string"
+ },
+ "imageUrls": {
+ "description": "Optional image URLs or image data URIs to attach to the scheduled note.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "instagramDestinations": {
+ "description": "Instagram destinations with accountId returned by list_instagram_destinations and optional independent caption. Each account receives its own delivery receipt.",
+ "items": {
+ "additionalProperties": false,
+ "properties": {
+ "accountId": {
+ "type": "string"
+ },
+ "caption": {
+ "maxLength": 2200,
+ "type": "string"
+ },
+ "label": {
+ "type": "string"
+ }
+ },
+ "required": [
+ "accountId"
+ ],
+ "type": "object"
+ },
+ "maxItems": 5,
+ "minItems": 1,
+ "type": "array"
+ },
+ "linkedInAccountId": {
+ "description": "Optional LinkedIn account id for a connected LinkedIn destination. Absence of both this field and linkedInOrganizationUrn selects the configured default.",
+ "minLength": 1,
+ "type": "string"
+ },
+ "linkedInOrganizationUrn": {
+ "description": "Optional LinkedIn Company Page URN for a connected LinkedIn destination. Requires linkedInAccountId.",
+ "minLength": 1,
+ "pattern": "^urn:li:organization:[^\\s]+$",
+ "type": "string"
+ },
+ "platformVersions": {
+ "additionalProperties": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "description": "Optional platform-specific text keyed by platform, e.g. { \"BLUESKY\": \"...\" }. Each supplied version must fit its limit (Bluesky 300, Threads 500, LinkedIn 3000, X 25000) or nothing is scheduled. Saved as the draft’s platform-specific version.",
+ "type": "object"
+ },
+ "platforms": {
+ "items": {
+ "enum": [
+ "SUBSTACK",
+ "LINKEDIN",
+ "X",
+ "BLUESKY",
+ "THREADS",
+ "INSTAGRAM",
+ "FACEBOOK",
+ "TIKTOK",
+ "PINTEREST"
+ ],
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "publication": {
+ "description": "Substack publication name, handle, or URL selected by the user. Optional when exactly one active Substack publication is connected: Narrareach uses it when its session is ready and says which one was used in substackPublicationSelection.message (source \"sole_connection\"); if the session needs a sync or the profile cannot be verified, nothing is scheduled and the result says what to fix. In a team workspace with one publication, or when a writer who is also a team member omits workspace, nothing is scheduled until the writer confirms it (requiresPublicationChoice: true, publicationChoiceReason: \"confirmation_required\"). Notes publish from the profile signed in to that connection, including publications sharing one login. Unverified or mismatched profile identity returns action_required without publishing. Notes are profile-level: when it is missing and all of the writer’s publications are signed in to one Substack profile, no choice is needed and the note posts from that profile. Only when the publications span two or more Substack profiles does the writer choose a profile: Narrareach uses the one they chose most recently (and says so in substackPublicationSelection.message), or, with no previous choice, nothing is scheduled and the result has requiresPublicationChoice: true, choiceScope: \"profile\" and publicationChoices (one per profile); ask the user, then call again with substackConnectionId set to the chosen publicationChoices[].substackConnectionId. An ambiguous publication value also returns publicationChoices.",
+ "type": "string"
+ },
+ "scheduledFor": {
+ "description": "Local wall-clock publishing date/time interpreted in timezone, including DST (e.g. \"2026-07-01T14:30:00\" means 2:30 PM). A Z or explicit UTC offset represents an absolute instant instead.",
+ "type": "string"
+ },
+ "socialAccountIds": {
+ "additionalProperties": {
+ "minLength": 1,
+ "type": "string"
+ },
+ "description": "Optional account to post to on Threads, Facebook, TikTok, Pinterest or X, keyed by platform, e.g. { \"THREADS\": \"<accountId>\" }, with accountId values from list_social_accounts. Omit a platform to use its only account or its default. Required for a platform where list_social_accounts reports accountChoiceRequired; ask the writer which account rather than picking one.",
+ "type": "object"
+ },
+ "substackConnectionId": {
+ "deprecated": true,
+ "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
+ "type": "string"
+ },
+ "threadsTopicTag": {
+ "description": "Optional Threads topic tag. Threads must be selected; maximum 50 characters.",
+ "type": "string"
+ },
+ "timezone": {
+ "description": "IANA timezone the scheduledFor time above is expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
+ "type": "string"
+ },
+ "videoUrls": {
+ "description": "Optional video URLs or video data URIs to attach to the scheduled note.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "workspace": {
+ "description": "Authorized team workspace name or id for team scheduling. Absence selects the authenticated user’s personal account.",
+ "type": "string"
+ },
+ "writer": {
+ "description": "Authorized team writer name, handle, or id. \"me\" selects the linked team voice. Required when a team workspace has multiple writers.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "scheduledFor",
+ "platforms",
+ "timezone",
+ "content",
+ "clientRequestId"
+ ],
+ "type": "object"
+ },
+ "tool": {
+ "const": "schedule_note",
+ "type": "string"
+ }
+ },
+ "required": [
+ "tool",
+ "arguments"
+ ],
+ "type": "object"
+ },
+ {
+ "additionalProperties": false,
+ "properties": {
+ "arguments": {
+ "additionalProperties": false,
+ "properties": {
+ "addSearchMetadata": {
+ "description": "Generate SEO titles, descriptions, and a Substack slug for supported article destinations. SEO metadata is generated automatically on Revenue Writer, Full Agentic Mode, and Teams & Agencies, and for trials or other accounts with article SEO access. Set this option to false to turn it off. X does not support separate article SEO settings.",
+ "type": "boolean"
+ },
+ "contentHtml": {
+ "description": "Required when creating a new draft. Supports public <img> or <video> elements and {{media:N}} placeholders resolved from media entries. Video articles require Substack as the sole platform. Native Substack paywall markup is <hr data-type=\"paywall\"> at the selected paragraph boundary, or a single {{NARRAREACH_PAYWALL}} token; paywallMarker supports custom tokens. A Substack Freewall (free and paid subscribers keep reading) is <hr data-type=\"paywall\" data-access=\"subscribers\">, or set freewall to true. Native subscribe block markup is <div data-type=\"button\" data-kind=\"subscribeCaption\" data-text=\"Subscribe\" data-caption=\"Your caption\"></div> with HTML-escaped attribute values. data-kind=\"subscribe\" represents a button without caption. Ordinary links remain links. Audience sections use a div with data-dynamic-content=\"true\" and data-dynamic-audiences=\"paid_sub\", containing data-dynamic-content-match=\"true\" and data-dynamic-content-else=\"true\" divs. Supported audience conditions: non_sub, free_sub, paid_sub, founding_sub (comma-separated). Keep both branches. Subscriber-tag targeting must be published in Substack.",
+ "type": "string"
+ },
+ "coverImage": {
+ "description": "Optional cover image for a newly created draft, placed at the top of the published body. Supports public HTTPS URLs, data URIs, or base64 image bytes. URL ingestion depends on source-host access. For an image attached in ChatGPT, use coverFile instead. For a saved draft (draftId), attach the cover first with update_draft.",
+ "properties": {
+ "data": {
+ "description": "Data URI or raw base64 image bytes.",
+ "type": "string"
+ },
+ "mimeType": {
+ "description": "Required for raw base64. Example: image/png.",
+ "type": "string"
+ },
+ "sourceType": {
+ "enum": [
+ "url",
+ "data_uri",
+ "base64"
+ ],
+ "type": "string"
+ },
+ "url": {
+ "description": "Public HTTPS image URL.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "freewall": {
+ "description": "Make the article's single wall divider (or paywallMarker) a Substack Freewall: everyone sees the content above it; free and paid subscribers keep reading below it. Requires SUBSTACK and a publication with Substack Freewalls. For a new draft (title and contentHtml) it sets the Freewall. A saved draft (draftId) keeps the wall already in its body: a Freewall there is scheduled as a Freewall with or without this field, and true only confirms it. Never combine with isPaidContent. Default false.",
+ "type": "boolean"
+ },
+ "isPaidContent": {
+ "description": "Whether the Substack article is paid-only. Default false. Do not combine with freewall.",
+ "type": "boolean"
+ },
+ "linkedinAuthorUrn": {
+ "description": "LinkedIn personal profile or Company Page author URN belonging to the connected LinkedIn Articles account.",
+ "type": "string"
+ },
+ "linkedinNewsletterUrn": {
+ "description": "LinkedIn newsletter URN belonging to the connected LinkedIn Articles account. Required when linkedinPublicationType is newsletter.",
+ "type": "string"
+ },
+ "linkedinPublicationType": {
+ "description": "LinkedIn destination type. Defaults to an individual article; newsletter represents a user-selected newsletter destination.",
+ "enum": [
+ "article",
+ "newsletter"
+ ],
+ "type": "string"
+ },
+ "linkedinShareCommentary": {
+ "description": "Optional LinkedIn share text used when publishing a LinkedIn article.",
+ "type": "string"
+ },
+ "media": {
+ "description": "Optional inline images or Substack article videos for a newly created draft. Replaces {{media:N}} placeholders in array order; leftovers are appended. kind defaults to image; video requires Substack as the sole platform. Supports public URLs, data URIs, and base64 bytes. In ChatGPT, for a file the user attached in the chat, first call upload_media with it in file, then pass the returned publicUrl here as url.",
+ "items": {
+ "properties": {
+ "data": {
+ "type": "string"
+ },
+ "fileName": {
+ "type": "string"
+ },
+ "kind": {
+ "description": "Defaults to image when omitted.",
+ "enum": [
+ "image",
+ "video"
+ ],
+ "type": "string"
+ },
+ "mimeType": {
+ "type": "string"
+ },
+ "sourceType": {
+ "enum": [
+ "url",
+ "data_uri",
+ "base64"
+ ],
+ "type": "string"
+ },
+ "url": {
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "mediumNotifyFollowers": {
+ "description": "Whether to email Medium subscribers about this story. true is only valid when platforms includes MEDIUM; false is ignored. Defaults to false (no email). Best-effort: a failure to apply this setting never blocks the publish/schedule and is reported as a warning.",
+ "type": "boolean"
+ },
+ "mediumPublicationId": {
+ "description": "Optional authorized Medium publication id when platforms includes MEDIUM. Absent means the personal profile. Writer-only access submits for editorial review and leaves the story unscheduled until acceptance. Explicit publication rejection allows personal-profile delivery with a warning; ambiguous submissions remain unpublished for review. Draft-only delivery does not submit to a publication.",
+ "type": "string"
+ },
+ "paywallMarker": {
+ "description": "Optional custom marker in contentHtml where the selected free preview ends; must appear exactly once. The standard {{NARRAREACH_PAYWALL}} marker is recognized without this field. Creates a native divider without changing sendToNewsletter. With freewall true it allows free and paid subscribers; otherwise it enables paid access.",
+ "maxLength": 200,
+ "type": "string"
+ },
+ "platforms": {
+ "items": {
+ "enum": [
+ "SUBSTACK",
+ "MEDIUM",
+ "LINKEDIN",
+ "X",
+ "WORDPRESS",
+ "GHOST"
+ ],
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "publication": {
+ "description": "Substack destination as a publication name, handle, or URL, for example \"AI Newsroom\", \"@theainewsroom\", or \"https://theainewsroom.substack.com\". Optional when exactly one active Substack publication is connected; Narrareach selects it automatically. Required when more than one active Substack publication is connected, except that when it is missing Narrareach uses the publication the writer scheduled or published to most recently and says so in substackPublicationSelection.message, with publicationChoices listing the others; tell the writer which one was used. If there is no previous choice, the value is ambiguous, or Narrareach cannot confirm the session publishes there, nothing is scheduled and the result has requiresPublicationChoice: true with publicationChoices (name, handle, url, substackConnectionId). Ask which one they want, then call again with publication set to the chosen handle (and draftId when a draft was already saved).",
+ "type": "string"
+ },
+ "publishMode": {
+ "description": "Only valid when all selected destinations are WordPress or Ghost. Defaults to publish; draft saves a remote draft at the scheduled time without publication.",
+ "enum": [
+ "publish",
+ "draft"
+ ],
+ "type": "string"
+ },
+ "scheduledFor": {
+ "description": "Required unless publishNow or platformSchedules is given, and must be in the future. Shared local wall-clock publishing date/time interpreted in timezone, including DST. A Z or explicit UTC offset represents an absolute instant. LinkedIn articles require at least 20 minutes of lead time.",
+ "type": "string"
+ },
+ "sendToNewsletter": {
+ "description": "Substack email delivery setting. Default true.",
+ "type": "boolean"
+ },
+ "substackConnectionId": {
+ "deprecated": true,
+ "description": "Exact Substack connection identifier, retained for backward compatibility, for example publicationChoices[].substackConnectionId from a requiresPublicationChoice result. publication is the preferred public destination selector; when both are given they must name the same publication.",
+ "type": "string"
+ },
+ "subtitle": {
+ "description": "Optional article subtitle for newly created drafts. Substack omits subtitles over 250 characters and returns a warning without changing the saved draft.",
+ "type": "string"
+ },
+ "tags": {
+ "description": "Optional tag list for newly created drafts. Substack receives all supplied tags. Medium receives its supported first 5 topics and returns a warning when extras are omitted. The saved draft remains unchanged.",
+ "items": {
+ "maxLength": 50,
+ "type": "string"
+ },
+ "maxItems": 50,
+ "type": "array"
+ },
+ "timezone": {
+ "description": "IANA timezone the scheduledFor time(s) above are expressed in (e.g. \"Europe/London\"). Defaults to the writer's saved timezone, else UTC.",
+ "type": "string"
+ },
+ "title": {
+ "description": "Required when creating a new draft.",
+ "type": "string"
+ }
+ },
+ "required": [
+ "platforms",
+ "scheduledFor",
+ "timezone",
+ "title",
+ "contentHtml",
+ "addSearchMetadata"
+ ],
+ "type": "object"
+ },
+ "tool": {
+ "const": "schedule_article",
+ "type": "string"
+ }
+ },
+ "required": [
+ "tool",
+ "arguments"
+ ],
+ "type": "object"
+ }
+]