KrakQL is a fork of Clairvoyance that leverages Large Language Models (LLMs) to perform blind introspection of GraphQL schemas (a.k.a. schema retrieval).
Schema retrieval requires sending a series of guesses to a GraphQL endpoint to infer its schema, when the endpoint does not support the standard GraphQL introspection query.
KrakQL uses LLMs to generate more effective guesses, which significantly reduces the number of queries needed to retrieve the schema, compared to dictionary-based approaches.
KrakQL was first presented in the paper "KrakQL: LLM-Guided Blind Introspection of GraphQL Schemas" at the 17th International Symposium on Search-Based Software Engineering (SSBSE 2025). If you use this code in your research, please cite the following paper:
@InProceedings{maugeri2025krakql,
author="Maugeri, Marcello and Angamo, Abenezer and Bella, Giampaolo",
title="KrakQL: LLM-Guided Blind Introspection of GraphQL Schemas",
booktitle="Search-Based Software Engineering",
year="2025",
publisher="Springer Nature Switzerland",
}
Note: At the time of writing, the DOI is not yet available. Please check online for the latest citation details.
KrakQL is organised into two main parts: KrakQL Agent and KrakQL Core (see the architecture figure). The core loop alternates between exploration decisions and probing requests, updating the partial schema after each response.
- The Novelty Search Scheduler selects the next Target Path to probe by ranking discovered types and fields with novelty scores (
get_by_novelty(), used in the main loop inblind_introspection()). - The KrakQL Agent is a supervisor-style multi-agent architecture built on Google ADK (initialisation in krakql/krakql_agent.py) that routes execution to the appropriate sub-agent depending on the probing context (
_run_async_impl()). - Depending on the selected Target Path, the KrakQL Agent invokes one of two advisors: a. If the Target Path points to a type, the Field Advisor proposes candidate field names (currently fixed at 64 in the FieldAdvisorPromptTemplate). b. If the Target Path points to a field, the Argument Advisor proposes candidate argument names (currently fixed at 64 in the ArgumentAdvisorPromptTemplate).
- The Client sends HTTP requests containing these candidates to the GraphQL endpoint and waits for the response.
- The response is passed to the Oracle, which extracts valid fields and arguments, including the ones retrieved via regex-based parsing in suggestion hints when available (
get_valid_fields(),get_valid_args()). - The Schema Tracker updates the partial schema observed so far through
Schema,Type, andFieldstructures (Schema), and the loop continues until time budget expires, or all novelty scores reach 0 (get_by_noveltyreturnsNone).
To run KrakQL, install the dependencies, configure your OpenAI API key, and start a blind introspection session against a GraphQL endpoint.
git clone https://github.com/marcellomaugeri/KrakQL.git
cd KrakQL
poetry installNote: Poetry is recommended, but you can install KrakQL using pip as well. Just make sure to install the required dependencies listed in pyproject.toml.
KrakQL currently supports OpenAI models (default: gpt-5-nano), so you need to set up your OpenAI API key as an environment variable.
However, as Google ADK supports multiple LLM providers, please feel free to experiment with other providers and change it here.
export OPENAI_API_KEY="<your key>"The command below starts a blind introspection session against the target endpoint, incrementally builds the inferred schema, and writes the result to schema.graphql.
By default, KrakQL uses a time budget of 5 minutes, configurable with --time-budget (in seconds).
poetry run krakql https://example.com/graphql --time-budget 300 -o schema.graphqlIf the target endpoint requires authentication (or any custom HTTP header), pass each header with -H "<Header-Name>: <value>".
Example:
poetry run krakql https://example.com/graphql \
-H "Authorization: Bearer <token>" \
-H "X-API-Key: <key>" \
-o schema.graphqlKrakQL updates novelty on the selected Target Path using --reward-factor (α in the paper, default 0.1) and --decay-factor (β in the paper, default 0.05).
During field probing, the selected type is rewarded when at least one new field is discovered for that type, and decayed when no new field is found.
The same strategy applies during argument probing: the selected field is rewarded when at least one new argument is discovered, and decayed otherwise.
In practice, larger --reward-factor and/or smaller --decay-factor make exploration longer, while smaller --reward-factor and/or larger --decay-factor make it stop earlier.
If you want to experiment with different values, you can set them in this way:
poetry run krakql https://example.com/graphql \
--reward-factor 0.15 \
--decay-factor 0.03 \
-o schema.graphqlPlease note that the code in this repository is a research prototype and may generate damaging queries. Do not use this software against any system without explicit prior written authorisation from the legal owner. The authors and maintainers disclaim any liability for misuse or damage caused by unauthorised use. KrakQL is based on Clairvoyance, which is licensed under the Apache 2.0 License. See LICENSE for licensing details. Contributions are encouraged through pull requests.
