Dê ao seu agente de IA um leitor de Twitter: definições de ferramenta para Claude, ChatGPT e Codex

Atualizado
Definições de ferramentas prontas para copiar que deixam Claude, ChatGPT ou Codex ler perfis, posts, respostas e buscas do X sem API key.
Em resumo: um agente precisa de quatro coisas para ler o X: uma URL que ele consiga montar a partir de um handle ou do link de um post, um corpo em JSON ou Markdown que ele consiga ler, um erro no qual ele consiga ramificar e um limite que ele consiga ver. Os endpoints
/tools/x/*da UnifAPI entregam as quatro grátis, sem fazer login, sem precisar de conta e sem chave de API, com limite por visitante, então uma definição de ferramenta é um único HTTP GET. Abaixo estão as definições para o tool use da Anthropic, o function calling da OpenAI e um SKILL.md para o Claude Code e o Codex, mais as três regras de que o modelo precisa: lerX-RateLimit-Remaining, dormir peloRetry-Aftere pedir Markdown quando o resultado vai direto para a janela de contexto.
Os modelos já sabem como ler o X. Pergunte ao Claude ou ao ChatGPT o que a @NASA postou nesta semana e eles vão tentar: uma busca na web, um fetch de x.com, talvez uma URL do Nitter vinda dos dados de treinamento. A busca devolve resumos, o fetch devolve uma casca em JavaScript e a instância do Nitter não existe mais. O modelo então chuta ou pede desculpas.
A solução não é um modelo mais inteligente, é uma ferramenta com uma URL que o modelo consiga construir e um corpo que ele consiga interpretar. Este post é essa ferramenta, nos três formatos que as pessoas realmente colocam em produção.
Os endpoints
Oito GETs, todos em https://unifapi.com/tools/x/, todos documentados com uma amostra capturada em /llms.txt:
| Endpoint | Parâmetros | Retorna |
|---|---|---|
profile | handle, posts (1–10), cursor | perfil, taxa de engajamento, posts recentes |
post | id (id ou URL) | um post com autor, mídia, post citado, métricas |
media | handle, cursor | os posts com foto e vídeo de uma conta |
replies | id, sort=top|recent, cursor | o post e suas respostas públicas |
search | q, cursor | posts recentes; os operadores de busca do X funcionam |
trends | location ou woeid | o que está em alta agora |
communities | q, cursor | Comunidades públicas do X para um tema |
followers | handle, kind=followers|following | quem segue uma conta, ou quem ela segue |
Toda lista é { items, hasMore, nextCursor }. Todo erro é { error: { type, message } }. Toda resposta traz X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset; um 429 acrescenta Retry-After. Adicione format=md para Markdown.
Tool use da Anthropic
Uma única ferramenta com um enum endpoint é mais simples para o modelo do que oito ferramentas, e os nomes dos parâmetros batem com os da API, então o modelo não tem como errá-los.
{
"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"]
}
}
O handler é uma linha de 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")) };
}
Devolver remaining ao modelo é intencional. Sabendo que tem 3 consultas restantes, o Claude para de paginar e responde com o que tem em vez de bater na parede.
Function calling da OpenAI
Mesmo formato, no invólucro da 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"]
}
}
}
Um SKILL.md para o Claude Code e o Codex
Agentes de programação não precisam de definição de ferramenta; precisam que alguém diga a eles que o padrão de URL existe. Um arquivo de skill no projeto faz isso:
---
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
Com esse arquivo presente, "veja o que a @NASA postou nesta semana e resuma as respostas ao post principal" vira dois curls que o agente escreve sozinho.
Três regras para o modelo
- Leia a contagem restante antes de paginar.
X-RateLimit-Remainingestá em toda resposta. Um perfil mais as respostas dele mais uma busca são 4 unidades de 20; um loop que pagina tudo gasta 20 unidades em um minuto. - Durma pelo
Retry-After, nunca tente de novo em loop. O corpo do 429 também informa a URL deupgrade; se a tarefa é maior do que o nível gratuito, é para lá que ela vai, com uma chave de workspace e os mesmos nomes de campo. - Peça Markdown quando o resultado for para leitura, JSON quando for para código.
format=mdrenderiza um perfil e seus posts em algumas centenas de tokens, sem o custo das aspas. JSON é para quando o modelo vai filtrar, ordenar ou passar os dados para outra ferramenta.
MCP
Se o agente já fala MCP, a API medida do X está no servidor MCP da UnifAPI com as mesmas operações (perfil, post, busca, respostas, seguidores e mais) atrás de uma chave de workspace, pay as you go. Os endpoints HTTP gratuitos acima são para o caso em que ainda não há chave, ou em que a tarefa é um punhado de leituras que não deveria precisar de uma.
FAQ
O Claude consegue ler o Twitter?
Com uma ferramenta, sim. O Claude não consegue carregar o x.com por conta própria (a página é uma casca em JavaScript), mas, com a ferramenta read_x acima, ele lê perfis, posts, respostas e resultados de busca em JSON e raciocina sobre eles.
O ChatGPT consegue ler tweets?
Mesma resposta: com a definição de function acima, em um GPT personalizado ou em um fluxo com Assistants. A navegação embutida do ChatGPT não consegue renderizar o x.com.
Isso precisa de chave de API?
Não. Os endpoints são grátis, sem chave, sem fazer login e sem precisar de conta, com limite por visitante: 20 consultas a cada 10 minutos, e uma busca conta como duas. A chave serve só para acesso medido, sem teto.
Existe limite para o que um agente pode fazer com os dados?
Os endpoints leem apenas dados públicos. Contas protegidas devolvem sua existência e suas contagens, nunca seus posts. Use os dados do jeito que os termos do X permitem para conteúdo público.