给你的 AI 智能体装一个 Twitter 阅读器:Claude、ChatGPT 和 Codex 的工具定义

给你的 AI 智能体装一个 Twitter 阅读器:Claude、ChatGPT 和 Codex 的工具定义
Unif Agents team
Unif Agents team

更新于

可直接复制的工具定义,让 Claude、ChatGPT 或 Codex 无需 API 密钥即可读取公开 X 资料、帖子、回复和搜索结果。

一句话总结:智能体读 X 需要四样东西:一个能从用户名或帖子链接拼出来的 URL、一个它能读的 JSON 或 Markdown 响应体、一个它能据以分支的错误,以及一个它看得见的限额。UnifAPI 的 /tools/x/* 端点四样都给,而且免费:无需登录、无需账号、无需 API 密钥,按访客限流,所以一个工具定义就是一次 HTTP GET。下面是 Anthropic 工具调用、OpenAI 函数调用的定义,以及给 Claude Code 和 Codex 用的 SKILL.md,外加模型需要的三条规则:读 X-RateLimit-Remaining,按 Retry-After 休眠,结果要直接进上下文窗口时就要 Markdown。

模型早就知道怎么读 X。问 Claude 或 ChatGPT @NASA 这周发了什么,它们会去试:网页搜索一下,抓一次 x.com,也许再拼一个训练数据里的 Nitter URL。搜索返回的是摘要,抓取返回的是一个 JavaScript 空壳,Nitter 实例早就没了。然后模型要么瞎猜,要么道歉。

解法不是更聪明的模型,而是一个工具:它的 URL 模型能拼出来,它的响应体模型能解析。本文就是这个工具,以人们真正会部署的三种格式给出。

端点

八个 GET,全在 https://unifapi.com/tools/x/ 下,每个都在 /llms.txt 里附有抓取的样例:

端点参数返回
profilehandle、posts(1–10)、cursor主页、互动率、近期帖子
postid(id 或 URL)一条帖子,含作者、媒体、引用的帖子、指标
mediahandle、cursor一个账号的照片和视频帖子
repliesid、sort=top|recent、cursor帖子及其公开回复
searchq、cursor近期帖子;支持 X 搜索运算符
trendslocation 或 woeid当前热搜
communitiesq、cursor某话题的公开 X 社区
followershandle、kind=followers|following谁在关注一个账号,或它关注了谁

每个列表都是 { items, hasMore, nextCursor }。每个错误都是 { error: { type, message } }。每个响应都带 X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset;429 另加 Retry-After。加 format=md 得到 Markdown。

Anthropic 工具调用

对模型来说,一个带 endpoint 枚举的工具比八个工具更简单,而且参数名与 API 一致,模型不会写错。

{
  "name": "read_x",
  "description": "Read public X (Twitter) data with no account: a profile and its recent posts, one post, an account's media, the replies under a post, a search over recent posts (X operators like from:, since:, min_faves:, filter:media work), trends by location, Communities by topic, or an account's followers/following. Free, rate-limited to 20 requests per 10 minutes; search costs 2. Returns JSON. Pass cursor from a previous result to page.",
  "input_schema": {
    "type": "object",
    "properties": {
      "endpoint": {
        "type": "string",
        "enum": [
          "profile",
          "post",
          "media",
          "replies",
          "search",
          "trends",
          "communities",
          "followers"
        ]
      },
      "handle": {
        "type": "string",
        "description": "X handle or profile URL (profile, media, followers)"
      },
      "id": { "type": "string", "description": "Post ID or x.com status URL (post, replies)" },
      "q": { "type": "string", "description": "Search query or Communities topic" },
      "location": {
        "type": "string",
        "description": "Trends location slug: worldwide, us, uk, japan, india, brazil, korea, germany, spain, mexico"
      },
      "sort": { "type": "string", "enum": ["top", "recent"] },
      "kind": { "type": "string", "enum": ["followers", "following"] },
      "cursor": { "type": "string" }
    },
    "required": ["endpoint"]
  }
}

处理函数就是一行 fetch:

async function readX(input: { endpoint: string } & Record<string, string | undefined>) {
  const { endpoint, ...params } = input;
  const qs = new URLSearchParams(Object.entries(params).filter(([, v]) => v) as [string, string][]);
  const res = await fetch(`https://unifapi.com/tools/x/${endpoint}?${qs}`, {
    headers: { Accept: "application/json" },
  });
  const body = await res.json();
  if (res.status === 429)
    return { error: body.error, retryAfterSeconds: Number(res.headers.get("Retry-After")) };
  return { ...body, remaining: Number(res.headers.get("X-RateLimit-Remaining")) };
}

把 remaining 返回给模型是刻意为之。被告知只剩 3 次查询后,Claude 会停止翻页,用手头的结果作答,而不是一头撞上限额。

OpenAI 函数调用

同样的形状,换成 OpenAI 的外壳:

{
  "type": "function",
  "function": {
    "name": "read_x",
    "description": "Read public X (Twitter) data with no account. endpoint=profile|post|media|replies|search|trends|communities|followers. Free, 20 requests per 10 minutes. Returns JSON with { items, hasMore, nextCursor } for lists.",
    "parameters": {
      "type": "object",
      "properties": {
        "endpoint": {
          "type": "string",
          "enum": [
            "profile",
            "post",
            "media",
            "replies",
            "search",
            "trends",
            "communities",
            "followers"
          ]
        },
        "handle": { "type": "string" },
        "id": { "type": "string" },
        "q": { "type": "string" },
        "location": { "type": "string" },
        "sort": { "type": "string", "enum": ["top", "recent"] },
        "kind": { "type": "string", "enum": ["followers", "following"] },
        "cursor": { "type": "string" }
      },
      "required": ["endpoint"]
    }
  }
}

给 Claude Code 和 Codex 的 SKILL.md

编码智能体不需要工具定义;它们只需要被告知这个 URL 模式存在。项目里放一个 skill 文件就行:

---
name: read-x
description: Read public X (Twitter) profiles, posts, replies, search, trends, communities, and followers as JSON or Markdown with no API key, via https://unifapi.com/tools/x/*. Use when a task needs what an account or post says on X.
---

# Reading X

All endpoints are GET https://unifapi.com/tools/x/<endpoint>. No key. Free limit 20 requests
per 10 minutes (search costs 2), printed in X-RateLimit-* headers; on 429 wait Retry-After.

- profile?handle=nasa profile + recent posts (+ posts=1-10, cursor)
- post?id=<id or x.com URL> one post
- media?handle=nasa photo/video posts
- replies?id=<id>&sort=top replies under a post (sort=recent for newest)
- search?q=from:nasa%20filter:media recent posts; X operators work
- trends?location=us trending now
- communities?q=ai X Communities
- followers?handle=nasa&kind=following

Add &format=md for Markdown when the result goes into context. Lists are { items, hasMore,
nextCursor }; pass cursor= to page. Errors are { error: { type, message } }.
Full reference with samples: https://unifapi.com/llms.txt

有了这个文件,"看看 @NASA 这周发了什么,并总结最热门那条帖子下的回复"就变成智能体自己写出的两条 curl。

给模型的三条规则

  1. 翻页前先读剩余次数。 X-RateLimit-Remaining 在每个响应上都有。一次主页加它的回复加一次搜索是 20 个单位里的 4 个;一个把所有东西都翻完的循环,一分钟就是 20 个单位。
  2. 按 Retry-After 休眠,绝不循环重试。 429 的响应体还写明了 upgrade URL;如果任务超出免费层,就该去那里,用工作区密钥,字段名不变。
  3. 结果是拿来读的就要 Markdown,拿来给代码用的就要 JSON。 format=md 用几百个 token 就能渲染一个主页及其帖子,没有引号带来的开销。JSON 用在模型要过滤、排序或把数据交给另一个工具的时候。

MCP

如果智能体已经会说 MCP,计量版 X API 在 UnifAPI MCP 服务器上提供同样的操作(主页、帖子、搜索、回复、关注者等),需要工作区密钥,按量付费。上面的免费 HTTP 端点适用于还没有密钥、或任务只是寥寥几次读取、本不该需要密钥的情况。

常见问题

Claude 能读 Twitter 吗?

有工具就能。Claude 自己加载不了 x.com(页面是个 JavaScript 空壳),但给它上面的 read_x 工具,它就能把主页、帖子、回复和搜索结果读成 JSON 并据此推理。

ChatGPT 能读推文吗?

同样的答案:用上面的函数定义,放在自定义 GPT 或 Assistants 工作流里。ChatGPT 内置的浏览功能渲染不了 x.com。

这需要 API 密钥吗?

不需要。这些端点免费使用,无需密钥、无需登录、无需账号,按访客限流:每 10 分钟 20 次查询,一次搜索计为两次。密钥只用于不设上限的计量访问。

智能体能用这些数据做的事有限制吗?

端点只读公开数据。受保护账号只返回它存在的事实和各项计数,绝不返回帖子。按 X 服务条款对公开内容的允许范围使用数据。