Run Sponsor Pipeline from your own code
Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page sizes the list backward from the goal, checks the budget window, scores every prospect, picks its channel and title, holds follow-ups to the cap and names the top targets with the next message each is owed - all free, in pipekit.js. The run writes the plan or the messages; the page then holds the reply to its own figures and rules (pipereply.js).
Base URL and the response shape
Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response has one shape:
{ "ok": true, "data": { ... } }
{ "ok": false, "error": { "code": "...", "message": "..." } }
The token is minted for this app (the guest call takes {"slug":"sponsor-pipeline"}), so no slug header is needed afterwards. Send it as Authorization: Bearer …. The run body is the input object, sent bare.
| Status | Code | Meaning |
|---|---|---|
| 400 | validation_error | The body is not a JSON object, or a required key (task, event, prospects, facts) is missing. |
| 401 | unauthorized | No token, or a stale one. Mint a guest token or sign in again. |
| 402 | insufficient_credits | The balance is under min_credits. Price with /estimate first. |
| 403 | forbidden | A guest token tried to run: both lanes are metered and need a personal sign-in. |
| 404 | not_found | Unknown job id. |
| 429 | rate_limited | Back off and retry. |
| 5xx | server_error | Transient. Retry with the same Idempotency-Key so a retry never double-bills. |
The task field comes first
Two lanes - plan (the outreach plan for the organizers) and emails (the next message each top target is owed). A missing or unknown task is answered as plan. Both lanes send the same four fields.
The input
| Field | Required | What |
|---|---|---|
task | yes | plan or emails. If it is missing or neither, do plan and set "task": "plan". |
event | yes | the event, the goal and its rates, the team, the program's sponsor-facing activities and which inputs exist. |
prospects | yes | every prospect with segment, motivation, fit, signal, warm path, stage, follow-ups, opt-out, history, liaison, source, and the page's score, channel and title to target; the top targets are marked with their rank. |
facts | yes | the backward math, the timing, the top targets in rank order (this order is the page's order for the top targets) with the next message each is owed, the source, channel and cadence menus with their picks, the checks, the signals and every finding tagged [fix], [check] or [info], most urgent first. |
retry_note | no | optional; if present, your previous reply was unusable - follow it. |
The rules the model applies
- Size the list backward: net-new goal / average package = sponsors needed; / close rate = prospects to pitch; / reply rate = the target list; source 2-3 times that. Both rates are self-set assumptions - event sponsorship publishes no benchmark of its own, and the usual 9-15% reply and 20-30% close figures are B2B SaaS sales numbers. Last edition's sponsors belong to the renewal motion, never to this list.
- Outreach starts at roughly T-8 months, because larger sponsors lock budgets in the previous financial year; under T-8 the window is closing, and six weeks out is almost always too late.
- Score Hot (strong fit, a fresh buying signal, a reachable path), Warm (fit, a softer signal), Cold (loose fit or no signal), Skip (no audience overlap). Every claim carries a source; public business contact channels only - a purchased or scraped list is out. Diversify across startups, midsized companies and enterprises.
- First touch: a warm intro through someone who knows someone inside is the default - exhaust it per target first; where no path exists, a referral ask to someone senior asking only who the right person is, never a pitch; inbound broadcast stays always on but is never the plan; a cold email sequence only when warm paths cannot reach enough targets. Target the title by motivation: Developer Relations for product feedback, Recruiting or HR for hiring, Marketing or PR for brand, the CEO when unknown.
- The first email carries no links, no attachments and no images - corporate phishing filters auto-trash it. It gives the event basics (size, place, dates), what the format is in plain words, one sponsor-specific angle, one differentiator, a low-friction request to talk at a specific proposed time, and a specific subject line rather than "Event and Company Partnership".
- The exploratory call comes before the prospectus and is needs discovery, not a pitch. The proposal goes out the same day, ties to the need heard, names only activities the program already contains, and carries a deadline.
- Prepare before any call: the fixed sponsor questions (projected attendance, aggregate audience composition, per-level benefits, logistics) answered in advance, and an answer ready for each of the four sponsor concerns - attendee value, co-sponsor mix, package value and organizer competence. "We don't see the value" is a discovery signal, not a price objection.
- Follow-ups: 1-2 weeks apart, at most 3 (tighten to 3-4 days only close to the event); the angle-rotation sequence (at most 4, each with a genuinely new angle, the last a breakup email naming the silence) only with a dedicated lead, a large list and a revenue gap. The repeated "just checking in" bump is deleted. An opt-out is honored at once, mid-sequence.
- A lapsed or released sponsor re-enters at the exploratory call - never pitched as if it had never met the event. A community-run event never promises attendee lists or purchasable talk slots. One named liaison per relationship, one shared pipeline. On a yes: invoice immediately, confirm amount and payment method in writing, verify the receiving account.
House rules
- Use only the input and the rules above. The page's companies, scores, channels, counts and picks are exact - copy them. Every number in a sentence must appear in the input or in the rules above.
- Label anything that is not one of the rules above, and is not in the input, as your own design.
- Never invent a person, a company fact, a statistic, a date, a price or a commitment; where one must be named and is not, write "to be named". Refer to people by name or as they - never infer anyone's gender from a name.
- Never use backticks, never refer to this input's fields by their key names in a sentence, and never copy this prompt's narrative wording into a reply.
- Reply with ONLY one JSON object - no prose before or after, no code fences.
The replies
plan
summary- one sentence, at most 35 words: the most urgent finding and the first move.math-sponsors(the page's sponsors needed),pitch(prospects to pitch),list(the target list),note(one sentence: the coverage gap and that both rates are self-set).timing- one sentence on the budget window, as the page says.top- one object per top target in the page's order:company(exactly),why(one short sentence: why it goes first, from its fit, signal and path),channel(the page's:warm,referralorreentry),title(the page's title to target),next(the page's next message:intro,referral,reentry,followuporproposal).channels-pick(the page's default first-touch channel),note(one sentence: what the warm paths reach and when the cold sequence comes in).cadence-pick(standardorrotation, the page's),cap(the page's cap),note(one sentence).prep- 2 to 4 short strings: what to have ready before the next calls (the fixed sponsor questions, the four sponsor concerns, the proposal inputs), only from the input and the rules above.checks- one object per outreach check in the page's order:check(the page's short name, exactly),pass(true or false, as the page says).signals- 2 or 3 short strings, the page's signals, each with what it would change next edition.caveats- at most 4 short strings:[fix]findings first in the page's order (the first four when there are more), then[check]findings in the page's order.[]when there are none of either.
{
"task": "plan",
"summary": "one sentence",
"math": { "sponsors": 8, "pitch": 32, "list": 97, "note": "one sentence" },
"timing": "one sentence",
"top": [ { "company": "a company", "why": "one short sentence", "channel": "warm", "title": "a title", "next": "intro" } ],
"channels": { "pick": "warm", "note": "one sentence" },
"cadence": { "pick": "standard", "cap": 3, "note": "one sentence" },
"prep": [ "a thing to have ready" ],
"checks": [ { "check": "Timing", "pass": true } ],
"signals": [ "what to record and what it changes" ],
"caveats": [ "a caveat" ]
}
The page holds it to its own figures: the backward math, every top target in order with its channel and next message, the channel and cadence picks with the cap, and the checks; no figure may appear that the input does not hold.
emails
messages- one object per top target in the page's order:company(exactly),kind(the page's next message:intro,referral,reentry,followuporproposal),to(who receives it: the connector for an intro - "to be named" when the page names nobody - someone senior at the company for a referral ask, otherwise the page's title to target),subject(specific, never "Event and Company Partnership"),body(the message, at most 150 words, signed by the page's liaison for that prospect, or by the event's team when there is none).note- one sentence, at most 30 words, for the organizers: what to settle before these go out.
{
"task": "emails",
"messages": [ { "company": "a company", "kind": "referral", "to": "someone senior", "subject": "a specific subject", "body": "the message" } ],
"note": "one sentence"
}
The page requires one message per top target in order, each of the kind it is owed: no link, web address or attachment in a first touch, no pitch in a referral ask, no bump in a follow-up, a deadline in a proposal, an acknowledged past in a re-entry note, and no activity the program lacks.
Worked examples - every lane, every sample
These are the page's three free samples (fictional events, companies and people; every figure is illustrative). Each input is exactly what the page sends; each reply is the saved reply the sample replays, shipped as the validating model wrote it; the last line is the page's own check. Every sample has both lanes.
Harborline Python (a community conference, 11 months out) - plan
8 sponsors needed, a list of 97, 6 in play; 11 months out; 4 top targets; sponsor-standard cadence; 3 of 6 checks.
Input:
{
"task": "plan",
"event": "Event: Harborline Python in Lisbon, October 14-15; attendance 450; community-run; 11 months out\nGoal: sponsorship revenue 60,000; renewals expected 20,000; average package 5,000; self-set close rate 25%, reply rate 33%\nTeam: volunteer organizers with a few hours a week; sponsors as multi-edition relationships; shared pipeline tool yes; contact list built by the team\nProgram: hiring corner yes; hands-on feedback session no; opt-in demo space no\nInputs: value proposition yes; prospectus yes; rate card yes; the fixed sponsor questions answered no",
"prospects": "Prospects, in order (company | segment | motivation | fit | signal | warm path | stage | follow-ups | opted out | history | liaison | source | score | channel | title to target):\n1. Quayside Data | midsized | hiring | strong | fresh | warm | call | 1 | no | new | Ana | yes | hot | warm | Recruiting, Talent Acquisition or HR | TOP TARGET #1\n2. Tidewell Cloud | enterprise | feedback | strong | fresh | none | first touch | 2 | no | new | NONE | yes | hot | referral | Developer Relations or a Developer Advocate | TOP TARGET #3\n3. Brindlewick | startup | hiring | some | old | none | first touch | 5 | no | new | NONE | yes | warm | referral | Recruiting, Talent Acquisition or HR\n4. Saltmarsh Labs | startup | brand | strong | fresh | warm | identified | 0 | no | new | NONE | yes | hot | warm | Marketing, PR or a relevant employee resource group | TOP TARGET #2\n5. Corvo Analytics | midsized | hiring | some | fresh | none | first touch | 1 | yes | new | NONE | yes | warm | referral | Recruiting, Talent Acquisition or HR\n6. Atlantic Ledger | enterprise | unknown | loose | none | none | identified | 0 | no | new | NONE | NONE | cold | referral | the CEO\n7. Pinecrest Tools | midsized | feedback | some | old | warm | first touch | 1 | no | lapsed | Rui | yes | warm | reentry | Developer Relations or a Developer Advocate | TOP TARGET #4\n8. Marlow Systems | enterprise | brand | strong | fresh | none | identified | 0 | no | last | NONE | yes | renewal | renewal | Marketing, PR or a relevant employee resource group\n9. Gullwing Games | startup | unknown | none | none | none | identified | 0 | no | new | NONE | NONE | skip | none | the CEO",
"facts": "Backward math: net-new goal 40,000 / average package 5,000 = 8 sponsors needed; / 25% close = 32 prospects to pitch; / 33% reply = a target list of 97; source 194-291 names; prospects in play 6 (committed, signed, lost, opted-out, skipped and renewal prospects are not in play)\nTiming: 11 months out - inside the T-8 window\nTop targets, in order, with the next message each is owed: Quayside Data (hot, warm; next: the proposal, same day as the call); Saltmarsh Labs (hot, warm; next: a warm-intro request to the connector); Tidewell Cloud (hot, referral; next: follow-up 3 of 3); Pinecrest Tools (warm, reentry; next: follow-up 2 of 3)\nTarget-list sources: Previous-sponsor roster default; Organizer-network employers available; Adjacent-event sponsor scan available; Institutional channels available; Attendee-stack vendor mapping not yet\nFirst-touch channel: the page's default is warm; rungs Warm intro default; Referral ask available; Inbound broadcast always on; Cold email sequence promoted; Purchased or scraped lists deleted\nFollow-up cadence: the page's pick is standard (cap 3 follow-ups); rungs Sponsor-standard cadence default; Angle-rotation sequence not yet; the repeated just-checking-in bump deleted\nChecks (3 of 6): Timing (Net-new outreach starts at or before roughly T-8 months) passed; Coverage (Prospects in play cover the backward-sized target list) MISSING; Warm first (Every target had its warm-path check before anything colder) passed; Cadence cap (No prospect past the follow-up cap, and every opt-out honored at once) MISSING; Evidence (Every scored prospect carries a source for its claims) MISSING; Ownership (One named liaison for every prospect past the first touch, in one shared pipeline) passed\nSignals to record: Pipeline coverage: prospects in play against the backward-sized list (self-set); Stage conversion per channel - first touch to call, call to proposal, proposal to close - with lapsed sponsors tagged apart (self-set); Objection recurrence by segment, routed to the value proposition\nFindings (15):\n[fix] optout (cadence): Opted out but still in the sequence: Corvo Analytics - remove them now, mid-sequence.\n[fix] past_cap (cadence): Past the cap of 3 follow-ups: Brindlewick (5) - move on; every touch past the cap costs more goodwill than it recovers.\n[fix] links (channel): First email with links, attachments or images: Pinecrest Tools - corporate phishing filters auto-trash it; save the prospectus and every link for the follow-up.\n[check] over_promise (program): The program has no hands-on feedback session (wanted by Tidewell Cloud, Pinecrest Tools) - pitch the program as it stands; route the missing activity to the program owners.\n[check] coverage (math): 6 prospects in play for a backward-sized list of 97 - source 194-291 names to qualify down from; a shortfall at the list stage predicts a shortfall at close.\n[check] no_source (evidence): No source for: Atlantic Ledger - every qualification claim carries a source URL and a date.\n[check] checklist (objections): Answer the fixed sponsor questions before outreach - projected attendance, aggregate audience composition, per-level benefits, logistics; a sponsor who has to chase them reads the event as poorly run.\n[check] checks (measurement): Outreach checks: 3 of 6 (all self-set).\n[info] rates (math): The 25% close and 33% reply rates are self-set assumptions - event sponsorship publishes no benchmark of its own; replace them with this event's observed rates edition over edition.\n[info] net_new (math): Renewals expected at 20,000 stay with the renewal motion - the net-new goal is 40,000.\n[info] skipped (list): Skipped (no audience overlap): Gullwing Games.\n[info] cold_up (channel): Warm paths reach 3 prospects against 32 to pitch - the cold email sequence is promoted for targets no one in the network reaches, after the referral ask.\n[info] renewal (channel): Marlow Systems sponsored last edition - left to the renewal motion, not this pipeline.\n[info] lapsed (channel): Pinecrest Tools re-enters at the exploratory call, tagged lapsed - never cold-pitched as if new.\n[info] honesty (program): Community-run: never promise attendee lists or purchasable talk slots - the sponsor buys access to a qualified audience, never its contact data."
}
Reply:
{
"task": "plan",
"summary": "The most urgent finding is that Corvo Analytics has opted out but remains in the follow-up sequence, so the first move is removing them from outreach immediately.",
"math": {
"sponsors": 8,
"pitch": 32,
"list": 97,
"note": "Only 6 prospects are in play against a backward-sized list of 97, and both the 25% close rate and the 33% reply rate are self-set assumptions."
},
"timing": "At 11 months out, the event is inside the roughly T-8-month budget window for outreach.",
"top": [
{
"company": "Quayside Data",
"why": "Strong fit, a fresh signal and a warm path ready to use.",
"channel": "warm",
"title": "Recruiting, Talent Acquisition or HR",
"next": "proposal"
},
{
"company": "Saltmarsh Labs",
"why": "Strong fit, a fresh signal and a warm path in place.",
"channel": "warm",
"title": "Marketing, PR or a relevant employee resource group",
"next": "intro"
},
{
"company": "Tidewell Cloud",
"why": "Strong fit and a fresh signal, with no warm path, reached instead through a referral ask.",
"channel": "referral",
"title": "Developer Relations or a Developer Advocate",
"next": "followup"
},
{
"company": "Pinecrest Tools",
"why": "Some fit and an older signal, but a warm path back in as a lapsed sponsor.",
"channel": "reentry",
"title": "Developer Relations or a Developer Advocate",
"next": "followup"
}
],
"channels": {
"pick": "warm",
"note": "Warm paths reach 3 of the 32 prospects to pitch, and the cold email sequence comes in only after the referral ask, for whoever is left."
},
"cadence": {
"pick": "standard",
"cap": 3,
"note": "The standard cadence caps follow-ups at 3, but Brindlewick is already past that cap and Corvo Analytics remains in the sequence despite opting out."
},
"prep": [
"The fixed sponsor questions - projected attendance, aggregate audience composition, per-level benefits, logistics - since none are answered yet.",
"An answer ready for each of the four sponsor concerns: attendee value, co-sponsor mix, package value and organizer competence.",
"The proposal inputs already on hand: the value proposition, the prospectus and the rate card."
],
"checks": [
{
"check": "Timing",
"pass": true
},
{
"check": "Coverage",
"pass": false
},
{
"check": "Warm first",
"pass": true
},
{
"check": "Cadence cap",
"pass": false
},
{
"check": "Evidence",
"pass": false
},
{
"check": "Ownership",
"pass": true
}
],
"signals": [
"Pipeline coverage against the backward-sized list - would recalibrate next edition's self-set close and reply rates.",
"Stage conversion per channel, with lapsed sponsors tagged apart - would show which channel to favor next edition.",
"Objection recurrence by segment, routed to the value proposition - would show which pitch to revise next edition."
],
"caveats": [
"Corvo Analytics opted out but is still in the follow-up sequence - remove them now, mid-sequence.",
"Brindlewick is past the cap of 3 follow-ups (5) - move on.",
"Pinecrest Tools' first email carried links, attachments or images - save the prospectus and every link for the follow-up.",
"The program has no hands-on feedback session, wanted by Tidewell Cloud and Pinecrest Tools - pitch the program as it stands."
]
}
The page's check: kept - nothing to flag
Harborline Python (a community conference, 11 months out) - emails
8 sponsors needed, a list of 97, 6 in play; 11 months out; 4 top targets; sponsor-standard cadence; 3 of 6 checks.
Input:
{
"task": "emails",
"event": "Event: Harborline Python in Lisbon, October 14-15; attendance 450; community-run; 11 months out\nGoal: sponsorship revenue 60,000; renewals expected 20,000; average package 5,000; self-set close rate 25%, reply rate 33%\nTeam: volunteer organizers with a few hours a week; sponsors as multi-edition relationships; shared pipeline tool yes; contact list built by the team\nProgram: hiring corner yes; hands-on feedback session no; opt-in demo space no\nInputs: value proposition yes; prospectus yes; rate card yes; the fixed sponsor questions answered no",
"prospects": "Prospects, in order (company | segment | motivation | fit | signal | warm path | stage | follow-ups | opted out | history | liaison | source | score | channel | title to target):\n1. Quayside Data | midsized | hiring | strong | fresh | warm | call | 1 | no | new | Ana | yes | hot | warm | Recruiting, Talent Acquisition or HR | TOP TARGET #1\n2. Tidewell Cloud | enterprise | feedback | strong | fresh | none | first touch | 2 | no | new | NONE | yes | hot | referral | Developer Relations or a Developer Advocate | TOP TARGET #3\n3. Brindlewick | startup | hiring | some | old | none | first touch | 5 | no | new | NONE | yes | warm | referral | Recruiting, Talent Acquisition or HR\n4. Saltmarsh Labs | startup | brand | strong | fresh | warm | identified | 0 | no | new | NONE | yes | hot | warm | Marketing, PR or a relevant employee resource group | TOP TARGET #2\n5. Corvo Analytics | midsized | hiring | some | fresh | none | first touch | 1 | yes | new | NONE | yes | warm | referral | Recruiting, Talent Acquisition or HR\n6. Atlantic Ledger | enterprise | unknown | loose | none | none | identified | 0 | no | new | NONE | NONE | cold | referral | the CEO\n7. Pinecrest Tools | midsized | feedback | some | old | warm | first touch | 1 | no | lapsed | Rui | yes | warm | reentry | Developer Relations or a Developer Advocate | TOP TARGET #4\n8. Marlow Systems | enterprise | brand | strong | fresh | none | identified | 0 | no | last | NONE | yes | renewal | renewal | Marketing, PR or a relevant employee resource group\n9. Gullwing Games | startup | unknown | none | none | none | identified | 0 | no | new | NONE | NONE | skip | none | the CEO",
"facts": "Backward math: net-new goal 40,000 / average package 5,000 = 8 sponsors needed; / 25% close = 32 prospects to pitch; / 33% reply = a target list of 97; source 194-291 names; prospects in play 6 (committed, signed, lost, opted-out, skipped and renewal prospects are not in play)\nTiming: 11 months out - inside the T-8 window\nTop targets, in order, with the next message each is owed: Quayside Data (hot, warm; next: the proposal, same day as the call); Saltmarsh Labs (hot, warm; next: a warm-intro request to the connector); Tidewell Cloud (hot, referral; next: follow-up 3 of 3); Pinecrest Tools (warm, reentry; next: follow-up 2 of 3)\nTarget-list sources: Previous-sponsor roster default; Organizer-network employers available; Adjacent-event sponsor scan available; Institutional channels available; Attendee-stack vendor mapping not yet\nFirst-touch channel: the page's default is warm; rungs Warm intro default; Referral ask available; Inbound broadcast always on; Cold email sequence promoted; Purchased or scraped lists deleted\nFollow-up cadence: the page's pick is standard (cap 3 follow-ups); rungs Sponsor-standard cadence default; Angle-rotation sequence not yet; the repeated just-checking-in bump deleted\nChecks (3 of 6): Timing (Net-new outreach starts at or before roughly T-8 months) passed; Coverage (Prospects in play cover the backward-sized target list) MISSING; Warm first (Every target had its warm-path check before anything colder) passed; Cadence cap (No prospect past the follow-up cap, and every opt-out honored at once) MISSING; Evidence (Every scored prospect carries a source for its claims) MISSING; Ownership (One named liaison for every prospect past the first touch, in one shared pipeline) passed\nSignals to record: Pipeline coverage: prospects in play against the backward-sized list (self-set); Stage conversion per channel - first touch to call, call to proposal, proposal to close - with lapsed sponsors tagged apart (self-set); Objection recurrence by segment, routed to the value proposition\nFindings (15):\n[fix] optout (cadence): Opted out but still in the sequence: Corvo Analytics - remove them now, mid-sequence.\n[fix] past_cap (cadence): Past the cap of 3 follow-ups: Brindlewick (5) - move on; every touch past the cap costs more goodwill than it recovers.\n[fix] links (channel): First email with links, attachments or images: Pinecrest Tools - corporate phishing filters auto-trash it; save the prospectus and every link for the follow-up.\n[check] over_promise (program): The program has no hands-on feedback session (wanted by Tidewell Cloud, Pinecrest Tools) - pitch the program as it stands; route the missing activity to the program owners.\n[check] coverage (math): 6 prospects in play for a backward-sized list of 97 - source 194-291 names to qualify down from; a shortfall at the list stage predicts a shortfall at close.\n[check] no_source (evidence): No source for: Atlantic Ledger - every qualification claim carries a source URL and a date.\n[check] checklist (objections): Answer the fixed sponsor questions before outreach - projected attendance, aggregate audience composition, per-level benefits, logistics; a sponsor who has to chase them reads the event as poorly run.\n[check] checks (measurement): Outreach checks: 3 of 6 (all self-set).\n[info] rates (math): The 25% close and 33% reply rates are self-set assumptions - event sponsorship publishes no benchmark of its own; replace them with this event's observed rates edition over edition.\n[info] net_new (math): Renewals expected at 20,000 stay with the renewal motion - the net-new goal is 40,000.\n[info] skipped (list): Skipped (no audience overlap): Gullwing Games.\n[info] cold_up (channel): Warm paths reach 3 prospects against 32 to pitch - the cold email sequence is promoted for targets no one in the network reaches, after the referral ask.\n[info] renewal (channel): Marlow Systems sponsored last edition - left to the renewal motion, not this pipeline.\n[info] lapsed (channel): Pinecrest Tools re-enters at the exploratory call, tagged lapsed - never cold-pitched as if new.\n[info] honesty (program): Community-run: never promise attendee lists or purchasable talk slots - the sponsor buys access to a qualified audience, never its contact data."
}
Reply:
{
"task": "emails",
"messages": [
{
"company": "Quayside Data",
"kind": "proposal",
"to": "Recruiting, Talent Acquisition or HR",
"subject": "Quayside Data proposal: Harborline Python hiring corner",
"body": "Hello,\n\nThank you for the call today. As promised, here is the proposal the same day.\n\nHarborline Python is a 450-attendee, community-run Python conference in Lisbon, October 14-15. Based on the hiring goal you described, this proposal centers on our hiring corner, which puts Quayside Data in front of attendees actively working in Python. It includes only the activities our program already runs this year; nothing beyond that is added.\n\nThe attached prospectus and rate card cover the full package and benefits. We would like to confirm by a date to be named, so we can finalize ahead of other sponsor conversations already underway.\n\nHappy to answer any questions in the meantime.\n\nBest,\nAna"
},
{
"company": "Saltmarsh Labs",
"kind": "intro",
"to": "to be named",
"subject": "Introduction to Saltmarsh Labs for Harborline Python?",
"body": "Hello,\n\nWe're organizing Harborline Python and hoped you might help us connect with Saltmarsh Labs.\n\nHarborline Python is a 450-attendee, community-run Python conference in Lisbon, taking place October 14-15. We think Saltmarsh Labs could be a strong sponsor fit this year, and we would value the chance to connect with the right person there.\n\nWould you be willing to make that introduction, or point us to who we should ask instead? No pressure if this isn't something you're able to help with.\n\nThank you for considering it.\n\nBest,\nHarborline Python Team"
},
{
"company": "Tidewell Cloud",
"kind": "followup",
"to": "Developer Relations or a Developer Advocate",
"subject": "Follow-up 3 of 3: Harborline Python materials now ready",
"body": "Hello,\n\nThis is follow-up 3 of 3 about sponsoring Harborline Python, our 450-attendee community-run Python conference in Lisbon, October 14-15.\n\nSince we last wrote, we've finalized this year's prospectus and sponsor value proposition, so we can now show exactly how a sponsorship lines up with the developer feedback interest you mentioned, using only the activities the program actually runs this year.\n\nWould you have time for a short call? If this isn't the right moment, just let us know and we'll step back rather than keep following up.\n\nBest,\nHarborline Python Team"
},
{
"company": "Pinecrest Tools",
"kind": "followup",
"to": "Developer Relations or a Developer Advocate",
"subject": "Follow-up 2 of 3: the Harborline Python prospectus for Pinecrest Tools",
"body": "Hello,\n\nThis is follow-up 2 of 3 for Pinecrest Tools on Harborline Python. It's good to be back in touch - we know Pinecrest Tools has sponsored Harborline Python before, and we'd welcome having you back for this edition.\n\nNow that we're past the first note, here is the prospectus we held back earlier, with full detail on this year's program and packages. The program runs as described in it; we haven't added a feedback session this time, so we want to be upfront about that rather than suggest otherwise.\n\nCould we find a short time to talk about what would make this edition work for Pinecrest Tools?\n\nBest,\nRui"
}
],
"note": "Confirm answers to the fixed sponsor questions before the Tidewell Cloud and Pinecrest Tools calls, since they remain unanswered."
}
The page's check: kept - nothing to flag
Gophers Night Krakow (a first edition in a series, 5 months out) - plan
4 sponsors needed, a list of 35, 5 in play; 5 months out; 3 top targets; sponsor-standard cadence; 2 of 6 checks.
Input:
{
"task": "plan",
"event": "Event: Gophers Night Krakow in Krakow, March 20; attendance 120; community-run; 5 months out; first edition of a series\nGoal: sponsorship revenue 6,000; renewals expected 0; average package 1,500; self-set close rate 30%, reply rate 40%\nTeam: volunteer organizers with a few hours a week; sponsors as one-off sales; shared pipeline tool no; contact list built by the team\nProgram: hiring corner no; hands-on feedback session no; opt-in demo space no\nInputs: value proposition no; prospectus no; rate card yes; the fixed sponsor questions answered yes",
"prospects": "Prospects, in order (company | segment | motivation | fit | signal | warm path | stage | follow-ups | opted out | history | liaison | source | score | channel | title to target):\n1. Vistula Soft | midsized | hiring | strong | fresh | warm | identified | 0 | no | new | NONE | yes | hot | warm | Recruiting, Talent Acquisition or HR | TOP TARGET #1\n2. Wawel Payments | enterprise | brand | some | old | none | identified | 0 | no | new | NONE | yes | warm | referral | Marketing, PR or a relevant employee resource group | TOP TARGET #3\n3. Kopiec Dev | startup | unknown | some | none | none | identified | 0 | no | new | NONE | NONE | cold | referral | the CEO\n4. Rynek Cloud | enterprise | hiring | strong | fresh | none | identified | 0 | no | new | NONE | yes | hot | referral | Recruiting, Talent Acquisition or HR | TOP TARGET #2\n5. Smok Studio | startup | brand | loose | old | none | identified | 0 | no | new | NONE | yes | cold | referral | Marketing, PR or a relevant employee resource group",
"facts": "Backward math: net-new goal 6,000 / average package 1,500 = 4 sponsors needed; / 30% close = 14 prospects to pitch; / 40% reply = a target list of 35; source 70-105 names; prospects in play 5 (committed, signed, lost, opted-out, skipped and renewal prospects are not in play)\nTiming: 5 months out - past T-8, the budget window is closing\nTop targets, in order, with the next message each is owed: Vistula Soft (hot, warm; next: a warm-intro request to the connector); Rynek Cloud (hot, referral; next: a referral ask); Wawel Payments (warm, referral; next: a referral ask)\nTarget-list sources: Previous-sponsor roster same-series roster; Organizer-network employers default; Adjacent-event sponsor scan available; Institutional channels available; Attendee-stack vendor mapping promoted\nFirst-touch channel: the page's default is warm; rungs Warm intro default; Referral ask available; Inbound broadcast always on; Cold email sequence promoted; Purchased or scraped lists deleted\nFollow-up cadence: the page's pick is standard (cap 3 follow-ups); rungs Sponsor-standard cadence default; Angle-rotation sequence not yet; the repeated just-checking-in bump deleted\nChecks (2 of 6): Timing (Net-new outreach starts at or before roughly T-8 months) MISSING; Coverage (Prospects in play cover the backward-sized target list) MISSING; Warm first (Every target had its warm-path check before anything colder) passed; Cadence cap (No prospect past the follow-up cap, and every opt-out honored at once) passed; Evidence (Every scored prospect carries a source for its claims) MISSING; Ownership (One named liaison for every prospect past the first touch, in one shared pipeline) MISSING\nSignals to record: Pipeline coverage: prospects in play against the backward-sized list (self-set); Stage conversion per channel - first touch to call, call to proposal, proposal to close - with lapsed sponsors tagged apart (self-set); Objection recurrence by segment, routed to the value proposition\nFindings (11):\n[fix] window (timing): 5 months out, past roughly T-8: larger sponsors locked this budget in the previous financial year - flag it and prioritize targets whose budget cycle is still open (anchor tiers want 6-9 months, supplementary 3-4).\n[check] over_promise (program): The program has no hiring corner (wanted by Vistula Soft, Rynek Cloud) - pitch the program as it stands; route the missing activity to the program owners.\n[check] coverage (math): 5 prospects in play for a backward-sized list of 35 - source 70-105 names to qualify down from; a shortfall at the list stage predicts a shortfall at close.\n[check] no_source (evidence): No source for: Kopiec Dev - every qualification claim carries a source URL and a date.\n[check] no_tool (pipeline): No shared pipeline - a CRM, an email follow-up tool or a spreadsheet all work; the habit matters more than the tool.\n[check] checks (measurement): Outreach checks: 2 of 6 (all self-set).\n[info] rates (math): The 30% close and 40% reply rates are self-set assumptions - event sponsorship publishes no benchmark of its own; replace them with this event's observed rates edition over edition.\n[info] cold_up (channel): Warm paths reach 1 prospect against 14 to pitch - the cold email sequence is promoted for targets no one in the network reaches, after the referral ask.\n[info] talks_only (program): A talks-only program convinces sponsors less than one with a business-oriented layer - adding that layer is a program decision, not a sales one.\n[info] honesty (program): Community-run: never promise attendee lists or purchasable talk slots - the sponsor buys access to a qualified audience, never its contact data.\n[info] no_valueprop (proposal): No per-segment value proposition yet - the call's needs discovery maps onto its categories."
}
Reply:
{
"task": "plan",
"summary": "The most urgent finding is that the event is 5 months out, past the roughly T-8-month budget window, so the first move is prioritizing targets whose budget cycle is still open.",
"math": {
"sponsors": 4,
"pitch": 14,
"list": 35,
"note": "5 prospects are in play against a backward-sized list of 35, and both the 30% close rate and the 40% reply rate are self-set assumptions."
},
"timing": "At 5 months out, the event is past the roughly T-8-month budget window, so that window is closing.",
"top": [
{
"company": "Vistula Soft",
"why": "Strong fit, a fresh signal and a warm path ready to use.",
"channel": "warm",
"title": "Recruiting, Talent Acquisition or HR",
"next": "intro"
},
{
"company": "Rynek Cloud",
"why": "Strong fit and a fresh signal, with no warm path, reached instead through a referral ask.",
"channel": "referral",
"title": "Recruiting, Talent Acquisition or HR",
"next": "referral"
},
{
"company": "Wawel Payments",
"why": "Some fit and an older signal, with no warm path, reached instead through a referral ask.",
"channel": "referral",
"title": "Marketing, PR or a relevant employee resource group",
"next": "referral"
}
],
"channels": {
"pick": "warm",
"note": "Warm paths reach 1 of the 14 prospects to pitch, and the cold email sequence comes in only after the referral ask, for whoever is left."
},
"cadence": {
"pick": "standard",
"cap": 3,
"note": "Standard cadence spaces follow-ups 1-2 weeks apart up to the cap of 3, and no prospect is past it yet."
},
"prep": [
"The fixed sponsor questions - projected attendance, aggregate audience composition, per-level benefits, logistics - already answered and ready to show.",
"An answer ready for each of the four sponsor concerns: attendee value, co-sponsor mix, package value and organizer competence.",
"The proposal inputs: the rate card is ready, but no value proposition or prospectus exists yet."
],
"checks": [
{
"check": "Timing",
"pass": false
},
{
"check": "Coverage",
"pass": false
},
{
"check": "Warm first",
"pass": true
},
{
"check": "Cadence cap",
"pass": true
},
{
"check": "Evidence",
"pass": false
},
{
"check": "Ownership",
"pass": false
}
],
"signals": [
"Pipeline coverage against the backward-sized list - would recalibrate next edition's self-set close and reply rates.",
"Stage conversion per channel, with lapsed sponsors tagged apart - would show which channel to favor next edition.",
"Objection recurrence by segment, routed to the value proposition - would show which pitch to revise next edition."
],
"caveats": [
"5 months out is past the roughly T-8-month budget window - prioritize targets whose budget cycle is still open (anchor tiers want 6-9 months, supplementary 3-4).",
"The program has no hiring corner, wanted by Vistula Soft and Rynek Cloud - pitch the program as it stands.",
"5 prospects are in play for a backward-sized list of 35 - source 70-105 names to qualify down from.",
"No source for Kopiec Dev - every qualification claim needs a source URL and a date."
]
}
The page's check: kept - nothing to flag
Gophers Night Krakow (a first edition in a series, 5 months out) - emails
4 sponsors needed, a list of 35, 5 in play; 5 months out; 3 top targets; sponsor-standard cadence; 2 of 6 checks.
Input:
{
"task": "emails",
"event": "Event: Gophers Night Krakow in Krakow, March 20; attendance 120; community-run; 5 months out; first edition of a series\nGoal: sponsorship revenue 6,000; renewals expected 0; average package 1,500; self-set close rate 30%, reply rate 40%\nTeam: volunteer organizers with a few hours a week; sponsors as one-off sales; shared pipeline tool no; contact list built by the team\nProgram: hiring corner no; hands-on feedback session no; opt-in demo space no\nInputs: value proposition no; prospectus no; rate card yes; the fixed sponsor questions answered yes",
"prospects": "Prospects, in order (company | segment | motivation | fit | signal | warm path | stage | follow-ups | opted out | history | liaison | source | score | channel | title to target):\n1. Vistula Soft | midsized | hiring | strong | fresh | warm | identified | 0 | no | new | NONE | yes | hot | warm | Recruiting, Talent Acquisition or HR | TOP TARGET #1\n2. Wawel Payments | enterprise | brand | some | old | none | identified | 0 | no | new | NONE | yes | warm | referral | Marketing, PR or a relevant employee resource group | TOP TARGET #3\n3. Kopiec Dev | startup | unknown | some | none | none | identified | 0 | no | new | NONE | NONE | cold | referral | the CEO\n4. Rynek Cloud | enterprise | hiring | strong | fresh | none | identified | 0 | no | new | NONE | yes | hot | referral | Recruiting, Talent Acquisition or HR | TOP TARGET #2\n5. Smok Studio | startup | brand | loose | old | none | identified | 0 | no | new | NONE | yes | cold | referral | Marketing, PR or a relevant employee resource group",
"facts": "Backward math: net-new goal 6,000 / average package 1,500 = 4 sponsors needed; / 30% close = 14 prospects to pitch; / 40% reply = a target list of 35; source 70-105 names; prospects in play 5 (committed, signed, lost, opted-out, skipped and renewal prospects are not in play)\nTiming: 5 months out - past T-8, the budget window is closing\nTop targets, in order, with the next message each is owed: Vistula Soft (hot, warm; next: a warm-intro request to the connector); Rynek Cloud (hot, referral; next: a referral ask); Wawel Payments (warm, referral; next: a referral ask)\nTarget-list sources: Previous-sponsor roster same-series roster; Organizer-network employers default; Adjacent-event sponsor scan available; Institutional channels available; Attendee-stack vendor mapping promoted\nFirst-touch channel: the page's default is warm; rungs Warm intro default; Referral ask available; Inbound broadcast always on; Cold email sequence promoted; Purchased or scraped lists deleted\nFollow-up cadence: the page's pick is standard (cap 3 follow-ups); rungs Sponsor-standard cadence default; Angle-rotation sequence not yet; the repeated just-checking-in bump deleted\nChecks (2 of 6): Timing (Net-new outreach starts at or before roughly T-8 months) MISSING; Coverage (Prospects in play cover the backward-sized target list) MISSING; Warm first (Every target had its warm-path check before anything colder) passed; Cadence cap (No prospect past the follow-up cap, and every opt-out honored at once) passed; Evidence (Every scored prospect carries a source for its claims) MISSING; Ownership (One named liaison for every prospect past the first touch, in one shared pipeline) MISSING\nSignals to record: Pipeline coverage: prospects in play against the backward-sized list (self-set); Stage conversion per channel - first touch to call, call to proposal, proposal to close - with lapsed sponsors tagged apart (self-set); Objection recurrence by segment, routed to the value proposition\nFindings (11):\n[fix] window (timing): 5 months out, past roughly T-8: larger sponsors locked this budget in the previous financial year - flag it and prioritize targets whose budget cycle is still open (anchor tiers want 6-9 months, supplementary 3-4).\n[check] over_promise (program): The program has no hiring corner (wanted by Vistula Soft, Rynek Cloud) - pitch the program as it stands; route the missing activity to the program owners.\n[check] coverage (math): 5 prospects in play for a backward-sized list of 35 - source 70-105 names to qualify down from; a shortfall at the list stage predicts a shortfall at close.\n[check] no_source (evidence): No source for: Kopiec Dev - every qualification claim carries a source URL and a date.\n[check] no_tool (pipeline): No shared pipeline - a CRM, an email follow-up tool or a spreadsheet all work; the habit matters more than the tool.\n[check] checks (measurement): Outreach checks: 2 of 6 (all self-set).\n[info] rates (math): The 30% close and 40% reply rates are self-set assumptions - event sponsorship publishes no benchmark of its own; replace them with this event's observed rates edition over edition.\n[info] cold_up (channel): Warm paths reach 1 prospect against 14 to pitch - the cold email sequence is promoted for targets no one in the network reaches, after the referral ask.\n[info] talks_only (program): A talks-only program convinces sponsors less than one with a business-oriented layer - adding that layer is a program decision, not a sales one.\n[info] honesty (program): Community-run: never promise attendee lists or purchasable talk slots - the sponsor buys access to a qualified audience, never its contact data.\n[info] no_valueprop (proposal): No per-segment value proposition yet - the call's needs discovery maps onto its categories."
}
Reply:
{
"task": "emails",
"messages": [
{
"company": "Vistula Soft",
"kind": "intro",
"to": "to be named",
"subject": "Introduction to Vistula Soft for Gophers Night Krakow?",
"body": "Hello,\n\nWe're organizing Gophers Night Krakow and hoped you might help us connect with Vistula Soft.\n\nGophers Night Krakow is a community-run event in Krakow on March 20, with 120 attendees, and this will be the first edition of the series. We think Vistula Soft could be a strong sponsor fit given the hiring interest we've seen, and we would value an introduction to the right person there.\n\nWould you be willing to make that connection, or point us to who we should ask instead? No pressure if this isn't something you can help with.\n\nThank you for considering it.\n\nBest,\nGophers Night Krakow Team"
},
{
"company": "Rynek Cloud",
"kind": "referral",
"to": "someone senior at Rynek Cloud",
"subject": "Sponsorship contact at Rynek Cloud for Gophers Night Krakow",
"body": "Hello,\n\nI'm reaching out about Gophers Night Krakow, a community-run event taking place in Krakow on March 20.\n\nCould you point me to the right person at Rynek Cloud to talk to about sponsoring this event?\n\nThank you for your time.\n\nBest,\nGophers Night Krakow Team"
},
{
"company": "Wawel Payments",
"kind": "referral",
"to": "someone senior at Wawel Payments",
"subject": "Sponsorship contact at Wawel Payments for Gophers Night Krakow",
"body": "Hello,\n\nI'm reaching out about Gophers Night Krakow, a community-run event taking place in Krakow on March 20.\n\nCould you point me to the right person at Wawel Payments to talk to about sponsoring this event?\n\nThank you for your time.\n\nBest,\nGophers Night Krakow Team"
}
],
"note": "The budget window is past roughly T-8 months, so confirm quickly whether Vistula Soft, Rynek Cloud and Wawel Payments still have open budget."
}
The page's check: kept - nothing to flag
Northwind Platform Summit (company-run, a dedicated lead) - plan
12 sponsors needed, a list of 240, 5 in play; 9 months out; 4 top targets; angle-rotation sequence; 4 of 6 checks.
Input:
{
"task": "plan",
"event": "Event: Northwind Platform Summit in Seattle, June 3-4; attendance 2200; company- or foundation-run; 9 months out\nGoal: sponsorship revenue 300,000; renewals expected 0; average package 25,000; self-set close rate 20%, reply rate 25%\nTeam: a dedicated sponsorship lead; sponsors as multi-edition relationships; shared pipeline tool yes; contact list built by the team\nProgram: hiring corner no; hands-on feedback session yes; opt-in demo space yes\nInputs: value proposition yes; prospectus yes; rate card yes; the fixed sponsor questions answered yes",
"prospects": "Prospects, in order (company | segment | motivation | fit | signal | warm path | stage | follow-ups | opted out | history | liaison | source | score | channel | title to target):\n1. Cobalt Observability | enterprise | selling | strong | fresh | warm | committed | 2 | no | new | Priya | yes | hot | warm | Marketing, PR or a relevant employee resource group\n2. Ferrous Security | midsized | feedback | strong | fresh | none | proposal | 3 | no | new | Marcus | yes | hot | referral | Developer Relations or a Developer Advocate | TOP TARGET #2\n3. Lumen Queue | startup | feedback | strong | old | none | call | 1 | no | new | NONE | yes | warm | referral | Developer Relations or a Developer Advocate | TOP TARGET #3\n4. Helix Data | enterprise | hiring | strong | fresh | warm | first touch | 0 | no | new | Priya | yes | hot | warm | Recruiting, Talent Acquisition or HR | TOP TARGET #1\n5. Arbor CI | midsized | selling | some | fresh | none | first touch | 4 | no | new | Dee | yes | warm | referral | Marketing, PR or a relevant employee resource group\n6. Quartz Edge | enterprise | brand | some | old | none | identified | 0 | no | released | NONE | yes | warm | reentry | Marketing, PR or a relevant employee resource group | TOP TARGET #4",
"facts": "Backward math: net-new goal 300,000 / average package 25,000 = 12 sponsors needed; / 20% close = 60 prospects to pitch; / 25% reply = a target list of 240; source 480-720 names; prospects in play 5 (committed, signed, lost, opted-out, skipped and renewal prospects are not in play)\nTiming: 9 months out - inside the T-8 window\nTop targets, in order, with the next message each is owed: Helix Data (hot, warm; next: follow-up 1 of 4); Ferrous Security (hot, referral; next: follow-up 4 of 4); Lumen Queue (warm, referral; next: the proposal, same day as the call); Quartz Edge (warm, reentry; next: a re-entry note)\nTarget-list sources: Previous-sponsor roster default; Organizer-network employers available; Adjacent-event sponsor scan available; Institutional channels available; Attendee-stack vendor mapping not yet\nFirst-touch channel: the page's default is warm; rungs Warm intro default; Referral ask available; Inbound broadcast always on; Cold email sequence promoted; Purchased or scraped lists deleted\nFollow-up cadence: the page's pick is rotation (cap 4 follow-ups); rungs Sponsor-standard cadence default; Angle-rotation sequence promoted; the repeated just-checking-in bump deleted\nChecks (4 of 6): Timing (Net-new outreach starts at or before roughly T-8 months) passed; Coverage (Prospects in play cover the backward-sized target list) MISSING; Warm first (Every target had its warm-path check before anything colder) passed; Cadence cap (No prospect past the follow-up cap, and every opt-out honored at once) passed; Evidence (Every scored prospect carries a source for its claims) passed; Ownership (One named liaison for every prospect past the first touch, in one shared pipeline) MISSING\nSignals to record: Pipeline coverage: prospects in play against the backward-sized list (self-set); Stage conversion per channel - first touch to call, call to proposal, proposal to close - with lapsed sponsors tagged apart (self-set); Objection recurrence by segment, routed to the value proposition\nFindings (8):\n[check] over_promise (program): The program has no hiring corner (wanted by Helix Data) - pitch the program as it stands; route the missing activity to the program owners.\n[check] coverage (math): 5 prospects in play for a backward-sized list of 240 - source 480-720 names to qualify down from; a shortfall at the list stage predicts a shortfall at close.\n[check] no_liaison (pipeline): No liaison for: Lumen Queue - one named organizer owns each relationship.\n[check] checks (measurement): Outreach checks: 4 of 6 (all self-set).\n[info] rates (math): The 20% close and 25% reply rates are self-set assumptions - event sponsorship publishes no benchmark of its own; replace them with this event's observed rates edition over edition.\n[info] cold_up (channel): Warm paths reach 2 prospects against 60 to pitch - the cold email sequence is promoted for targets no one in the network reaches, after the referral ask.\n[info] lapsed (channel): Quartz Edge re-enters at the exploratory call, tagged lapsed - never cold-pitched as if new.\n[info] close (close): Cobalt Observability said yes: invoice immediately, confirm amount and payment method in writing, and verify the receiving account before payment is sent."
}
Reply:
{
"task": "plan",
"summary": "The most urgent finding is that the program has no hiring corner, which Helix Data wants, so the first move is pitching the program as it stands.",
"math": {
"sponsors": 12,
"pitch": 60,
"list": 240,
"note": "5 prospects are in play against a backward-sized list of 240, and both the 20% close rate and the 25% reply rate are self-set assumptions."
},
"timing": "At 9 months out, the event is inside the roughly T-8-month budget window for outreach.",
"top": [
{
"company": "Helix Data",
"why": "Strong fit, a fresh signal and a warm path ready to use.",
"channel": "warm",
"title": "Recruiting, Talent Acquisition or HR",
"next": "followup"
},
{
"company": "Ferrous Security",
"why": "Strong fit and a fresh signal, with no warm path, reached instead through a referral ask.",
"channel": "referral",
"title": "Developer Relations or a Developer Advocate",
"next": "followup"
},
{
"company": "Lumen Queue",
"why": "Strong fit but an older signal, with no warm path, reached instead through a referral ask.",
"channel": "referral",
"title": "Developer Relations or a Developer Advocate",
"next": "proposal"
},
{
"company": "Quartz Edge",
"why": "Some fit and an older signal, with no warm path, re-entering instead as a released sponsor.",
"channel": "reentry",
"title": "Marketing, PR or a relevant employee resource group",
"next": "reentry"
}
],
"channels": {
"pick": "warm",
"note": "Warm paths reach 2 of the 60 prospects to pitch, and the cold email sequence comes in only after the referral ask, for whoever is left."
},
"cadence": {
"pick": "rotation",
"cap": 4,
"note": "The rotation cadence caps follow-ups at 4, each with a new angle, and Ferrous Security's follow-up 4 of 4 is its last one, which should acknowledge the lack of response and close the thread."
},
"prep": [
"An answer ready for each of the four sponsor concerns: attendee value, co-sponsor mix, package value and organizer competence.",
"The proposal inputs already on hand: the value proposition, the prospectus and the rate card.",
"A named liaison for Lumen Queue before its proposal goes out, since none is assigned yet."
],
"checks": [
{
"check": "Timing",
"pass": true
},
{
"check": "Coverage",
"pass": false
},
{
"check": "Warm first",
"pass": true
},
{
"check": "Cadence cap",
"pass": true
},
{
"check": "Evidence",
"pass": true
},
{
"check": "Ownership",
"pass": false
}
],
"signals": [
"Pipeline coverage against the backward-sized list - would recalibrate next edition's self-set close and reply rates.",
"Stage conversion per channel, with lapsed sponsors tagged apart - would show which channel to favor next edition.",
"Objection recurrence by segment, routed to the value proposition - would show which pitch to revise next edition."
],
"caveats": [
"The program has no hiring corner, wanted by Helix Data - pitch the program as it stands.",
"5 prospects are in play for a backward-sized list of 240 - source 480-720 names to qualify down from.",
"No liaison for Lumen Queue - one named organizer should own each relationship.",
"Outreach checks: 4 of 6, all self-set."
]
}
The page's check: kept - nothing to flag
Northwind Platform Summit (company-run, a dedicated lead) - emails
12 sponsors needed, a list of 240, 5 in play; 9 months out; 4 top targets; angle-rotation sequence; 4 of 6 checks.
Input:
{
"task": "emails",
"event": "Event: Northwind Platform Summit in Seattle, June 3-4; attendance 2200; company- or foundation-run; 9 months out\nGoal: sponsorship revenue 300,000; renewals expected 0; average package 25,000; self-set close rate 20%, reply rate 25%\nTeam: a dedicated sponsorship lead; sponsors as multi-edition relationships; shared pipeline tool yes; contact list built by the team\nProgram: hiring corner no; hands-on feedback session yes; opt-in demo space yes\nInputs: value proposition yes; prospectus yes; rate card yes; the fixed sponsor questions answered yes",
"prospects": "Prospects, in order (company | segment | motivation | fit | signal | warm path | stage | follow-ups | opted out | history | liaison | source | score | channel | title to target):\n1. Cobalt Observability | enterprise | selling | strong | fresh | warm | committed | 2 | no | new | Priya | yes | hot | warm | Marketing, PR or a relevant employee resource group\n2. Ferrous Security | midsized | feedback | strong | fresh | none | proposal | 3 | no | new | Marcus | yes | hot | referral | Developer Relations or a Developer Advocate | TOP TARGET #2\n3. Lumen Queue | startup | feedback | strong | old | none | call | 1 | no | new | NONE | yes | warm | referral | Developer Relations or a Developer Advocate | TOP TARGET #3\n4. Helix Data | enterprise | hiring | strong | fresh | warm | first touch | 0 | no | new | Priya | yes | hot | warm | Recruiting, Talent Acquisition or HR | TOP TARGET #1\n5. Arbor CI | midsized | selling | some | fresh | none | first touch | 4 | no | new | Dee | yes | warm | referral | Marketing, PR or a relevant employee resource group\n6. Quartz Edge | enterprise | brand | some | old | none | identified | 0 | no | released | NONE | yes | warm | reentry | Marketing, PR or a relevant employee resource group | TOP TARGET #4",
"facts": "Backward math: net-new goal 300,000 / average package 25,000 = 12 sponsors needed; / 20% close = 60 prospects to pitch; / 25% reply = a target list of 240; source 480-720 names; prospects in play 5 (committed, signed, lost, opted-out, skipped and renewal prospects are not in play)\nTiming: 9 months out - inside the T-8 window\nTop targets, in order, with the next message each is owed: Helix Data (hot, warm; next: follow-up 1 of 4); Ferrous Security (hot, referral; next: follow-up 4 of 4); Lumen Queue (warm, referral; next: the proposal, same day as the call); Quartz Edge (warm, reentry; next: a re-entry note)\nTarget-list sources: Previous-sponsor roster default; Organizer-network employers available; Adjacent-event sponsor scan available; Institutional channels available; Attendee-stack vendor mapping not yet\nFirst-touch channel: the page's default is warm; rungs Warm intro default; Referral ask available; Inbound broadcast always on; Cold email sequence promoted; Purchased or scraped lists deleted\nFollow-up cadence: the page's pick is rotation (cap 4 follow-ups); rungs Sponsor-standard cadence default; Angle-rotation sequence promoted; the repeated just-checking-in bump deleted\nChecks (4 of 6): Timing (Net-new outreach starts at or before roughly T-8 months) passed; Coverage (Prospects in play cover the backward-sized target list) MISSING; Warm first (Every target had its warm-path check before anything colder) passed; Cadence cap (No prospect past the follow-up cap, and every opt-out honored at once) passed; Evidence (Every scored prospect carries a source for its claims) passed; Ownership (One named liaison for every prospect past the first touch, in one shared pipeline) MISSING\nSignals to record: Pipeline coverage: prospects in play against the backward-sized list (self-set); Stage conversion per channel - first touch to call, call to proposal, proposal to close - with lapsed sponsors tagged apart (self-set); Objection recurrence by segment, routed to the value proposition\nFindings (8):\n[check] over_promise (program): The program has no hiring corner (wanted by Helix Data) - pitch the program as it stands; route the missing activity to the program owners.\n[check] coverage (math): 5 prospects in play for a backward-sized list of 240 - source 480-720 names to qualify down from; a shortfall at the list stage predicts a shortfall at close.\n[check] no_liaison (pipeline): No liaison for: Lumen Queue - one named organizer owns each relationship.\n[check] checks (measurement): Outreach checks: 4 of 6 (all self-set).\n[info] rates (math): The 20% close and 25% reply rates are self-set assumptions - event sponsorship publishes no benchmark of its own; replace them with this event's observed rates edition over edition.\n[info] cold_up (channel): Warm paths reach 2 prospects against 60 to pitch - the cold email sequence is promoted for targets no one in the network reaches, after the referral ask.\n[info] lapsed (channel): Quartz Edge re-enters at the exploratory call, tagged lapsed - never cold-pitched as if new.\n[info] close (close): Cobalt Observability said yes: invoice immediately, confirm amount and payment method in writing, and verify the receiving account before payment is sent."
}
Reply:
{
"task": "emails",
"messages": [
{
"company": "Helix Data",
"kind": "followup",
"to": "Recruiting, Talent Acquisition or HR",
"subject": "Follow-up 1 of 4: what Northwind Platform Summit offers Helix Data",
"body": "Hello,\n\nThis is follow-up 1 of 4 on partnering with Northwind Platform Summit, our 2200-attendee summit in Seattle, June 3-4.\n\nWe don't run a dedicated hiring corner this year, so rather than offer that, we want to point you to what the program does include: a hands-on feedback session and an opt-in demo space, both of which put Helix Data's team directly in front of attendees. The attached prospectus and rate card lay out how a package fits around those.\n\nWould you have time for a short call to talk through what matters most to Helix Data this year?\n\nBest,\nPriya"
},
{
"company": "Ferrous Security",
"kind": "followup",
"to": "Developer Relations or a Developer Advocate",
"subject": "Follow-up 4 of 4: closing the loop for Ferrous Security",
"body": "Hello,\n\nThis is follow-up 4 of 4 on the proposal we sent Ferrous Security for Northwind Platform Summit.\n\nWe haven't heard back since sending it, so we want to name that directly rather than send another reminder. If the feedback-session-focused package we proposed isn't the right fit, our opt-in demo space might be worth a second look before we close this out - it's a different way to reach the same audience.\n\nIf timing or priorities have shifted, that's completely understandable. We won't follow up again after this note, but the door stays open if Ferrous Security wants to pick this back up for Northwind Platform Summit.\n\nBest,\nMarcus"
},
{
"company": "Lumen Queue",
"kind": "proposal",
"to": "Developer Relations or a Developer Advocate",
"subject": "Lumen Queue proposal: Northwind Platform Summit feedback session",
"body": "Hello,\n\nThank you for the call today. As promised, here is the proposal the same day.\n\nNorthwind Platform Summit runs June 3-4 in Seattle for 2200 attendees. Based on the feedback goal you described, this proposal centers on our hands-on feedback session, which gives Lumen Queue direct time with attendees, with our opt-in demo space as a complementary option. It includes only the activities the program already runs this year.\n\nThe attached prospectus and rate card lay out the full package and benefits. We would like to confirm by a date to be named, so we can finalize ahead of other sponsor conversations underway.\n\nHappy to answer any questions in the meantime.\n\nBest,\nNorthwind Platform Summit Team"
},
{
"company": "Quartz Edge",
"kind": "reentry",
"to": "Marketing, PR or a relevant employee resource group",
"subject": "Welcome back, Quartz Edge - Northwind Platform Summit this year",
"body": "Hello,\n\nIt's good to reconnect - Quartz Edge has sponsored Northwind Platform Summit before, and we'd love to have you back for this edition.\n\nRather than go over the basics again, we'd like to hear what matters most to Quartz Edge this year and what would make a sponsorship worth it this time.\n\nCould we find a short call to talk it through? A time to be named works on our side - happy to work around your schedule.\n\nBest,\nNorthwind Platform Summit Team"
}
],
"note": "Assign a named liaison for Lumen Queue before its proposal goes out, since no organizer currently owns that relationship."
}
The page's check: kept - nothing to flag
The lead sheet CSV for the first sample
company,segment,motivation,score,channel,title,stage,follow_ups,liaison,top_target
Quayside Data,midsized,hiring,hot,warm,"Recruiting, Talent Acquisition or HR",call,1,Ana,yes
Tidewell Cloud,enterprise,feedback,hot,referral,Developer Relations or a Developer Advocate,first touch,2,,yes
Brindlewick,startup,hiring,warm,referral,"Recruiting, Talent Acquisition or HR",first touch,5,,
Saltmarsh Labs,startup,brand,hot,warm,"Marketing, PR or a relevant employee resource group",identified,0,,yes
Corvo Analytics,midsized,hiring,warm,referral,"Recruiting, Talent Acquisition or HR",first touch,1,,
Atlantic Ledger,enterprise,unknown,cold,referral,the CEO,identified,0,,
Pinecrest Tools,midsized,feedback,warm,reentry,Developer Relations or a Developer Advocate,first touch,1,Rui,yes
Marlow Systems,enterprise,brand,renewal,renewal,"Marketing, PR or a relevant employee resource group",identified,0,,
Gullwing Games,startup,unknown,skip,none,the CEO,identified,0,,
Build the input yourself
Load the engine in node (global.window = global; require("./pipekit.js"); require("./pipereply.js")), then:
const K = PipeKit, R = PipeReply;
const f = K.form({ name: "My Conf", monthsOut: "11", goal: "60000", renewalExpected: "20000", avgPackage: "5000", closeRate: "25", replyRate: "33",
prospects: fs.readFileSync("prospects.csv", "utf8") });
// f.needed, f.pitch, f.list, f.timing, f.prospects (score, channel, title), f.inPlay, f.top (next, nextNo)
// f.recChannel, f.recCadence, f.cap and the source, channel and cadence rungs, f.checks, f.findings
K.leadCSV(f) // company, segment, motivation, score, channel, title, stage, ...
const b = K.buildInput(f, "plan"); // or "emails"
const wire = K.toWire(b.input); // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "plan");
// R.check(reply, b) // {status: kept or flagged, notes}
Get a token for the steps below from /tokens.html.
Step 1 — a tiny client helper
One function that sends JSON and unwraps the response. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.
BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="paste-your-token-here" # from https://sponsor-pipeline.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}
import json, urllib.request
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "paste-your-token-here" # from https://sponsor-pipeline.skillsafe.ai/tokens.html
def api(method, path, body=None, headers=None):
req = urllib.request.Request(BASE + path, method=method,
data=None if body is None else json.dumps(body).encode(),
headers={"Content-Type": "application/json", **({"Authorization": "Bearer " + TOKEN} if TOKEN else {}), **(headers or {})})
with urllib.request.urlopen(req) as r:
env = json.load(r)
if env.get("error"):
raise RuntimeError(env["error"])
return env["data"]
// sponsor-pipeline.mjs -- Node 18+ (global fetch)
const BASE = "https://api.skillsafe.ai/v1/app-api";
let TOKEN = "paste-your-token-here"; // from https://sponsor-pipeline.skillsafe.ai/tokens.html
async function api(method, path, body, headers = {}) {
const r = await fetch(BASE + path, { method, headers: { "Content-Type": "application/json",
...(TOKEN ? { Authorization: "Bearer " + TOKEN } : {}), ...headers },
body: body === undefined ? undefined : JSON.stringify(body) });
const env = await r.json();
if (env.error) throw new Error(env.error.code + ": " + env.error.message);
return env.data;
}
package main
import ("bytes"; "encoding/json"; "fmt"; "net/http")
const base = "https://api.skillsafe.ai/v1/app-api"
var token = "paste-your-token-here" // from https://sponsor-pipeline.skillsafe.ai/tokens.html
func api(method, path string, body any, headers map[string]string) (map[string]any, error) {
var buf bytes.Buffer
if body != nil { json.NewEncoder(&buf).Encode(body) }
req, _ := http.NewRequest(method, base+path, &buf)
req.Header.Set("Content-Type", "application/json")
if token != "" { req.Header.Set("Authorization", "Bearer "+token) }
for k, v := range headers { req.Header.Set(k, v) }
res, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer res.Body.Close()
var env struct { Data map[string]any; Error map[string]any }
json.NewDecoder(res.Body).Decode(&env)
if env.Error != nil { return nil, fmt.Errorf("%v", env.Error) }
return env.Data, nil
}
// SponsorPipeline.java -- Java 17+, with com.fasterxml.jackson.core:jackson-databind
import com.fasterxml.jackson.databind.*;
import java.net.URI; import java.net.http.*; import java.util.*;
public class SponsorPipeline {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static String token = "paste-your-token-here"; // from https://sponsor-pipeline.skillsafe.ai/tokens.html
static final ObjectMapper M = new ObjectMapper();
static final HttpClient C = HttpClient.newHttpClient();
static JsonNode api(String method, String path, Object body, Map<String, String> headers) throws Exception {
var b = HttpRequest.newBuilder(URI.create(BASE + path)).header("Content-Type", "application/json");
if (!token.isEmpty()) b.header("Authorization", "Bearer " + token);
if (headers != null) headers.forEach(b::header);
b.method(method, body == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(M.writeValueAsString(body)));
JsonNode env = M.readTree(C.send(b.build(), HttpResponse.BodyHandlers.ofString()).body());
if (env.hasNonNull("error")) throw new RuntimeException(env.get("error").toString());
return env.get("data");
}
}
require "json"
require "net/http"
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "paste-your-token-here" # from https://sponsor-pipeline.skillsafe.ai/tokens.html
def api(method, path, body = nil, headers = {})
uri = URI(BASE + path)
req = Net::HTTPGenericRequest.new(method, !body.nil?, true, uri.request_uri,
{ "Content-Type" => "application/json" }.merge(TOKEN.empty? ? {} : { "Authorization" => "Bearer #{TOKEN}" }).merge(headers))
req.body = JSON.generate(body) unless body.nil?
env = JSON.parse(Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }.body)
raise env["error"].to_s if env["error"]
env["data"]
end
<?php
const BASE = "https://api.skillsafe.ai/v1/app-api";
$TOKEN = "paste-your-token-here"; // from https://sponsor-pipeline.skillsafe.ai/tokens.html
function api(string $method, string $path, $body = null, array $headers = []) {
global $TOKEN;
$h = ["Content-Type: application/json"];
if ($TOKEN) $h[] = "Authorization: Bearer $TOKEN";
foreach ($headers as $k => $v) $h[] = "$k: $v";
$ch = curl_init(BASE . $path);
curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $h, CURLOPT_RETURNTRANSFER => true]);
if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$env = json_decode(curl_exec($ch), true);
if (!empty($env["error"])) throw new Exception(json_encode($env["error"]));
return $env["data"];
}
// Program.cs -- .NET 6+ console app
using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Nodes;
static class Api {
public const string Base = "https://api.skillsafe.ai/v1/app-api";
public static string Token = "paste-your-token-here"; // from https://sponsor-pipeline.skillsafe.ai/tokens.html
static readonly HttpClient C = new();
public static async Task<JsonNode?> Call(string method, string path, object? body = null, Dictionary<string, string>? headers = null) {
var req = new HttpRequestMessage(new HttpMethod(method), Base + path);
if (Token != "") req.Headers.Add("Authorization", "Bearer " + Token);
if (headers != null) foreach (var h in headers) req.Headers.Add(h.Key, h.Value);
if (body != null) req.Content = JsonContent.Create(body);
var env = JsonNode.Parse(await (await C.SendAsync(req)).Content.ReadAsStringAsync())!;
if (env["error"] is JsonNode e && e.GetValueKind() != JsonValueKind.Null) throw new Exception(e.ToJsonString());
return env["data"];
}
}
Step 2 — a token
A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"sponsor-pipeline"}' | jq -r '.data.token')
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN = ""
TOKEN = api("POST", "/guest", {"slug": "sponsor-pipeline"})["token"]
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN = "";
TOKEN = (await api("POST", "/guest", { slug: "sponsor-pipeline" })).token;
// inside main: a guest token (enough for /me and /estimate); a run needs your personal token
token = ""
g, err := api("POST", "/guest", map[string]string{"slug": "sponsor-pipeline"}, nil)
if err != nil { panic(err) }
token = g["token"].(string)
// inside main: a guest token (enough for /me and /estimate); a run needs your personal token
token = "";
token = api("POST", "/guest", Map.of("slug", "sponsor-pipeline"), null).get("token").asText();
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN.replace("")
TOKEN.replace(api("POST", "/guest", { slug: "sponsor-pipeline" })["token"])
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
$TOKEN = "";
$TOKEN = api("POST", "/guest", ["slug" => "sponsor-pipeline"])["token"];
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
Api.Token = "";
Api.Token = (await Api.Call("POST", "/guest", new { slug = "sponsor-pipeline" }))!["token"]!.GetValue<string>();
Step 3 — GET /me
Who the token is (subject_type: user or guest) and the credit balance.
api GET /me | jq '.data | {subject_type, credits}'
me = api("GET", "/me")
print(me["subject_type"], me.get("credits"))
const me = await api("GET", "/me");
console.log(me.subject_type, me.credits);
me, _ := api("GET", "/me", nil, nil)
fmt.Println(me["subject_type"], me["credits"])
JsonNode me = api("GET", "/me", null, null);
System.out.println(me.get("subject_type") + " " + me.get("credits"));
me = api("GET", "/me")
puts [me["subject_type"], me["credits"]].inspect
$me = api("GET", "/me");
echo $me["subject_type"], " ", $me["credits"] ?? "", "\n";
var me = await Api.Call("GET", "/me");
Console.WriteLine($"{me!["subject_type"]} {me["credits"]}");
Step 4 — POST /estimate
Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.
# input.json: the run input object - {"task": "plan", "event": "Event: ...; attendance 450; community-run; 11 months out", "prospects": "Prospects, in order ...", "facts": "Backward math: ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}'
inp = json.load(open("input.json")) # {"task": "plan", "event": "Event: ...; attendance 450; community-run; 11 months out", "prospects": "Prospects, in order ...", "facts": "Backward math: ..."}
# - see the input table
est = api("POST", "/estimate", inp)
print(est["hold_credits"], est["min_credits"], est["model"], est.get("warnings"))
import { readFileSync } from "node:fs";
const input = JSON.parse(readFileSync("input.json", "utf8")); // {task: "plan" or "emails", event, prospects, facts} (see the input table)
const est = await api("POST", "/estimate", input);
console.log(est.hold_credits, est.min_credits, est.model, est.warnings);
raw, _ := os.ReadFile("input.json") // add "os" to the imports
var input map[string]any
json.Unmarshal(raw, &input)
est, _ := api("POST", "/estimate", input, nil)
fmt.Println(est["hold_credits"], est["min_credits"], est["model"])
Map<String, Object> input = M.readValue(new java.io.File("input.json"), Map.class);
JsonNode est = api("POST", "/estimate", input, null);
System.out.println(est.get("hold_credits") + " " + est.get("min_credits") + " " + est.get("model"));
input = JSON.parse(File.read("input.json"))
est = api("POST", "/estimate", input)
puts [est["hold_credits"], est["min_credits"], est["model"]].inspect
$input = json_decode(file_get_contents("input.json"), true);
$est = api("POST", "/estimate", $input);
echo $est["hold_credits"], " ", $est["min_credits"], " ", $est["model"], "\n";
var input = JsonNode.Parse(File.ReadAllText("input.json"))!;
var est = await Api.Call("POST", "/estimate", input);
Console.WriteLine($"{est!["hold_credits"]} {est["min_credits"]} {est["model"]}");
Step 5 — POST /run, then poll the job
Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses sponsor-pipeline:<task>:<inputHash>:a<attempt> - the lane is part of the key - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A plan carries summary, math, timing, top, channels, cadence, prep, checks, signals and caveats; a messages reply carries messages (company, kind, to, subject, body) and note. The code below prints the headline parts of either (list items are plain strings).
KEY="sponsor-pipeline:plan:$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}'
jq -r '.summary // .format, .note // .timing, ((.signals // .caveats)[] | "\(.signal // .caveat): \(.text // .text)")' reply.json
jq -r '.note // .note // empty' reply.json # the note for the organizers (emails)
import hashlib, time
key = "sponsor-pipeline:" + inp["task"] + ":" + hashlib.sha256(json.dumps(inp).encode()).hexdigest()[:16] + ":a1"
job = api("POST", "/run", inp, {"Idempotency-Key": key})
while True:
j = api("GET", "/jobs/" + job["job_id"])
if j["status"] in ("succeeded", "failed", "cancelled"):
break
time.sleep(2)
reply = json.loads(j["output"]["output"]) # the reply as one JSON object
print(j["charged_credits"], j.get("truncated"), reply.get("summary"))
print(reply.get("note") or reply.get("timing", ""))
for s in reply.get("signals") or reply.get("caveats") or []:
print(s.get("signal", s.get("caveat")), "-", s.get("text", s.get("text")))
if reply.get("note"):
print("note:", reply["note"])
import { createHash } from "node:crypto";
const key = `sponsor-pipeline:${input.task}:${createHash("sha256").update(JSON.stringify(input)).digest("hex").slice(0, 16)}:a1`;
const job = await api("POST", "/run", input, { "Idempotency-Key": key });
let j;
do { await new Promise((r) => setTimeout(r, 2000)); j = await api("GET", "/jobs/" + job.job_id); }
while (!["succeeded", "failed", "cancelled"].includes(j.status));
const reply = JSON.parse(j.output.output);
console.log(j.charged_credits, j.truncated, reply.summary);
console.log(reply.note ?? reply.timing);
for (const s of reply.signals || reply.caveats || []) console.log(s.signal ?? s.caveat, "-", s.text ?? s.text);
if (reply.note) console.log("note:", reply.note);
sum := sha256.Sum256(raw) // add "crypto/sha256", "encoding/hex", "time" to the imports
key := "sponsor-pipeline:" + input["task"].(string) + ":" + hex.EncodeToString(sum[:8]) + ":a1"
job, _ := api("POST", "/run", input, map[string]string{"Idempotency-Key": key})
var j map[string]any
for {
time.Sleep(2 * time.Second)
j, _ = api("GET", "/jobs/"+job["job_id"].(string), nil, nil)
if s := j["status"]; s == "succeeded" || s == "failed" || s == "cancelled" { break }
}
var reply map[string]any
json.Unmarshal([]byte(j["output"].(map[string]any)["output"].(string)), &reply)
items, _ := reply["signals"].([]any) // signals and caveats are plain strings
fmt.Println(j["charged_credits"], j["truncated"], reply["summary"])
fmt.Println(reply["note"], reply["timing"])
for _, x := range items {
c := x.(map[string]any)
fmt.Println(c["signal"], "-", c["status"])
}
if fix, ok := reply["note"].(string); ok && fix != "" {
fmt.Println("note:", fix)
}
var digest = java.security.MessageDigest.getInstance("SHA-256").digest(M.writeValueAsBytes(input));
String key = "sponsor-pipeline:" + input.get("task") + ":" + HexFormat.of().formatHex(digest, 0, 8) + ":a1";
JsonNode job = api("POST", "/run", input, Map.of("Idempotency-Key", key)), j;
do { Thread.sleep(2000); j = api("GET", "/jobs/" + job.get("job_id").asText(), null, null); }
while (!Set.of("succeeded", "failed", "cancelled").contains(j.get("status").asText()));
JsonNode reply = M.readTree(j.get("output").get("output").asText());
System.out.println(j.get("charged_credits") + " " + reply.get("summary"));
System.out.println(reply.path("note").asText(reply.path("timing").asText()));
for (JsonNode s : reply.has("signals") ? reply.path("signals") : reply.path("caveats")) System.out.println(s.path("signal").asText(s.path("caveat").asText()) + " - " + s.path("status").asText(s.path("text").asText()));
if (!reply.path("note").asText().isEmpty()) System.out.println("note: " + reply.get("note").asText());
require "digest"
key = "sponsor-pipeline:#{input["task"]}:#{Digest::SHA256.hexdigest(JSON.generate(input))[0, 16]}:a1"
job = api("POST", "/run", input, { "Idempotency-Key" => key })
j = nil
loop do
sleep 2
j = api("GET", "/jobs/#{job["job_id"]}")
break if %w[succeeded failed cancelled].include?(j["status"])
end
reply = JSON.parse(j["output"]["output"])
puts [j["charged_credits"], j["truncated"], reply["summary"]].inspect
puts reply["note"] || reply["timing"]
(reply["signals"] || reply["caveats"] || []).each { |s| puts "#{s["signal"] || s["caveat"]} - #{s["text"] || s["text"]}" }
puts "note: #{reply["note"]}" unless reply["note"].to_s.empty?
$key = "sponsor-pipeline:" . $input["task"] . ":" . substr(hash("sha256", json_encode($input)), 0, 16) . ":a1";
$job = api("POST", "/run", $input, ["Idempotency-Key" => $key]);
do { sleep(2); $j = api("GET", "/jobs/" . $job["job_id"]); }
while (!in_array($j["status"], ["succeeded", "failed", "cancelled"]));
$reply = json_decode($j["output"]["output"], true);
echo $j["charged_credits"], " ", ($reply["summary"] ?? ""), "\n";
echo $reply["note"] ?? $reply["timing"] ?? "", "\n";
foreach ($reply["signals"] ?? $reply["caveats"] ?? [] as $s) echo $s["signal"] ?? $s["caveat"], " - ", $s["text"] ?? $s["text"], "\n";
if (!empty($reply["note"])) echo "note: ", $reply["note"], "\n";
var digest = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(input.ToJsonString()));
var key = $"sponsor-pipeline:{input["task"]}:{Convert.ToHexString(digest, 0, 8).ToLowerInvariant()}:a1";
var job = await Api.Call("POST", "/run", input, new() { ["Idempotency-Key"] = key });
JsonNode j;
do { await Task.Delay(2000); j = (await Api.Call("GET", "/jobs/" + job!["job_id"]))!; }
while (!new[] { "succeeded", "failed", "cancelled" }.Contains(j["status"]!.GetValue<string>()));
var reply = JsonNode.Parse(j["output"]!["output"]!.GetValue<string>());
Console.WriteLine($"{j["charged_credits"]} {reply!["summary"]}");
Console.WriteLine($"{reply["note"] ?? reply["timing"]}");
foreach (var s in (reply["signals"] ?? reply["caveats"]) as JsonArray ?? new JsonArray()) Console.WriteLine($"{s!["signal"] ?? s["caveat"]} - {s["text"] ?? s["text"]}");
if (reply["note"] is JsonNode fix && fix.GetValue<string>() != "") Console.WriteLine("note: " + fix);
Step 6 — POST /run-stream
The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.
# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: sponsor-pipeline:plan:$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json
rev = json.load(open("input.json")) # the same run input as input.json: {"task": "plan", "event": "Event: ...; attendance 450; community-run; 11 months out", "prospects": "Prospects, in order ...", "facts": "Backward math: ..."}
# - see the input table
req = urllib.request.Request(BASE + "/run-stream", method="POST", data=json.dumps(rev).encode(),
headers={"Content-Type": "application/json", "Authorization": "Bearer " + TOKEN,
"Idempotency-Key": "sponsor-pipeline:plan:" + hashlib.sha256(json.dumps(rev).encode()).hexdigest()[:16] + ":a1"})
with urllib.request.urlopen(req) as r:
for line in r:
line = line.decode().strip()
if line.startswith("data:"):
print(line[5:].strip()[:200])
const rev = JSON.parse(readFileSync("input.json", "utf8"));
const r = await fetch(BASE + "/run-stream", { method: "POST", body: JSON.stringify(rev), headers: {
"Content-Type": "application/json", Authorization: "Bearer " + TOKEN,
"Idempotency-Key": `sponsor-pipeline:plan:${createHash("sha256").update(JSON.stringify(rev)).digest("hex").slice(0, 16)}:a1` } });
const dec = new TextDecoder();
for await (const chunk of r.body) for (const line of dec.decode(chunk).split("\n"))
if (line.startsWith("data:")) console.log(line.slice(5).trim().slice(0, 200));
rraw, _ := os.ReadFile("input.json") // add "bufio", "strings" to the imports
rs := sha256.Sum256(rraw)
req, _ := http.NewRequest("POST", base+"/run-stream", bytes.NewReader(rraw))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Idempotency-Key", "sponsor-pipeline:plan:"+hex.EncodeToString(rs[:8])+":a1")
res, _ := http.DefaultClient.Do(req)
sc := bufio.NewScanner(res.Body)
for sc.Scan() { if l := sc.Text(); strings.HasPrefix(l, "data:") { fmt.Println(l[5:]) } }
String rev = java.nio.file.Files.readString(java.nio.file.Path.of("input.json"));
var rd = java.security.MessageDigest.getInstance("SHA-256").digest(rev.getBytes());
var sreq = HttpRequest.newBuilder(URI.create(BASE + "/run-stream")).header("Content-Type", "application/json")
.header("Authorization", "Bearer " + token).header("Idempotency-Key", "sponsor-pipeline:plan:" + HexFormat.of().formatHex(rd, 0, 8) + ":a1")
.POST(HttpRequest.BodyPublishers.ofString(rev)).build();
C.send(sreq, HttpResponse.BodyHandlers.ofLines()).body().filter(l -> l.startsWith("data:")).forEach(System.out::println);
rev = File.read("input.json")
uri = URI(BASE + "/run-stream")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Authorization" => "Bearer #{TOKEN}",
"Idempotency-Key" => "sponsor-pipeline:plan:#{Digest::SHA256.hexdigest(rev)[0, 16]}:a1")
req.body = rev
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |h|
h.request(req) { |res| res.read_body { |chunk| chunk.each_line { |l| puts l if l.start_with?("data:") } } }
end
$rev = file_get_contents("input.json");
$ch = curl_init(BASE . "/run-stream");
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $rev, CURLOPT_HTTPHEADER => [
"Content-Type: application/json", "Authorization: Bearer $TOKEN",
"Idempotency-Key: sponsor-pipeline:plan:" . substr(hash("sha256", $rev), 0, 16) . ":a1"],
CURLOPT_WRITEFUNCTION => function ($ch, $chunk) { foreach (explode("\n", $chunk) as $l) if (str_starts_with($l, "data:")) echo $l, "\n"; return strlen($chunk); }]);
curl_exec($ch);
var rev = File.ReadAllText("input.json");
var rd = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(rev));
var sreq = new HttpRequestMessage(HttpMethod.Post, Api.Base + "/run-stream") { Content = new StringContent(rev, System.Text.Encoding.UTF8, "application/json") };
sreq.Headers.Add("Authorization", "Bearer " + Api.Token);
sreq.Headers.Add("Idempotency-Key", $"sponsor-pipeline:plan:{Convert.ToHexString(rd, 0, 8).ToLowerInvariant()}:a1");
using var http = new HttpClient();
using var res = await http.SendAsync(sreq, HttpCompletionOption.ResponseHeadersRead);
using var rdr = new StreamReader(await res.Content.ReadAsStreamAsync());
for (string? l; (l = await rdr.ReadLineAsync()) != null;) if (l.StartsWith("data:")) Console.WriteLine(l);