Querying GraphQL APIs: selection sets, variables, fragments, cursor pagination, introspection, and error handling for agents fetching data from GraphQL endpoints. Triggers on: query a GraphQL API, write a GraphQL query, fetch data via GraphQL, introspect a schema, paginate GraphQL results.
./install.sh graphql-basicsname: "graphql_basics" description: "Querying GraphQL APIs: selection sets, variables, fragments, cursor pagination, introspection, and error handling for agents fetching data from GraphQL endpoints. Triggers on: query a GraphQL API, write a GraphQL query, fetch data via GraphQL, introspect a schema, paginate GraphQL results." metadata: { "includeInPrompt": true }
Fetch data from GraphQL APIs correctly and efficiently: write queries that ask for exactly the fields needed, pass arguments via variables (never string interpolation), page through connection-style results, discover a schema via introspection, and handle GraphQL's distinctive error model (errors come back inside a 200 response). Scoped to querying an existing API — designing a GraphQL schema or operating a server is a different problem.
me: user(login: "x")) let the same field appear twice with different arguments.$vars at the top of the query and send them as a separate variables JSON object. Interpolating user input into the query string is an injection risk and breaks caching.Content-Type: application/json and a body of {"query": "...", "variables": {...}} (an operationName key disambiguates when the document holds several operations).Example with a public demo endpoint (the command shape is standard GraphQL-over-HTTP; confirm the endpoint responds before depending on it):
bash
curl -s -X POST https://countries.trevorblades.com/ \
-H "Content-Type: application/json" \
-d '{"query":"query GetCountry($code: ID!) { country(code: $code) { name capital currency } }","variables":{"code":"US"}}'
Expected response shape: {"data": {"country": {"name": ..., "capital": ..., "currency": ...}}} — fields exactly as requested, nothing more.
edges { node { ... } cursor } and pageInfo { hasNextPage endCursor }. Loop: request first: N, after: $cursor, collect edges, set $cursor = pageInfo.endCursor, repeat while pageInfo.hasNextPage is true. Prefer this over offset-style args when the API offers both — cursors stay stable when rows are inserted mid-pagination.fragment UserFields on User { id name } and uses ...UserFields in both. Keeps large queries consistent and smaller.graphql
query {
__schema {
queryType { fields { name } }
mutationType { fields { name } }
}
}
For one type's fields: query { __type(name: "Country") { fields { name type { name } } } }.
errors array alongside partial data. Always check for an errors key in the response JSON — don't trust HTTP status alone. Non-2xx statuses are transport-level failures (auth, rate limit, wrong endpoint); the errors array is operation-level (bad field, validation, null in a non-null position). Retry the former, fix the query for the latter.After applying this skill, an agent should produce:
variables object.edges/pageInfo/endCursor with the termination condition stated (hasNextPage == false).variables; no value ever gets concatenated into the query string. This is the injection rule for GraphQL.errors entry instead of data.errors key on every response. HTTP 200 does not mean success in GraphQL. Treat a non-empty errors array as the operation having failed, even when data is partially present.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.