planning-user-interviews
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlanning user interviews
规划用户访谈
Use this skill when someone asks to set up a user interview — to talk to customers, check sentiment, or gather qualitative feedback through a voice conversation. The plan is captured as a that a voice agent will later run through.
UserInterviewTopic当有人要求设置用户访谈——与客户交流、了解用户情绪或通过语音对话收集定性反馈时,可使用本技能。访谈计划将被保存为,后续由Voice Agent执行。
UserInterviewTopicWhat a complete topic needs
完整主题所需内容
Before calling , gather these:
user-interview-topics-create- Who to interview — at least one of:
- — an existing cohort ID
interviewee_cohort - — list of email addresses
interviewee_emails - — list of PostHog distinct IDs
interviewee_distinct_ids
- What to ask about — (required free text)
topic - How the agent should frame the conversation — optional (extra system prompt)
agent_context - The questions to work through — optional ordered list
questions
The API rejects topics with no targeting, so at least one of the three audience fields must be set. They can be combined — a cohort plus a handful of extra emails is fine.
在调用接口前,需收集以下信息:
user-interview-topics-create- 访谈对象 — 至少包含以下一项:
- — 现有cohort的ID
interviewee_cohort - — 邮箱地址列表
interviewee_emails - — PostHog distinct IDs列表
interviewee_distinct_ids
- 访谈内容 — (必填自由文本)
topic - Agent对话框架 — 可选的(额外系统提示)
agent_context - 访谈问题清单 — 可选的有序列表
questions
API会拒绝未设置目标对象的主题,因此至少需填写上述三类受众字段中的一项。也可组合使用——比如同时选择一个cohort和额外几个邮箱是允许的。
Step 1: Clarify intent
步骤1:明确需求意图
If the request is vague, ask:
- Which feature or behavior? "checkout" might be the button click, the page view, or the payment submission — narrow it down to one event.
- What do you want to learn? Why they bounced? What confused them? What alternatives they tried? The goal shapes both the audience and the questions.
- Which kind of users? Heavy users (what works), drop-offs (what blocks adoption), at-risk users (what breaks retention), or a mix.
Skip these questions only when the user has already answered them.
若用户请求模糊,可询问以下问题:
- 针对哪个功能或行为? “checkout”可能指按钮点击、页面浏览或支付提交——需将范围缩小至单一事件。
- 您希望了解什么? 用户为何流失?什么让他们困惑?他们尝试过哪些替代方案?研究目标会影响受众选择和问题设计。
- 针对哪类用户? 重度用户(了解现有功能优势)、流失用户(了解阻碍因素)、高风险用户(了解影响留存的问题),还是混合群体?
仅当用户已明确回答这些问题时,才可跳过。
Step 2: Pick the audience
步骤2:选择受众群体
Map what the user said to one of these paths:
- They named a cohort ("our power users", "trial signups last week") — use filtered by name to find the cohort, confirm the match, and pass the cohort ID as
cohorts-list.interviewee_cohort - They described the kind of person but no cohort exists — offer to either create the cohort first () or fall back to finding people by behavior (see below).
cohorts-create - They gave email addresses or distinct IDs — accept them directly. Skip the cohort lookup.
- They described a behavior, not a cohort ("users who tried checkout but didn't finish", "people who used to use dark mode and stopped") — find them by querying their events (see below).
- They were vague ("a few customers", "some power users") — ask which they prefer:
- Pick an existing cohort →
cohorts-list - Look up specific persons by name or email → with a search query
persons-list - Find users by behavior → see below
- Paste a list of email addresses
- Pick an existing cohort →
Each email passes through DRF email validation (display-name format is accepted alongside plain ).
Paul D'Ambra <paul@x.com>paul@x.com根据用户描述匹配以下路径:
- 用户指定了cohort(如“我们的核心用户”“上周注册的试用用户”)——使用按名称筛选找到对应cohort,确认匹配后,将cohort ID作为
cohorts-list传入。interviewee_cohort - 用户描述了用户类型但无对应cohort——提供两种选择:先创建cohort(),或通过用户行为查找(见下文)。
cohorts-create - 用户提供了邮箱地址或distinct IDs——直接接收,跳过cohort查询。
- 用户描述了行为而非cohort(如“尝试过checkout但未完成的用户”“曾经使用深色模式但现已停用的用户”)——通过查询用户事件找到对应人群(见下文)。
- 用户描述模糊(如“几位客户”“一些核心用户”)——询问用户偏好:
- 选择现有cohort →
cohorts-list - 通过姓名或邮箱查找特定用户 → 使用搜索查询调用
persons-list - 通过用户行为查找 → 见下文
- 粘贴邮箱地址列表
- 选择现有cohort →
每个邮箱需通过DRF邮箱验证(支持显示名称格式,也支持纯邮箱格式)。
Paul D'Ambra <paul@x.com>paul@x.comFinding users by behavior
通过用户行为查找受众
When the user describes who they want to talk to in behavioral terms, find them in the project's own data:
- Find the right event. Call to list events that actually exist in the project. Don't guess event names from training data — PostHog event taxonomies are bespoke. Match the user's description to one or two candidate events; if multiple plausible matches exist, list them and ask which behavior they care about.
read-data-schema - Query for users. Call with HogQL. Filter by the chosen event over the last 60 days, group by person — prefer
execute-sql(directly usable asperson.properties.email), fall back tointerviewee_emails(fordistinct_id). Keep both kinds of rows. The aggregates in each template (interviewee_distinct_ids,event_count,last_seen) are what feed Step 5's per-interviewee context. Replacedays_since_last_seenwith the chosen event, and<event_name>with<id>orperson.properties.email:distinct_id- Heavy users —
SELECT <id> AS id, count() AS event_count, max(timestamp) AS last_seen, dateDiff('day', max(timestamp), now()) AS days_since_last_seen FROM events WHERE event = '<event_name>' AND timestamp > now() - INTERVAL 60 DAY GROUP BY <id> HAVING count() >= 5 ORDER BY count() DESC LIMIT 20 - Drop-offs (tried once or twice and never came back) —
SELECT <id> AS id, count() AS event_count, max(timestamp) AS last_seen, dateDiff('day', max(timestamp), now()) AS days_since_last_seen FROM events WHERE event = '<event_name>' AND timestamp > now() - INTERVAL 60 DAY GROUP BY <id> HAVING count() <= 2 AND dateDiff('day', max(timestamp), now()) > 14 ORDER BY count() ASC LIMIT 20 - At-risk (was active, now dormant) —
SELECT <id> AS id, count() AS event_count, max(timestamp) AS last_seen, dateDiff('day', max(timestamp), now()) AS days_since_last_seen FROM events WHERE event = '<event_name>' AND timestamp > now() - INTERVAL 60 DAY GROUP BY <id> HAVING count() >= 3 AND dateDiff('day', max(timestamp), now()) > 14 ORDER BY days_since_last_seen DESC LIMIT 20
- Heavy users —
- Build a balanced sample. Unless the user asked for one specific segment, mixing 5 heavy users + 3 drop-offs + 2 at-risk users yields the most actionable interviews: you learn what works, what blocks adoption, and what breaks retention. Adjust counts to match what the user actually wants.
Pass the email rows as and the distinct-ID rows as — both can be set on the same topic. Keep and per person so Step 5 can synthesise context like "used checkout 47 times in last 60 days; last seen 2 days ago".
interviewee_emailsinterviewee_distinct_idsevent_countdays_since_last_seen当用户以行为描述目标访谈对象时,需从项目自身数据中查找:
- 找到对应事件——调用列出项目中实际存在的事件。不要根据训练数据猜测事件名称——PostHog的事件分类是定制化的。将用户描述匹配到1-2个候选事件;若存在多个合理匹配,列出所有选项并询问用户关注的具体行为。
read-data-schema - 查询用户——使用HogQL调用。筛选过去60天内的目标事件,按用户分组——优先使用
execute-sql(可直接作为person.properties.email),其次是interviewee_emails(作为distinct_id)。保留两类数据。模板中的聚合字段(interviewee_distinct_ids、event_count、last_seen)将用于步骤5的单用户上下文生成。将days_since_last_seen替换为选定事件,<event_name>替换为<id>或person.properties.email:distinct_id- 重度用户 —
SELECT <id> AS id, count() AS event_count, max(timestamp) AS last_seen, dateDiff('day', max(timestamp), now()) AS days_since_last_seen FROM events WHERE event = '<event_name>' AND timestamp > now() - INTERVAL 60 DAY GROUP BY <id> HAVING count() >= 5 ORDER BY count() DESC LIMIT 20 - 流失用户(尝试1-2次后未再使用) —
SELECT <id> AS id, count() AS event_count, max(timestamp) AS last_seen, dateDiff('day', max(timestamp), now()) AS days_since_last_seen FROM events WHERE event = '<event_name>' AND timestamp > now() - INTERVAL 60 DAY GROUP BY <id> HAVING count() <= 2 AND dateDiff('day', max(timestamp), now()) > 14 ORDER BY count() ASC LIMIT 20 - 高风险用户(曾活跃现已休眠) —
SELECT <id> AS id, count() AS event_count, max(timestamp) AS last_seen, dateDiff('day', max(timestamp), now()) AS days_since_last_seen FROM events WHERE event = '<event_name>' AND timestamp > now() - INTERVAL 60 DAY GROUP BY <id> HAVING count() >= 3 AND dateDiff('day', max(timestamp), now()) > 14 ORDER BY days_since_last_seen DESC LIMIT 20
- 重度用户 —
- 构建均衡样本——除非用户明确要求单一细分群体,否则混合5位重度用户+3位流失用户+2位高风险用户能获得最具价值的访谈结果:既了解现有优势,也能发现阻碍 adoption 和影响留存的问题。可根据用户实际需求调整数量。
将邮箱数据作为传入,distinct ID数据作为传入——同一主题可同时设置这两个字段。保留每位用户的和,以便步骤5生成如“过去60天内使用checkout 47次;最后一次访问是2天前”的上下文信息。
interviewee_emailsinterviewee_distinct_idsevent_countdays_since_last_seenStep 3: Capture the topic
步骤3:确定访谈主题
topicExample: "ask trial users why they didn't convert" → .
topic: "Why trial users didn't convert in the first 14 days"topic示例:“询问试用用户为何未转化” → 。
topic: "为何试用用户在最初14天内未转化"Step 4: Prepare the voice agent
步骤4:准备Voice Agent
Two fields shape what the agent actually does on the call. Always ask about both before creating the topic.
以下两个字段决定Agent在通话中的实际行为。创建主题前务必询问这两项内容。
Always ask: what questions do they want to ask?
必问:希望Agent提出哪些问题?
questions- ✅ "What made you decide to try PostHog?"
- ❌ "Did you like PostHog?"
If the user already listed questions in their original request, use those and confirm. Otherwise, ask explicitly: "What questions do you want the agent to ask?"
If the user can't think of any, suggest 3–5 open-ended questions drawn from the and offer them for review before creating.
topicThe field is technically optional in the API, but don't skip it silently — an interview with no questions is rarely useful.
Question templates by research goal:
- Why users dropped off / churned:
- "Tell me about the last time you tried [feature] — what were you trying to do?"
- "Walk me through what happened step-by-step."
- "What did you expect vs what actually happened?"
- "What made you stop or decide not to continue?"
- "What would need to change for you to use [feature] regularly?"
- Why heavy users love a feature:
- "Tell me about how you use [feature] — what problem does it solve for you?"
- "Walk me through your typical workflow."
- "What would you do if [feature] didn't exist?"
- "What almost made you not use it when you first tried?"
- "What's one thing you wish it did differently?"
- Why someone hasn't tried a feature yet:
- "Have you noticed [feature] in the product?"
- "What's stopped you from trying it?"
- "What would have to be true for it to be worth trying?"
questions- ✅ “是什么让您决定尝试PostHog?”
- ❌ “您喜欢PostHog吗?”
若用户在初始请求中已列出问题,直接使用并确认。否则,明确询问:“您希望Agent提出哪些问题?”
若用户无法想出问题,根据建议3-5个开放式问题,供用户审核确认后再创建主题。
topic该字段在API中是可选的,但请勿跳过——没有问题的访谈几乎毫无价值。
按研究目标分类的问题模板:
- 用户为何流失/ churned:
- “请告诉我您最后一次尝试[功能]的经历——您当时想完成什么操作?”
- “请一步步告诉我发生了什么。”
- “您的预期与实际情况有何不同?”
- “是什么让您停止使用或决定不再继续?”
- “需要做出哪些改变才能让您定期使用[功能]?”
- 重度用户为何喜爱某功能:
- “请告诉我您如何使用[功能]——它为您解决了什么问题?”
- “请描述您的典型工作流程。”
- “如果[功能]不存在,您会怎么做?”
- “您初次尝试时,是什么差点让您放弃使用它?”
- “您希望它在哪些方面有所改进?”
- 用户为何尚未尝试某功能:
- “您注意到产品中的[功能]了吗?”
- “是什么阻止您尝试它?”
- “满足什么条件才值得您尝试?”
Always offer: extra context to guide the interview
必选:提供引导访谈的额外上下文
agent_context"Want to give the agent any extra context? Things like tone, what to avoid, or background on the interviewee help guide the conversation. It's optional."
Useful kinds of context:
- Tone: "warm and conversational", "skip pleasantries — this is a 10-minute call"
- Constraints: "don't promise feature delivery", "do not discuss pricing"
- Background the agent should know: "the user just churned from the Scale plan; be empathetic", "this person tried PostHog 6 months ago and bounced"
- Persona: "you are Sam, a PostHog product researcher"
If the user declines, that's fine — leave empty and continue.
agent_contextagent_context“是否需要为Agent提供额外上下文?诸如语气、需避免的内容或访谈对象背景等信息,有助于引导对话。该字段为可选。”
有用的上下文类型:
- 语气:“热情且口语化”“跳过寒暄——这是10分钟的通话”
- 约束:“不要承诺功能上线”“请勿讨论定价”
- Agent需了解的背景:“用户刚从Scale套餐流失;需保持同理心”“该用户6个月前尝试过PostHog后就不再使用”
- 角色设定:“您是Sam,PostHog的产品研究员”
若用户拒绝填写,无需处理——保持为空即可继续。
agent_contextCalling user-interview-topics-create
调用user-interview-topics-create接口
Once you have the pieces:
json
{
"topic": "Why trial users churned in week 2",
"interviewee_cohort": 42,
"interviewee_emails": ["paul@acme.com"],
"agent_context": "Be warm. The interviewee just churned — don't pitch.",
"questions": [
"What were you hoping PostHog would help with?",
"Where did you get stuck?",
"What would have made you stay?"
]
}After creation, capture the returned topic ID — you'll need it for Step 5 and for handing off to the voice agent.
收集完所有信息后:
json
{
"topic": "Why trial users churned in week 2",
"interviewee_cohort": 42,
"interviewee_emails": ["paul@acme.com"],
"agent_context": "Be warm. The interviewee just churned — don't pitch.",
"questions": [
"What were you hoping PostHog would help with?",
"Where did you get stuck?",
"What would have made you stay?"
]
}创建完成后,记录返回的主题ID——步骤5及交接给Voice Agent时会用到。
Step 5: Optionally attach per-interviewee context
步骤5:可选添加单用户上下文
The topic-level applies to every interviewee. If the user knows something specific about individual interviewees that should shape that one conversation, attach it as a per-interviewee row via . This is optional — most topics won't need it.
agent_contextuser-interview-topics-interviewees-createEach row pairs an (must match one of the emails or distinct IDs in the parent topic's targeting) with an string. At most one row per (topic, interviewee). A user can have zero rows.
interviewee_identifieragent_contextGood per-interviewee context looks like:
- "uses the replay product but has never used summarization"
- "churned from Scale plan last month — be empathetic, don't pitch"
- "founder, very technical, skip basic product explanations"
After Step 4 succeeds, ask the user: "Want to add per-interviewee context? Useful when individual people have very different backgrounds. You can either dictate the rows or paste a CSV."
If you found the audience via behavioral query in Step 2, you already have per-person context (usage counts, dormancy windows). Use it: e.g. for heavy users, for drop-offs.
"used checkout 47 times in last 60 days; last seen 2 days ago""tried checkout once 18 days ago, never returned"主题级别的适用于所有访谈对象。若用户了解个别访谈对象的特定信息,且这些信息会影响对应对话,可通过接口为单个访谈对象添加上下文。这是可选操作——大多数主题无需此步骤。
agent_contextuser-interview-topics-interviewees-create每条记录将(必须与父主题目标对象中的邮箱或distinct ID匹配)与字符串配对。每个(主题,访谈对象)最多对应一条记录,用户也可无对应记录。
interviewee_identifieragent_context优质的单用户上下文示例:
- “使用replay产品但从未使用summarization功能”
- “上月从Scale套餐流失——保持同理心,不要推销”
- “创始人,技术背景深厚,跳过基础产品讲解”
步骤4完成后,询问用户:“是否需要添加单用户上下文?当个别用户背景差异较大时非常有用。您可以口述记录内容或粘贴CSV文件。”
若步骤2中通过行为查询找到受众,您已拥有单用户上下文(使用次数、休眠时长)。可直接使用:例如,重度用户的上下文为“过去60天内使用checkout 47次;最后一次访问是2天前”,流失用户的上下文为“18天前尝试过一次checkout,之后未再返回”。
Accepting CSV input
接收CSV输入
If the user pastes a CSV, expect two columns: . Either with or without a header row. Examples:
identifier,contextcsv
paul@acme.com,uses replay but never summarization
steve@apple.com,founder; very technical; skip product basicsOr with a header:
csv
identifier,context
abc-distinct-id-1,churned from Scale last month — be empatheticParse the CSV, then call once per row with the captured . Skip blank lines. Quote-escape commas inside the context cell — standard CSV rules.
user-interview-topics-interviewees-createtopic_idIf a row's identifier isn't present in the parent topic's or , warn the user before creating — the voice agent looks up context by exact string match, so a mismatched identifier just gets ignored at runtime.
interviewee_emailsinterviewee_distinct_ids若用户粘贴CSV文件,预期包含两列:。可包含或不包含表头行。示例:
identifier,contextcsv
paul@acme.com,uses replay but never summarization
steve@apple.com,founder; very technical; skip product basics或带表头:
csv
identifier,context
abc-distinct-id-1,churned from Scale last month — be empathetic解析CSV文件后,针对每一行调用接口,传入已记录的。跳过空行。上下文单元格中的逗号需使用引号转义——遵循标准CSV规则。
user-interview-topics-interviewees-createtopic_id若某行的identifier未出现在父主题的或中,创建前需提醒用户——Voice Agent会通过精确字符串匹配查找上下文,不匹配的identifier在运行时会被忽略。
interviewee_emailsinterviewee_distinct_idsEdge cases
边缘情况
- No users match the behavioral query. Possible reasons: the event isn't firing, the date range is too narrow, or no users have email addresses captured as person properties. Offer to widen the date range, try a different event, or fall back to cohorts / explicit emails.
- Users matched but few have emails. PostHog stores whatever the SDK captures. If only a handful of matching users have email addresses on their person profile, surface the count and ask: take the smaller sample, fall back to (the agent can still reach them via in-app delivery), or skip the behavioral query and let the user paste emails directly.
interviewee_distinct_ids - Ambiguous event name. If returns multiple candidates (e.g.
read-data-schema,checkout_started,checkout_completed), list them with counts and let the user pick the behavior they want to understand. Don't pick silently.checkout_abandoned - User asks to interview only drop-offs (or only one segment). That works, but flag the tradeoff: interviewing only drop-offs tells you what's broken without telling you what works. Recommend including 2–3 successful users for contrast unless the user has a reason for the narrower sample.
- 行为查询未匹配到用户:可能原因包括事件未触发、日期范围过窄或无用户的person属性中包含邮箱地址。建议扩大日期范围、尝试其他事件,或改用cohort/明确邮箱。
- 匹配到用户但少数有邮箱:PostHog存储SDK捕获的所有数据。若仅少数匹配用户的person资料中包含邮箱地址,需告知用户数量并询问:选择较小样本、改用(Agent仍可通过应用内推送联系用户),或跳过行为查询让用户直接粘贴邮箱。
interviewee_distinct_ids - 事件名称模糊:若返回多个候选事件(如
read-data-schema、checkout_started、checkout_completed),列出所有选项及对应数量,让用户选择需了解的行为。请勿自行选择。checkout_abandoned - 用户要求仅访谈流失用户(或单一细分群体):这是允许的,但需告知用户利弊:仅访谈流失用户只能了解问题所在,无法了解现有优势。建议加入2-3位成功用户作为对比,除非用户有明确理由选择更窄的样本。
What this skill is not for
本技能不适用场景
- Uploading a recorded interview — that's the separate model (
UserInterviewwith an audio file). Different flow, different model.user_interviews_create - Listing existing topics — handles that directly with
user-interview-topics-list,search, andlimit. No skill needed.offset - Analyzing transcripts after the interview — out of scope here; that lives with the recorded flow.
UserInterview
- 上传已录制的访谈音频——属于独立的模型(通过
UserInterview接口上传音频文件)。流程不同,模型不同。user_interviews_create - 列出现有主题——可直接通过
user-interview-topics-list、search和limit参数处理,无需使用本技能。offset - 访谈后分析转录文本——超出本技能范围;属于已录制的流程的功能。",
UserInterview