Skip to content

PascalSenn/apidays-singapore

Repository files navigation

apidays-singapore

A demo + case study showing how an AI agent can discover and query a federated GraphQL API backed by Singapore open-data sources (weather, air quality, traffic, parking, dengue clusters, food hygiene, healthcare, education, housing, demographics).

The case study compares the token cost of different API-discovery strategies (REST with OpenAPI, GraphQL with the schema in the prompt, GraphQL with semantic introspection, etc.) when an LLM has to answer a natural-language question about Singapore.

What's in the repo

  • src/AppHost — .NET Aspire host that launches the gateway and all subgraphs.
  • src/Gateway — HotChocolate Fusion gateway (GraphQL + YARP reverse proxy for REST). Exposes a composed schema with semantic introspection (__search, __definitions) enabled.
  • src/Subgraphs/* — one subgraph per data domain (Weather, AirQuality, Traffic, Parking, Dengue, Food, Healthcare, Education, Housing, Demographics). Each exposes GraphQL and a small REST surface; data is served from cached JSON fixtures.
  • src/Defaults — shared Aspire service defaults and GraphQL source-schema defaults.
  • case-study/ — prompts, runner scripts, and results for the token-cost comparison.

Prerequisites

  • .NET SDK 10.0.201 or newer (global.json pins the minor version).
  • Claude Code CLI on PATH (only needed to run the case-study agents; the gateway itself doesn't need it).
  • curl and jq for ad-hoc queries.
  • Optional: tiktoken Python package for exact token counts in the case-study output.

Start the gateway

cd src/AppHost
dotnet run

Aspire boots the gateway and all ten subgraphs. Once up:

Sanity check:

curl -s -X POST http://localhost:5110/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query":"{ __typename }"}'

Run an example query

Ask the composed schema for area info and nearby taxi availability:

curl -s -X POST http://localhost:5110/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query":"{ areaByName(name: \"Bedok\") { name availableTaxis nearestStation { name } } }"}' \
  | jq

Or use semantic introspection to discover fields by intent before querying:

curl -s -X POST http://localhost:5110/graphql \
  -H 'Content-Type: application/json' \
  -d '{"query":"{ __search(query:\"outdoor safety air quality taxis\", first:5) { coordinate score } }"}' \
  | jq

Run a case-study agent

The case-study scripts invoke Claude Code against a prompt and record the full conversation trace plus token usage.

# semantic introspection via curl (the leanest GraphQL approach)
./case-study/run.sh graphql-skill

# REST with the gateway's merged OpenAPI spec
./case-study/run.sh rest

# run all strategies and print a comparison table
./case-study/run.sh all

Available modes: rest, rest-full, rest-full-embedded, rest-minimal, graphql, graphql-full, graphql-full-embedded, graphql-file, graphql-skill, graphql-mcp, all. Each run writes *_trace.jsonl and *_results.json into case-study/.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages