Skill instructions
get-started3.95 KB
View saved version →
---
name: get-started
description: "Set up PostFast in this conversation and check that it works: connect PostFast, pick the workspace, see which social accounts are connected, fix disconnected ones and make a first post. Use when someone is new to PostFast here, asks how to set it up or what it can do, says the PostFast tools are missing or signed out, wants to connect or reconnect a social account, or asks why their posts are not going out."
---
# Get started with PostFast
These steps check the PostFast connection and take the user to their first post. They only read, apart from a connect link the user asks for. Scheduling, comments, repurposing and reports have their own skills: schedule-posts, manage-comments, repurpose-content and performance-report.
## Rules
1. **Read first, change nothing.** Setup uses tools that only read. The one exception is `generate_connect_link`, and only when the user wants a link to connect or reconnect an account.
2. **Report what the tools return.** Don't guess which accounts are connected, and mention the ones that are not.
3. **Keep it short.** Show what the next step needs, then offer it.
## Steps
### 1. Check the connection
Call `list_workspaces`.
- **It answers:** PostFast is connected. Carry on.
- **The PostFast tools are missing, or the call says the user is not signed in or the sign-in expired:** PostFast is not connected in this app yet, or its sign-in lapsed. Ask the user to add or reconnect PostFast in their app's connector or app settings and sign in with their PostFast account. While signing in they choose the workspace this connection uses by default. Then try again.
- **They have no PostFast account:** say that PostFast works with an existing PostFast account and that they need one to use it here. Don't link to sign-up, plans or pricing.
### 2. Pick the workspace
`list_workspaces` shows every workspace this connection can use. With one, carry on. With several, show them by name and ask which to work in, then pass its `id` as `workspaceId` on every call that follows. Leaving `workspaceId` out uses the workspace chosen at sign-in.
### 3. See the connected accounts
Call `list_accounts` and list the accounts by network, with each one's `platformUsername` or `displayName`.
- **CONNECTED** accounts can publish.
- **DISABLED** accounts won't publish until they are reconnected. Give the `disabledReason` and offer a reconnect link: `generate_connect_link` with `platforms` set to that network. Whoever owns the account opens the link and signs in again. Set `sendEmail` only when the user asks you to email the link and gives the address.
- **No accounts:** nothing is connected in this workspace yet. The user connects accounts in the PostFast app (https://app.postfa.st) or sends a link from `generate_connect_link` to whoever owns them.
- `inboxCapable` shows which accounts' comments reach the PostFast inbox.
### 4. Settle the time zone
Ask for the user's time zone once, and use it for every time you show or schedule.
### 5. Offer a first step
In two or three lines, offer what fits the accounts they have:
- Schedule or draft posts. Every post waits for their yes before it publishes.
- Answer comments on Instagram, Facebook, TikTok and Threads, with a preview of every reply first.
- Turn an article or a link into a week of posts.
- Report how their posts and followers did.
If they want to post now, follow the schedule-posts skill.
## When something fails
- **A missing scope or permission:** the connection was allowed less than this needs, or the user's role in the workspace doesn't include it. Ask them to reconnect PostFast and allow everything it asks for, or to ask a workspace admin.
- **`socialMediaDisconnected` when scheduling:** the account needs reconnecting (step 3).
- **`subscription.required`:** the account has no active PostFast plan, so PostFast refuses the call. Say so plainly, and that the account owner can sort out the plan in PostFast. Don't link to pricing, plans or checkout, and don't recommend a plan.
manage-comments6.8 KB
View saved version →
---
name: manage-comments
description: Read and answer comments on the user's social posts through the PostFast inbox, showing every reply or deletion to the user before it happens. Use when someone asks what people are saying under their posts, wants to find comments nobody has answered, reply to comments publicly or with an Instagram private reply, hide, unhide or delete a comment, or sort and assign comment threads on TikTok, Instagram, Facebook or Threads.
---
# Answer comments with PostFast
The PostFast inbox holds comments on the user's own posts on TikTok, Instagram, Facebook Pages and Threads. It is a comments inbox: never describe it as direct messages. Each account's `inboxCapable` flag in `list_accounts` says whether its comments reach the inbox today, and comments arrive only from the time the account was connected; there is no older history.
## Rules
1. **Nothing is sent or deleted without a yes to the exact preview.** Each action has its own preview tool, which sends nothing and returns a preview: `preview_comment_reply` for a public reply, `preview_private_reply` for an Instagram private reply and `preview_comment_deletion` for a deletion. Show the user the preview, wait for their yes in the conversation, and only then call the tool that carries it out: `reply_to_comment`, `send_private_reply` or `delete_comment`. This holds even when the user dictated the reply word for word: they still see the preview and say yes before it is sent. Never preview and carry out in the same turn.
2. **Carry out exactly what was previewed.** Pass the `confirmToken` from the preview with the same `itemId` and `text`, and the same `workspaceId` only if you passed one to the preview. If the user changes the text, preview it again and show the new preview.
3. **The conversation decides whether and how long a reply can be.** Read `canReply`, `maxReplyLength`, `windowState` and `disabledReason` on the conversation and keep to them. Don't assume a network's rules. When `canReply` is false, tell the user why, using `disabledReason`, instead of trying.
4. **If `preview_comment_reply`, `preview_private_reply` or `preview_comment_deletion` is not among your tools,** that action (a public reply, a private reply or a deletion) isn't available on this connection. Tell the user and suggest doing it in PostFast instead. Reading, hiding, restoring and sorting comments still work.
## Find comments to answer
1. If the user has more than one workspace (`list_workspaces`), ask which one and pass its `id` as `workspaceId` on every call.
2. `get_inbox_unread_count` gives the total of unread comments.
3. `list_inbox_conversations` lists threads, newest activity first, one per post. Filter with `unreadOnly`, `statuses` (OPEN, SNOOZED or CLOSED), `platforms` or `socialMediaIds`, and page with `page`.
4. `list_inbox_items` with the conversation's `id` as `conversationId` lists its comments and replies, oldest first (`order: "DESC"` for newest first). Items have `direction` (INBOUND from people, OUTBOUND from the account), `state` (VISIBLE, HIDDEN or DELETED), the author, and the text.
5. A comment is unanswered when it is INBOUND and VISIBLE and no OUTBOUND item replies to it; a reply's `parentExternalItemId` is the `externalItemId` of the comment it answers.
6. Show each comment with its post (the caption, and the link from `postPreview` when there is one), the author, the text and when it was written, and say whether a reply is possible.
7. After you have shown the user a thread, call `mark_inbox_conversation_read` for it.
## Reply
1. Draft a short reply to each comment the user wants answered, in the voice of the account and within `maxReplyLength`. Suggest hiding spam or abuse rather than answering it. Show the drafts as a numbered list so the user can change or drop any of them.
2. For each reply the user keeps, call `preview_comment_reply` with the comment's own `itemId` (the item from `list_inbox_items`, not the conversation) and the `text` exactly as the user kept it, word for word.
3. Show the previews together: for each, whose comment it is and what it says, and the exact reply that will appear under it publicly. For example:
> **Nothing is sent yet. Reply to these?**
>
> 1. **@maria_k** on your 12 Oct Reel: "Is the cafe open on Sundays?"
> Your reply: "Yes, from 9:00 to 15:00. See you there!"
>
> Reply **yes** to send, or tell me what to change.
4. After the user says yes, call `reply_to_comment` once for each previewed reply, with its `confirmToken`, `itemId` and `text`. A yes can cover every reply in the preview it answers.
5. A `confirmToken` works once and expires 15 minutes after the preview. If it has expired, preview the reply again and show it again.
Replies on Threads can't be removed through PostFast afterwards, so point that out in the preview when a reply goes to Threads.
## Instagram private reply
`preview_private_reply` and then `send_private_reply` send one private reply to an Instagram comment. It arrives in the commenter's direct messages (possibly in their message requests), so say that in the preview. It is possible only when the comment item's `canPrivateReply` is true, once per comment, and within 7 days of the comment. It goes through preview, yes and send like any reply, and it can't be unsent.
## Hide, restore or delete a comment
- **Hide or restore:** `set_inbox_item_state` with `action` HIDE or UNHIDE. Hiding takes the comment out of public view on the network, and it can be undone. Tell the user which comment you are hiding; if hiding was your suggestion, ask first.
- **Delete:** `preview_comment_deletion`, then the preview, the yes and `delete_comment`. Deleting removes the comment from the network for good. Threads doesn't support deleting; offer to hide the comment instead.
## Sort and assign
- `set_inbox_conversation_status` sets a thread to OPEN, SNOOZED or CLOSED.
- `assign_inbox_conversation` gives a thread to a workspace member by `assigneeUserId`, or unassigns it when that is left out. No tool lists members, so use an id the user gives you or one already on a conversation's `assignedToUserId`.
- Both change only PostFast; nothing changes on the network.
## When something fails
Errors come back as `inbox.*` codes, such as `replyTooLong`, `replyNotSupported`, `rateLimited`, `privateReplyAlreadySent`, `privateReplyWindowExpired` or `deleteNotSupported`. Tell the user plainly what happened. When `reply_to_comment`, `send_private_reply` or `delete_comment` says the token doesn't match, preview the action again with the exact values and show the new preview.
If a call says the connection doesn't have permission for the action yet, the user needs to reconnect PostFast and allow it; their app may offer that on its own. Then make the same call again: a `confirmToken` that was refused this way still works until it expires, so the user doesn't need to approve the same preview twice.
performance-report3.6 KB
View saved version →
---
name: performance-report
description: Summarize how the user's social media is performing from PostFast analytics, with reach, engagement and follower growth per network, the best and weakest posts, and what to post more of. Use when someone asks how their posts did last week or last month, which posts worked best, how their follower count changed, or wants a performance report for a client, a manager or their team.
---
# Report social media performance with PostFast
This skill only reads. It never creates, approves or deletes anything.
## Steps
### 1. Set the scope
- **Workspace**: if `list_workspaces` shows more than one, ask which, and pass its `id` as `workspaceId` on every call.
- **Period**: use the period the user names. "Last week" means the previous Monday to Sunday in the user's time zone; with no period given, use the last 7 full days. State the dates you used. For a trend, also fetch the period of the same length just before it.
- **Accounts**: `list_accounts` gives each account's `platform`, `platformUsername` and current `followerCount`.
### 2. Fetch the numbers
- **Posts**: `get_post_analytics` with `startDate` and `endDate` (ISO 8601), and `platforms` or `socialMediaIds` to narrow it. It returns published posts with their `latestMetric` (impressions, reach, likes, comments, shares, total interactions) and network-specific `extras`; videos add views and watch time, and Instagram adds `saveRate`, and `reelsSkipRate` on Reels. There is no paging, so ask for a month at most at a time.
- **Followers**: `get_follower_history` for each account, with `from` and `to`. It returns `currentFollowerCount`, the change over the period (`delta`) and daily points. Tracking starts when PostFast first recorded the account (`trackingStartedAt`), so there is nothing before that date.
- **What went out**: optionally, `list_posts` with `statuses` PUBLISHED and FAILED and the same `from` and `to`, to count the posts published and the ones that failed.
Numbers come back as strings: convert them before you add or compare them. A post whose `latestMetric` is null has no metrics yet; count it but leave it out of averages.
### 3. Know the coverage
- Post analytics cover Instagram, Facebook, TikTok, Threads, YouTube, LinkedIn company pages and Pinterest business accounts. X, Bluesky, Telegram, Google Business Profile and LinkedIn personal profiles have no post analytics here; say so instead of reporting zeros.
- Follower history covers Facebook Pages, Instagram, YouTube, Pinterest, Threads, Bluesky, Telegram, LinkedIn company pages and TikTok, not X or personal Facebook profiles.
### 4. Write the report
1. **Summary**: two or three sentences on the period: posts published, total reach, engagement, and follower change.
2. **By network**: a table with posts, impressions, reach, interactions, engagement rate and follower change for each account. Engagement rate is interactions divided by reach; when reach is missing, use impressions and say so. Networks count impressions differently, so compare each network with its own earlier period rather than with the others.
3. **Best posts**: the top three by engagement rate, each with its account, date, the first line of its text, its numbers, and a short guess at why it worked, worded as a guess.
4. **Weakest posts**: the bottom one or two, with the same details.
5. **Next**: two or three concrete suggestions drawn from the data, such as the formats, topics, days or times that did best.
Keep every number traceable to the data you fetched, and don't state causes as facts. If the user wants to act on the suggestions, the schedule-posts skill can plan and schedule the next posts.
repurpose-content3.5 KB
View saved version →
---
name: repurpose-content
description: Turn an article, blog post, newsletter, video transcript or web page into a series of social posts and schedule them through PostFast. Use when someone shares a link or pasted text and asks for posts about it, a week of posts from it, a launch or campaign sequence across their networks, or captions for each network from one piece of content.
---
# Turn one piece of content into a week of posts
This skill plans and drafts the posts. Creating and scheduling them follows the schedule-posts skill, so they are held until the user approves them.
## Rules
1. **Nothing is created until the user has agreed to the drafts.** Planning and drafting use no PostFast tools that change anything.
2. **Stay true to the source.** Use only facts, numbers, names and quotes that are in it, word for word where it matters. Don't invent statistics, results or testimonials. Quote people only as the source quotes them.
3. **Fit each network.** Before you draft, load the schedule-posts skill and read its platform rules (`../schedule-posts/references/platform-rules.md` from this skill's folder): text limits, required media and how links work on each network.
## Steps
### 1. Read the source
Use what the user pasted or attached, or read the page at the link they gave with your own web tools, if you have them. If you can't open it, ask the user to paste the text. Read all of it before you plan.
### 2. Settle the brief
Ask only for what you can't tell, and propose a default for the rest:
- **Accounts**: `list_accounts` shows what's connected (use `list_workspaces` first if the user has more than one workspace). Only CONNECTED accounts can be scheduled.
- **How many posts, over how long**: by default about five posts over one week.
- **Time zone and times**: the user's time zone, and the times they usually post.
- **Link and call to action**: usually the source's own link, and what readers should do next.
- **Voice**: the account's usual tone, unless the user says otherwise.
### 3. Pull out the material
Note the main point, three to five strong supporting points (a finding, a tip, a number, a quote, an example), who it is for, and the call to action.
### 4. Plan the series
Lay the posts out in a table: day and time, account, angle, and media. Give each post its own angle, such as the announcement, a key takeaway, a surprising number, a quote, a practical tip, a question to the audience, and a recap. Don't repeat an angle on the same account, spread posts to one account over different days, and start with the announcement.
### 5. Draft each post
- Write every post so it stands on its own for someone who hasn't read the source.
- Fit each draft to its network with the platform rules: length, where the link goes, hashtags.
- Networks that require media (see the platform rules) need an image or video for every post. Use media the user gives you, or ask. An image from the source itself can be used only if the user confirms they may use it.
- Show the plan and all the drafts together, and let the user change, drop or add posts. Nothing is created yet.
### 6. Schedule them
When the user is happy with the drafts, follow the schedule-posts skill from its step 4: upload the media, create the posts on hold with `create_posts` and `approvalStatus: "PENDING_APPROVAL"`, show the preview, and call `approve_posts` only after the user says yes to that preview. If nothing changed since the drafts, keep the preview short: each post's account, time and first line, and a note that the texts are the ones agreed.
schedule-posts7.8 KB
View saved version →
---
name: schedule-posts
description: Schedule and publish social media posts through PostFast, with the user's approval before anything goes out. Use when someone wants to post or schedule something on X, Instagram, Facebook, TikTok, LinkedIn, YouTube, Threads, Pinterest, Bluesky, Telegram or Google Business Profile, plan a week of content, save a draft for later, or check, fix or remove posts that are scheduled or failed.
---
# Schedule posts with PostFast
These steps use the PostFast connector's tools. PostFast holds each post you create until the user approves it, so the user sees exactly what will go out, where and when, before anything is published.
## Rules
1. **Create on hold, publish only on a yes.** Create every post with `approvalStatus: "PENDING_APPROVAL"`. Show the user the preview (step 6), and call `approve_posts` only after they say yes to it in the conversation, even when their first message asked you to post right away. A yes covers the posts as previewed; if anything changes, preview again.
2. **Only connected accounts publish.** Check each account's `connectionStatus` in `list_accounts` before you schedule to it.
3. **Fit each network.** Before you write or adapt a post, read `references/platform-rules.md` in this skill's folder: text limits, required media, and the settings each network needs.
4. **Use the user's time zone.** `scheduledAt` is ISO 8601 with a UTC offset. If you don't know the user's time zone, ask once, and show every time back in it.
## Steps
### 1. Pick the workspace
Call `list_workspaces`. With one workspace, carry on and leave `workspaceId` out. With several, use the one the user names or ask which, then pass its `id` as `workspaceId` on every call that follows, including `approve_posts`, `delete_post`, `delete_posts` and `list_posts` in later turns. Leaving it out uses the workspace the user connected, where a post from another workspace isn't found: `delete_post` then answers `deleted: false`, `delete_posts` lists it in `notFoundIds`, and `list_posts` returns nothing.
### 2. Pick the accounts
Call `list_accounts` and match what the user asked for ("our Instagram", "LinkedIn and X") by `platform`, `platformUsername` and `displayName`. If a network has more than one account, ask which one.
If an account's `connectionStatus` is DISABLED:
- Don't schedule to it; PostFast rejects that. Tell the user, and give the `disabledReason`.
- Offer a reconnect link: `generate_connect_link` with `platforms` set to that network. Whoever owns the account opens the link and signs in again. Set `sendEmail` only when the user asks you to email the link and gives the address.
- Offer to save the post as a draft in the meantime.
### 3. Write the posts
- One post per account: a post for three networks is three posts.
- When the user gives exact text, use it as given. If it's over a network's limit, say so and offer a shorter version rather than cutting it yourself.
- When you write the text, fit it to each network instead of pasting one text everywhere: its length, how hashtags, mentions and links work there, and its tone. Keep names, prices, dates and links exactly as the user gave them.
### 4. Add media
- TikTok, Instagram, Pinterest and YouTube need media, even for a draft. If the user hasn't given any, ask for it before you create anything.
- A file at a public https URL: `upload_from_url` with `sourceUrl`. For a caption file or a document, link to the file itself; a share page doesn't work.
- A file in the conversation: `upload_media`. If your app can attach the file to the tool call, pass it as `file`. Otherwise pass its bytes as base64 in `data` with its MIME type in `contentType`, which suits images of a few MB. For a video or a large file you can't attach, ask for a public https link that downloads the file, and use `upload_from_url`.
- Each upload returns a `media_id` and its `type`. Pass an IMAGE or VIDEO one as `mediaItems[].key`, with that `type` and `sortOrder` from 0. A CAPTION one (an .srt or .vtt file) goes in `controls.youtubeCaptionKey` and a DOCUMENT one (a PDF, Word or PowerPoint file) in `controls.linkedinAttachmentKey`, never in `mediaItems`; the platform rules cover both. You can use the same `media_id` in several posts.
### 5. Create the posts, held
Call `create_posts` with:
- `posts`: one entry per account, each with `socialMediaId`, `content`, and where needed `mediaItems`, `scheduledAt` and `firstComment`. Up to 15 posts per call.
- `status`: SCHEDULED, with a `scheduledAt` in the future and within a year on every post; or DRAFT, with no `scheduledAt`, to save it in PostFast without a time.
- `approvalStatus`: `"PENDING_APPROVAL"`. The connector holds every post until it is approved anyway; passing it makes that explicit.
- `controls`: the network settings from the platform rules. They apply to every post in the call, so posts that need different settings go in separate calls.
If the call is rejected, the error names the rule, for example `socialMediaDisconnected`, `contentLength.x` or `platformMedia.instagram.mediaRequired`. Fix that post and create it again. Keep the post ids from the result.
### 6. Show the preview and ask
Show every post as it will go out, then ask for a yes. For example:
> **Nothing is published yet. Shall I schedule these?**
>
> 1. **Instagram @acme**, Tue 14 Oct, 09:00 (Europe/Sofia), feed post with 1 image
> "Our autumn menu is here…" *(the full text)*
> 2. **LinkedIn Acme Ltd**, Tue 14 Oct, 09:00 (Europe/Sofia), text only
> "We're launching our autumn menu…" *(the full text)*
>
> Reply **yes** to schedule both, or tell me what to change.
Give the full text, the media, and the settings that change what people see, such as Reel or feed, a Threads topic, a Pinterest board, a LinkedIn document and its title, or YouTube captions. A draft needs no approval: say it is saved in PostFast and has no time yet.
### 7. Approve after the yes
When the user says yes to the preview, call `approve_posts` with the post ids and `approvalStatus: "APPROVED"`. Then check them with `list_posts` and `ids`: each should be SCHEDULED and APPROVED, and it publishes at its time.
- **Changes:** there is no edit. Delete the held post with `delete_post` (its `id`, and the same `workspaceId`), create the new version (step 5), and preview again.
- **No, or no answer:** leave the posts held. They stay in PostFast unpublished, where the user can review them. Delete them only if the user asks.
- **The time has passed:** approved less than 2 hours late, the post goes out within about a minute. Past 2 hours, don't approve it: tell the user, and only if they agree, create it again with a new time and delete the old one.
## "Post it now"
PostFast has no publish-now. Schedule the post about 5 minutes ahead and say so in the preview. If the yes arrives after that time, the post goes out right after approval (step 7).
## Check, fix or remove posts
- `list_posts` filters by `statuses` (DRAFT, SCHEDULED, PUBLISHED, FAILED), `platforms`, accounts (`socialMediaIds`, the `id`s from `list_accounts`), `from` and `to`, or `ids`, up to 50 per page.
- A FAILED post has a `lastError`. MISSED_DISCONNECTED means its account was disconnected when it was due: reconnect the account (step 2), then create the post again. MISSED_NOT_PUBLISHED means it passed its time by more than 2 hours without going out. Other errors are usually media the network refused.
- Each post shows its settings in `controls`. Only the field for the post's own network means anything; the others can hold defaults.
- `delete_post` removes a post from PostFast and stops a scheduled post from going out. To remove several, pass up to 100 ids to `delete_posts` in one call; it returns `deletedIds` and `notFoundIds`. Neither removes a post that was already published: that stays on the network until the user deletes it there, so say so. Deleting can't be undone, so confirm first: list every post you are about to delete.
Referenced files: 1 — file references are metadata, not package contents.