Skip to content

Founder posts

Each week, three posts in your voice for LinkedIn and X, written from what you shipped and learned, every number from a record.

Kind
Agent task
Price
6.2¢ per 3 posts
Your time
12 minutes
Approval
Runs on its own
Post.write
You, to your agent

Write three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first.

curl -X POST "https://api.sb/leaseline.app/posts/write?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"goal":"Write three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first.","budget":{"amount":0.5,"currency":"USD"}}'
npx startup-builder do Post.write --try --data '{"goal":"Write three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first.","budget":{"amount":0.5,"currency":"USD"}}'
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Post.write({ goal: 'Write three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first.', budget: { amount: 0.5, currency: 'USD' } })"
  }
}
import { $ } from 'startup-builder'

const result = await $.try.Post.write({ goal: 'Write three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first.', budget: { amount: 0.5, currency: 'USD' } })
Response
{
  "mode": "try",
  "stored": false,
  "estimate": "About 6.2¢ per 3 posts",
  "sample": {
    "account": "LinkedIn",
    "at": "Mon 08:30",
    "topic": "the $100 message test",
    "source": "experiments/exp_9",
    "status": "scheduled"
  }
}
Try mode reads, stores nothing and spends nothingAPI referenceIts Nouns

What you get

  • 3 posts · Each week, three posts in your voice for LinkedIn and X, written from what you shipped and learned, every number from a record. · Post
  • posts[] · Each post: the account, when it goes up, the text, and the record it came from.
  • held[] · posts that failed the grade twice, with the finding.
  • skipped · Topics left out, such as a change with no user-facing effect.

Connect once: LinkedIn, X account. How long: Minutes; posts go up through the week.

Trigger

It runs weekly at 08:00 on the first weekday.

TypeScript
every('mon 08:00', ($) => $.Post.write({ handles: ['linkedin:founder', 'x:founder'], perWeek: 3 }))

Steps

Your agent does these steps, one row per step; each step’s check is part of its row and its price.

StepVerbReturnsPriceApproval
1. Read the week’s materialCollection.queryCall notes, shipped changes, answers that worked and the latest test readoutFreeRuns on its own
2. Choose three topicsContent.draftThree topics a buyer would stop for, each tied to one recordAbout 0.2¢Runs on its own
3. Write each LinkedIn postContent.draftA post per topic, in your voice, with the record’s numbersAbout 3¢Runs on its own
4. Cut each into an X versionContent.draftThe same point in X’s length, with the link in a replyAbout 3¢Runs on its own
5. Schedule them on your accountsPost.scheduleEach post scheduled at the account’s best slotFreeRuns on its own

Calls: Collection.query, then Content.draft, then Post.schedule.

About 6.2¢ per 3 posts, each time it runs, capped at 25¢.

Example: give it a goal

Write three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first.

The plan it shows runs 5 steps, priced before it spends anything; Run it above shows the result it returns.

When something fails

Each failure, and what happens next
WhenThen
The week has no new materialNothing is scheduled and the readout says so; it never invents a topic.
A post fails the gradeIt is rewritten once; a second failure holds it with the finding, and it is not billed.
An account needs signing in againScheduling stops on that account with the fix line; the others go ahead.
You call it twice in one weekThe week’s posts are returned: it is idempotent per handle, ISO week and slot.

Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-post-write-1-<step>-<item>.

How it is graded

A second model reads each post beside your last 20 posts and the record it cites. It passes when it reads as you on the voice samples, every number matches its record, and it makes one point. A miss is redone at no charge.

Change it

AskCompiles to
Only LinkedIn, and only from what I shipped.Post.write
Harvest the people who comment, two days after each post.Audience.harvest
Turn the best post into a page on my site.Page.answer
TypeScript
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'post-write',
  verb: 'Post.write',
  input: { handles: 'string[]', perWeek: 'integer', from: "('calls' | 'changes' | 'answers' | 'experiments')[]" },
  trigger: { schedule: 'mon 08:00' },
  maxCost: 0.25,
  grade: { evaluator: 'your last 20 posts; the cited record', passWhen: 'reads as you; every number matches; one point', remedy: 'redo' },
  execute: async (ctx, { handles = ['linkedin:founder', 'x:founder'], perWeek = 3, from = ['calls', 'changes', 'answers', 'experiments'] }) => {
    const week = await ctx.step('source', () => $.Collection.query({ from, since: '7d' }))
    if (!week.rows.length) return { posts: [], skipped: 'nothing new this week' }
    const posts = await ctx.step('write', () => $.Content.draft({ kind: 'founder-posts', from: week.rows, count: perWeek, handles, maxCost: 0.1 }))
    return ctx.step('schedule', () => $.Post.schedule({ posts: posts.map((p) => p.$id), slots: 'best' }))   // graded before it schedules
  },
})

Extend it with extends: 'Post.write' and base(), or compose your own from these steps.

Works with

Plays that order it: Reuse what you already published, Build in public, Category kit, Founder voice, Organic social, Owned newsletter.

It serves Publish and post. It deepens Content marketing.

For agents

For agents: the guide, its approvals, retries and lookups
FactValue
GuidePost.write
Guide approvallimits
GoalWrite three LinkedIn posts this week from what I shipped, spend up to 50¢, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval.
Triggerevery('mon 08:00', ($) => $.Post.write({ handles: ['linkedin:founder', 'x:founder'], perWeek: 3 }))
RetryThree times with backoff, then the next route; the same idempotency key never charges, sends or posts twice
Idempotency keyleaseline-post-write-1
LookupsA find: input asks unless exactly one record fits
Step
1. Read the week’s material
2. Choose three topics
3. Write each LinkedIn post
4. Cut each into an X version
5. Schedule them on your accounts

The amounts live once, on the hub (approvals).

Who does each step, and how it is checked
StepFunctionDoerCheckerAssuranceInputs
1. Read the week’s materialcodeCodeCode checks each result against its declared typemeasured$0.from
2. Choose three topicsagenticThe Content lead agentA second model grades the outputgraded$1
3. Write each LinkedIn postagenticThe Content lead agentA second model grades the outputgraded$2.topics, $0.voice
4. Cut each into an X versionagenticThe Content lead agentAdversarial review by a second model: Pass, or the claim cutgraded$3.posts
5. Schedule them on your accountscodeCodeCode reads the result back from where it landedmeasured$4.passed, $0.handles

The doer is never the checker, and the weakest assurance on the path is the whole call’s.

Under the hood

Under the hood: the Systems, Nouns and Events it touches
KindWhat it touches
SystemsSites and content, Social
NounsCollection, Content, Action, Post
EventsCollection.queried, Content.drafted, Action.evaluated, Post.scheduled

Reference

Inputs, outputs, its Event and its errors
NameTypeDefaultMeaning
handlesstring[]['linkedin:founder', 'x:founder']The accounts it posts as.
perWeekinteger3Posts a week, at most. Fewer when the week had less to say.
from('calls' | 'changes' | 'answers' | 'experiments')[]['calls', 'changes', 'answers', 'experiments']Where topics come from: call notes, shipped changes, answers that worked, test readouts.
voiceFileyour last 20 postsSamples of how you write; the voice grade reads against them.
maxCostnumber0.25The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link.

Emits Post.written. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).

Contents