Scenario
Reddit AMAs are the internet’s richest interview format. This job collects common AMA questions, feeds them into Mavera Speak sessions with personas, and produces interview transcripts — deep qualitative research without recruiting.Architecture
Code
import os, requests, time
# --- Auth setup same as Job 1 ---
SUB = "entrepreneur"
# 1. Find AMA posts + extract questions
r = requests.get(f"{RD}/r/{SUB}/search", headers=RD_H,
params={"q": "AMA OR ask me anything", "restrict_sr": "true", "sort": "top", "t": "year", "limit": 15, "raw_json": 1})
r.raise_for_status()
ama_posts = [p["data"] for p in r.json()["data"]["children"]]
questions = []
for post in ama_posts[:10]:
cr = requests.get(f"{RD}/comments/{post['id']}", headers=RD_H,
params={"limit": 20, "depth": 1, "sort": "top", "raw_json": 1})
if cr.ok and len(cr.json()) > 1:
for c in cr.json()[1]["data"]["children"]:
body = c.get("data",{}).get("body","")
if body and "?" in body and len(body) < 500:
questions.append(body.strip())
time.sleep(0.7)
# 2. Curate via Mave
dedup = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
"message": f"Deduplicate these {len(questions)} AMA questions by theme. Return 8 best as numbered list.\n\n" +
"\n".join(f"- {q[:200]}" for q in questions[:50])
}).json()
curated = [l.strip().lstrip("0123456789.) ") for l in dedup.get("content","").split("\n")
if l.strip() and any(c.isalpha() for c in l)][:8]
if not curated:
curated = ["What was the turning point?", "Biggest mistake?", "How do you decide when to pivot?",
"What does your typical day look like?", "How did you get first 100 customers?",
"Best advice you've received?", "What would you do differently?", "How do you handle imposter syndrome?"]
# 3. Personas + Speak
INTERVIEWEES = [
{"name": "Bootstrapped SaaS Founder", "desc": "$5M ARR, no funding, team of 12. Profitability over growth."},
{"name": "VC-Backed CEO", "desc": "Series A ($8M). Team of 40. Scaling fast. Board dynamics."},
{"name": "Solopreneur / Creator", "desc": "$300K/year digital products. No employees. Freedom over scale."},
]
for p in INTERVIEWEES:
persona = requests.post(f"{MV_BASE}/personas", headers=MV_H, json={
"name": f"AMA: {p['name']}", "description": p["desc"],
}).json()
speak = requests.post(f"{MV_BASE}/speak", headers=MV_H, json={
"persona_id": persona["id"],
"input": [{"role": "system", "content": f"You are {p['name']} doing a Reddit AMA in /r/{SUB}. Answer candidly with examples."}]
+ [{"role": "user", "content": q} for q in curated],
"mode": "interview",
}).json()
print(f"\n{'='*60}\nAMA: {p['name']}\n{'='*60}")
for ex in speak.get("exchanges", speak.get("messages", [])):
if ex.get("role") == "user": print(f"\n Q: {ex['content'][:150]}")
elif ex.get("role") == "assistant": print(f" A: {ex['content'][:350]}")
time.sleep(0.3)
// --- Auth setup same as Job 1 ---
const SUB = "entrepreneur";
// 1. AMA search + questions
const amaPosts = (await (await fetch(
`${RD}/r/${SUB}/search?q=${encodeURIComponent("AMA OR ask me anything")}&restrict_sr=true&sort=top&t=year&limit=15&raw_json=1`,
{ headers: RD_H })).json()).data.children.map(p => p.data);
const questions = [];
for (const post of amaPosts.slice(0, 10)) {
const cr = await fetch(`${RD}/comments/${post.id}?limit=20&depth=1&sort=top&raw_json=1`, { headers: RD_H });
if (cr.ok) for (const c of ((await cr.json())[1]?.data?.children || [])) {
const body = c.data?.body || "";
if (body && body.includes("?") && body.length < 500) questions.push(body.trim());
}
await new Promise(r => setTimeout(r, 700));
}
// 2. Curate
const dedup = await fetch(`${MV_BASE}/mave/chat`, { method: "POST", headers: MV_H,
body: JSON.stringify({ message: `Deduplicate ${questions.length} AMA questions. Return 8 best.\n\n${questions.slice(0,50).map(q=>`- ${q.slice(0,200)}`).join("\n")}` }),
}).then(r => r.json());
let curated = (dedup.content || "").split("\n").filter(l => /[a-zA-Z]/.test(l))
.map(l => l.replace(/^\d+[\.\)]\s*/, "").trim()).slice(0, 8);
if (!curated.length) curated = ["Turning point?", "Biggest mistake?", "Pivot or push through?",
"Typical day?", "First 100 customers?", "Best advice?", "Do differently?", "Imposter syndrome?"];
// 3. Personas + Speak
const INTERVIEWEES = [
{ name: "Bootstrapped SaaS Founder", desc: "$5M ARR, no funding. Profitability > growth." },
{ name: "VC-Backed CEO", desc: "Series A ($8M). Team of 40. Scaling fast." },
{ name: "Solopreneur / Creator", desc: "$300K/yr digital products. Freedom > scale." },
];
for (const p of INTERVIEWEES) {
const persona = await fetch(`${MV_BASE}/personas`, { method: "POST", headers: MV_H,
body: JSON.stringify({ name: `AMA: ${p.name}`, description: p.desc }),
}).then(r => r.json());
const speak = await fetch(`${MV_BASE}/speak`, { method: "POST", headers: MV_H,
body: JSON.stringify({ persona_id: persona.id, mode: "interview",
input: [{ role: "system", content: `You are ${p.name} doing an AMA in /r/${SUB}. Answer candidly.` },
...curated.map(q => ({ role: "user", content: q }))],
}),
}).then(r => r.json());
console.log(`\n${"=".repeat(60)}\nAMA: ${p.name}\n${"=".repeat(60)}`);
for (const ex of speak.exchanges || speak.messages || []) {
if (ex.role === "user") console.log(`\n Q: ${ex.content.slice(0,150)}`);
else if (ex.role === "assistant") console.log(` A: ${ex.content.slice(0,350)}`);
}
}
Example Output
AMA: Bootstrapped SaaS Founder
Q: Turning point? A: Canceling freemium. Support dropped 70%, conversion tripled.
Q: Biggest mistake? A: VP Sales at $800K ARR. Burned $180K. Should've hired SDRs first.
AMA: Solopreneur / Creator
Q: First 100 customers? A: Reddit. 6 months answering niche sub questions.
"Here's what I built" thread → 40 sales week 1. No ads.
Error Handling
AMA availability
AMA availability
Broaden to “ask anything” or “Q&A” if results are sparse.
Speak limits
Speak limits
Split 8+ question interviews into two 4-question sessions.