Felo API PlatformFelo API Platform

研究

在压库存之前研究一个产品细分

先拿到品类背景,在明确日期抓取竞品页面,读买家在 X 上抱怨什么,再把证据和备忘录存进一个 LiveDoc,下单前还能回来看。

构建时间30 分钟难度进阶更新于2026-10-30
适合谁电商运营产品研究员DTC 创始人

复制 prompt

把方括号里的字段替换掉,然后粘贴到 Claude Code、Codex 或任何能访问终端的 AI。它会安装 Felo skill、在花额度前询问,并执行这套 workflow。

在备货或发布之前,调研这个产品细分:[产品或品类]。

市场:[国家或地区]。渠道:[电商平台 / DTC / 零售]。买家发帖时间范围:过去 [30] 天。
可比产品或竞品 URL:[URL]。预算和毛利约束:[约束]。读者:[团队]。

输出一份 Markdown 备忘录,包含:
1. 一段式结论:是否值得继续研究,以及什么会改变你的判断。
2. 需求信号:来源对兴趣、季节性和替代品怎么说。
3. 竞争产品:各自宣称什么、页面上采集到的价格、买家说它哪里不足。
4. 价格定位:页面上实际找到的价格点,每个都附采集日期。
5. 买家抱怨和未满足需求,附引文、账号和日期。
6. 备货前需要解决的风险和开放问题。
7. 来源:用到的每个页面和帖子,附 URL 和日期。

规则:
- 只使用 API 返回的内容。不要编造市场规模、销量估计、评论数或竞品价格。
- 按采集到的原样报告价格,附页面 URL 和采集日期。不要取平均或做归一化。
- 把 X 帖子当作轶事,不是市场数据;样本太薄时要说明。
- 区分厂商宣称和买家反馈。
- 消耗额度前,先展示计划执行的抽取和搜索并等待我批准。
- 不要联系供应商、下订单,或在 X 上给任何人发消息。
- 将结果写入 ./product-research.md,并在对话中总结。

复制的内容也包含安装步骤和安全规则。

你会得到什么

一次运行的示例输出,不是实时生成。

备忘录示例(节选)

产品调研 — 示例品类

结论

值得进一步研究,但公开证据不足以做库存决策。下面的开放问题是下一步。

品类背景

买家比较的是台面空间和清洁难度,而不是压力。没有公开来源支持市场规模估计。

竞品页面

  • Example A — 产品页(2026-10-30 采集)
  • Example B — 产品页(2026-10-30 采集)

买家反馈

  • @example_buyer:“一年换第三次;密封圈会坏。” — 2026-10-19
  • @example_home:“清洁要花几分钟,没人提这一点。” — 2026-10-24

价格定位

价格于 2026-10-30 从链接页面采集。分为两档;每个页面直接引用,没有取平均。

风险和开放问题

  • 密封圈耐用性是最反复出现的投诉。
  • 没有来源覆盖退货率。
  • 下单前确认供应商交期和到岸成本。

来源

  • https://example.com/product-a — 2026-10-30
  • https://x.com/example_buyer/status/... — 2026-10-19

实际调用

给开发者:同一套 workflow 的可复制代码,按执行顺序排列。

展开实际 API 调用
  1. 向 Chat 要品类图景

    从有来源的答案开始,而不是一张白纸:Chat 搜索公开网络、给页面排序并返回用过的资源。一次问清需求背景、替代品和常见抱怨,然后把最相关的资源保留为证据列表。下面的 helper 只发送一次 Key,非 2xx 响应会抛错。

    product-research.ts
    const BASE = "https://openapi.felo.ai";
    const headers = {
      Authorization: `Bearer ${process.env.FELO_API_KEY}`,
      "Content-Type": "application/json",
    };
    
    async function felo<T>(path: string, body?: unknown): Promise<T> {
      const res = await fetch(`${BASE}${path}`, {
        method: body ? "POST" : "GET",
        headers,
        body: body ? JSON.stringify(body) : undefined,
      });
      if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
      return res.json() as Promise<T>;
    }
    
    type ChatData = {
      data: {
        answer: string;
        resources: { link: string; title: string; snippet: string }[];
      };
    };
    
    const niche = "portable espresso maker"; // replace with the category you are judging
    
    const context = await felo<ChatData>("/v2/chat", {
      query: `Demand, price bands, and buyer complaints for ${niche} in the US`,
    });
    
    const sources = context.data.resources.slice(0, 5);

    示例输出

    {
      "answer": "Buyers compare on counter space and cleanup …",
      "sources": [
        { "link": "https://example.com/category-guide", "title": "…", "snippet": "…" }
      ]
    }
  2. 抓取竞品页面

    用 readability 把两三个竞品商品页抽成 Markdown。目标是页面今天的主张和价格,而不是改写过的规格表。把 URL 和内容放在一起,并在备忘录里记录抓取日期——没有日期的价格只是传闻。

    product-research.ts
    const PRODUCT_PAGES = [
      { url: "https://example.com/product-a", title: "Example A — product page" },
      { url: "https://example.com/product-b", title: "Example B — product page" },
    ];
    
    type ExtractData = { data: { content: string } };
    
    const listings = await Promise.all(
      PRODUCT_PAGES.map((page) =>
        felo<ExtractData>("/v2/web/extract", {
          url: page.url,
          output_format: "markdown",
          with_readability: true,
        }).then((extracted) => ({ ...page, content: extracted.data.content })),
      ),
    );

    示例输出

    [
      {
        "url": "https://example.com/product-a",
        "title": "Example A — product page",
        "content": "# Example A\n\nSpecs and price as displayed…"
      }
    ]
  3. 读买家在 X 上的反馈

    厂商页面列功能,买家描述失败。搜索品类加上买家遇到问题时的摩擦词——物流、质量、退款——限定最近 30 天,并保留账号、日期和帖子链接。这些帖子是轶事,不是需求数据,备忘录必须说明。

    product-research.ts
    type XData = {
      data: {
        tweets: {
          content: string;
          author: { username: string };
          created_at: string;
          metrics: { retweet_count: number; favorite_count: number; reply_count: number };
          url: string;
        }[];
      };
    };
    
    const since = Math.floor((Date.now() - 30 * 24 * 60 * 60 * 1000) / 1000);
    
    const search = await felo<XData>("/v2/x/tweet/search", {
      query: `"${niche}" (shipping OR quality OR refund)`,
      limit: 50,
      since_time: since,
    });
    
    const complaints = search.data.tweets;

    示例输出

    { "data": { "tweets": [
      {
        "content": "Third replacement in a year; the seal fails.",
        "author": { "username": "example_buyer" },
        "created_at": "2026-10-19T15:02:00Z",
        "metrics": { "retweet_count": 1, "favorite_count": 12, "reply_count": 3 },
        "url": "https://x.com/example_buyer/status/..."
      }
    ] } }
  4. 写备忘录

    这一步是普通代码:把品类答案、抓取日期、买家引语和来源列表拼成一段 Markdown。开放问题部分要诚实——备忘录有用,正是因为它把页面能证明的东西和还需要向供应商确认的东西分开。

    product-research.ts
    const capturedOn = new Date().toISOString().slice(0, 10);
    
    const memo = [
      `# Product research — ${niche}`,
      "",
      "## Category context",
      context.data.answer,
      "",
      "## Competitor pages",
      ...listings.map(
        (page) => `- [${page.title}](${page.url}) — captured ${capturedOn}`,
      ),
      "",
      "## What buyers report",
      ...complaints.slice(0, 10).map(
        (post) =>
          `- @${post.author.username} (${post.created_at.slice(0, 10)}): ${post.content}`,
      ),
      "",
      "## Sources",
      ...sources.map((source) => `- [${source.title}](${source.link})`),
    ].join("\n");
    
    console.log(memo);
  5. 把证据存进 LiveDoc

    每个细分跑一次:创建 LiveDoc,把 short_id 存进配置。把竞品页面和 Chat 来源作为 URL 资源加进去,归档会自动去重,再把备忘录作为文档资源加进去。下单前可以检索抓取结果,看看备忘录写完之后哪些价格变了。

    product-research.ts
    type LiveDocData = { data: { short_id: string } };
    
    const research = await felo<LiveDocData>("/v2/livedocs", {
      name: `Product research: ${niche}`,
      description: "Competitor pages, buyer posts, and the memo",
    });
    
    await felo(`/v2/livedocs/${research.data.short_id}/resources/urls`, {
      urls: [
        ...listings.map((page) => ({ url: page.url, title: page.title })),
        ...sources.map((source) => ({ url: source.link, title: source.title })),
      ].slice(0, 10),
    });
    
    await felo(`/v2/livedocs/${research.data.short_id}/resources/doc`, {
      title: `Product memo — ${capturedOn}`,
      content: memo,
    });

    示例输出

    { "short_id": "PvyKouzJirXjFdst4uKRK3" }

包含什么

  • 来自 Chat 的有来源品类图景,以及背后的页面
  • 在明确日期抓取的竞品商品页 Markdown
  • X 上带账号、日期和链接的买家抱怨
  • 由这些输入拼成的 Markdown 备忘录
  • 一个同时保存证据和备忘录的 LiveDoc

不做什么

  • 只覆盖公开来源;付费市场报告、供应商报价和内部销售数据不在范围内
  • 不估算市场规模、销量或毛利
  • 价格按抓取结果记录,绝不做归一化或平均
  • X 帖子是轶事,不是需求数据
  • 不联系供应商、不下单、不改 listing

常见问题

市场背景从哪里来?

Chat API 返回有来源的答案及其使用的公开页面。竞品页面来自你提供的 URL,用 Web Fetch 抽取;买家帖子来自 X Search。不涉及私有销售数据。

它能告诉我一个产品会不会卖爆吗?

不能。它整理公开证据——品类背景、抓取价格和买家抱怨——并写下未知项。需求验证仍然需要你自己的数据,比如广告、预售或供应商沟通。

如果平台阻止抓取怎么办?

Web Fetch 逐个 URL 抓公开页面,有些站点会拦截。换一个你能访问的商品或供应商页面,让备忘录明确标出缺失的抓取,而不是猜价格。

怎么避免竞品价格过时?

备忘录里的每个价格都绑定页面 URL 和抓取日期。下单前重新跑一次抽取;归档会保留更早的抓取,能看出价格动过。

它会联系供应商或卖家吗?

不会。workflow 是只读的:抓页面、搜公开帖子、写本地备忘录。它从不发消息、下单或修改 listing。

一次研究要花多少?

每次 Chat、页面抽取和 X 搜索都会消耗按量计费的额度;当前费率在价格页面。prompt 会在这些调用运行前请求确认。

相关 workflow

改成你的版本

同一套配方,按你实际的交付方式调整。

加入评测视频转录

品类里有评测视频时,用 YouTube Subtitling 拉转录,并在买家部分加两三条带时间戳的引语。视频评测仍然是一个人的体验,所以沿用 X 帖子的轶事标签。

把两个候选并排比较

对每个候选跑同样的步骤,把备忘录并排看:宣称功能、抓取价格、反复出现的抱怨和开放问题。在拿到自己的销售或退货数据之前,比较保持定性,这才是诚实的排序方式。

下单前刷新

下单前一天重跑页面抽取。保留同一个 LiveDoc,新增一份备忘录文档,这样归档能看出桌面研究和真正下单之间发生了什么——包括涨出预算的价格。

这套配方背后的参考页面,以及下一步可以看什么。