Geben Sie Ihrem KI-Agent einen Twitter-Reader: Tool-Definitionen für Claude, ChatGPT und Codex

Aktualisiert
Tool-Definitionen zum Kopieren, mit denen Claude, ChatGPT oder Codex öffentliche X-Profile, Posts, Antworten und Suche ohne API-Key lesen.
Kurz gesagt: Ein Agent braucht vier Dinge, um X zu lesen: eine URL, die er aus einem Handle oder einem Post-Link bauen kann, einen JSON- oder Markdown-Body, den er lesen kann, einen Fehler, nach dem er verzweigen kann, und ein Limit, das er sehen kann. Die
/tools/x/*-Endpoints auf UnifAPI liefern alle vier kostenlos, ohne Login, ohne Account und ohne API-Key, pro Besucher begrenzt, eine Tool-Definition ist also ein einziges HTTP GET. Unten stehen die Definitionen für Tool Use von Anthropic, Function Calling von OpenAI und eine SKILL.md für Claude Code und Codex, dazu die drei Regeln, die das Modell braucht:X-RateLimit-Remaininglesen, beiRetry-Afterwarten und Markdown anfordern, wenn das Ergebnis direkt ins Kontextfenster wandert.
Modelle wissen bereits, wie man X liest. Fragt man Claude oder ChatGPT, was @NASA diese Woche gepostet hat, versuchen sie es: eine Websuche, ein Abruf von x.com, vielleicht eine Nitter-URL aus den Trainingsdaten. Die Suche liefert Zusammenfassungen, der Abruf liefert eine JavaScript-Hülle, und die Nitter-Instanz gibt es nicht mehr. Dann rät das Modell oder entschuldigt sich.
Die Lösung ist kein klügeres Modell, sondern ein Tool mit einer URL, die das Modell konstruieren kann, und einem Body, den es parsen kann. Dieser Beitrag ist dieses Tool, in den drei Formaten, die tatsächlich im Einsatz sind.
Die Endpoints
Acht GETs, alle unter https://unifapi.com/tools/x/, alle mit einer aufgezeichneten Beispielantwort in /llms.txt dokumentiert:
| Endpoint | Parameter | Liefert |
|---|---|---|
profile | handle, posts (1–10), cursor | Profil, Engagement-Rate, aktuelle Posts |
post | id (id oder URL) | einen Post mit Autor, Medien, zitiertem Post, Metriken |
media | handle, cursor | die Foto- und Video-Posts eines Accounts |
replies | id, sort=top|recent, cursor | den Post und seine öffentlichen Antworten |
search | q, cursor | aktuelle Posts; die Suchoperatoren von X funktionieren |
trends | location oder woeid | was gerade im Trend liegt |
communities | q, cursor | öffentliche X Communities zu einem Thema |
followers | handle, kind=followers|following | wer einem Account folgt oder wem er folgt |
Jede Liste ist { items, hasMore, nextCursor }. Jeder Fehler ist { error: { type, message } }. Jede Antwort trägt X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset; ein 429 ergänzt Retry-After. Mit format=md kommt Markdown.
Tool Use von Anthropic
Ein einziges Tool mit einem endpoint-Enum ist für das Modell einfacher als acht Tools, und die Parameternamen entsprechen der API, sodass das Modell sie nicht falsch wählen kann.
{
"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"]
}
}
Der Handler ist eine Zeile 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")) };
}
Dass remaining an das Modell zurückgeht, ist Absicht. Weiß Claude, dass noch 3 Abrufe übrig sind, hört es auf zu blättern und antwortet mit dem, was es hat, statt gegen die Wand zu laufen.
Function Calling von OpenAI
Dieselbe Form, im Wrapper von 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"]
}
}
}
Eine SKILL.md für Claude Code und Codex
Coding-Agents brauchen keine Tool-Definition; sie müssen nur wissen, dass es das URL-Muster gibt. Eine Skill-Datei im Projekt erledigt das:
---
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
Liegt diese Datei vor, werden aus „schau nach, was @NASA diese Woche gepostet hat, und fasse die Antworten auf den Top-Post zusammen“ zwei curl-Aufrufe, die der Agent selbst schreibt.
Drei Regeln für das Modell
- Vor dem Blättern den Restwert lesen.
X-RateLimit-Remainingsteht in jeder Antwort. Ein Profil plus seine Antworten plus eine Suche sind 4 von 20 Einheiten; eine Schleife, die alles durchblättert, verbraucht 20 Einheiten in einer Minute. - Bei
Retry-Afterwarten, nie in einer Schleife neu versuchen. Der 429-Body nennt auch dieupgrade-URL; ist die Aufgabe größer als der kostenlose Tarif, geht es dorthin, mit einem Workspace-Key und denselben Feldnamen. - Markdown anfordern, wenn das Ergebnis gelesen wird, JSON, wenn es in Code weiterverarbeitet wird.
format=mdrendert ein Profil und seine Posts in ein paar hundert Tokens ohne Quoting-Overhead. JSON ist für den Fall, dass das Modell filtern, sortieren oder die Daten an ein anderes Tool weiterreichen will.
MCP
Spricht der Agent bereits MCP, steht die abgerechnete X API auf dem UnifAPI-MCP-Server mit denselben Operationen (Profil, Post, Suche, Antworten, Follower und mehr) hinter einem Workspace-Key bereit, nutzungsbasiert (Pay as you go). Die kostenlosen HTTP-Endpoints oben sind für den Fall, dass es noch keinen Key gibt oder die Aufgabe eine Handvoll Lesezugriffe ist, die keinen brauchen sollte.
FAQ
Kann Claude Twitter lesen?
Mit einem Tool ja. Claude kann x.com selbst nicht laden (die Seite ist eine JavaScript-Hülle), aber mit dem read_x-Tool oben liest es Profile, Posts, Antworten und Suchergebnisse als JSON und argumentiert darüber.
Kann ChatGPT Tweets lesen?
Dieselbe Antwort: mit der Function-Definition oben, in einem Custom GPT oder einem Assistants-Workflow. Das eingebaute Browsing von ChatGPT kann x.com nicht rendern.
Braucht das einen API-Key?
Nein. Die Endpoints sind kostenlos nutzbar, ohne Key, Login oder Account, und pro Besucher begrenzt: 20 Abfragen pro 10 Minuten, wobei eine Suche als zwei zählt. Ein Key ist nur für abgerechneten Zugriff ohne Obergrenze nötig.
Gibt es Grenzen dafür, was ein Agent mit den Daten tun darf?
Die Endpoints lesen ausschließlich öffentliche Daten. Geschützte Accounts liefern ihre Existenz und ihre Zahlen, nie ihre Posts. Die Daten sind so zu nutzen, wie es die Nutzungsbedingungen von X für öffentliche Inhalte erlauben.