Guidance for Claude Code when working in this repo.
Instill AI's API gateway, built on KrakenD. This repo maintains the composed krakend.json configuration plus a set of custom KrakenD plugins. It fronts Instill backend services (pipeline, model, mgmt, artifact, agent, etc.) and handles routing, auth, and streaming.
- KrakenD CE (version pinned via
KRAKEND_CE_VERSIONin.env) — the gateway binary. - Go (version pinned via
GOLANG_VERSIONin.env; plugins currently ongo 1.25.6) — for plugins compiled as.sovia-buildmode=plugin. - Alpine-based Docker image; multi-stage build with optional
aarch64-linux-musl-crosstoolchain for cross-compiling amd64 -> arm64. - flexible-config (FC) KrakenD templating to compose
krakend.jsonfromconfig/base.json,config/share/partials,config/share/templates, andconfig/settings(generated byconfig/envsubst.sh). - jwx CLI (lestrrat-go/jwx v2.0.12) built into the image for JWKS handling;
scripts/generate_jwks.shinvokes it.
krakend.json— the composed, committed gateway config consumed at runtime.config/— source of truth for config composition.base.json— FC entrypoint.share/partials,share/templates— FC fragments.settings-env/— templated settings expanded byenvsubst.shintoconfig/settings/.envsubst.sh— substitutes env vars into settings.
plugins/— one Go module per plugin, each built into a.so:grpc-proxy— HTTP <-> gRPC bridging for backend services.simple-auth— auth middleware.registry— registry proxying.blob— blob/object handling.pipeline-sse-streaming,model-sse-streaming— SSE streaming for pipeline/model trigger endpoints.
scripts/generate_jwks.sh— generates JWKS usingjwx.Dockerfile(prod),Dockerfile.dev(dev).release-please/— release automation config.
Requires a .env file at the repo root (the Makefile includes it and exports variables such as SERVICE_NAME, SERVICE_PORT, STATES_PORT, METRICS_PORT, GOLANG_VERSION, KRAKEND_CE_VERSION).
make help— list targets.make build-dev— buildinstill/${SERVICE_NAME}:devfromDockerfile.dev.make build-latest— buildinstill/${SERVICE_NAME}:latestfromDockerfile.make dev— run the dev container (auto-joinsinstill-networkif present, elsebridge).make logs— tail container logs.make stop— stop the container.make rm— remove the container.make top— show container processes.make plugin— compile all six plugins to/usr/local/lib/krakend/plugins/*.so(run inside the dev container where that path and toolchain exist).make config— regeneratekrakend.json: runsconfig/envsubst.sh,scripts/generate_jwks.sh, thenkrakend checkwith FC env vars, and pretty-prints viajq. Requireskrakendandjqon PATH.make run—krakend run -c krakend.json.
No Go test target is defined at the repo root. Plugin modules are independent; use go commands inside each plugins/<name>/ directory if needed.
- Do not hand-edit
krakend.jsonfor logic changes — editconfig/base.json, the partials/templates, orsettings-env/, then runmake configto regenerate. - Each plugin is its own Go module (
plugins/<name>/go.mod); changes are local to that module. - Plugins must be built with the exact Go toolchain version used by the KrakenD binary — mismatches break
-buildmode=pluginloading. Prefer building through the Docker images. - Cross-compiling to arm64 from amd64 uses the
aarch64-linux-musl-crosstoolchain pulled in the Dockerfile; replicate those env vars (CC,CGO_ENABLED=1,GOARCH) if building outside Docker. - Releases go through
release-please; see that directory for config.
The plugins/blob handler is a transparent HTTP byte-proxy to MinIO; every code path through proxyToMinIO MUST:
- Forward
Range,If-Range,If-None-Match, andIf-Modified-Sinceverbatim onto the upstream MinIO request. Dropping these headers silently is not a perf optimisation — it coerces MinIO into200 OKwith the full object body on every request, which breaks<video>.fastSeek()and HTTP cache revalidation for every downstream consumer (multi-hundred-MB citation videos become unplayable). Per-endpoint header allow-lists insettings-env/input_headers.jsondo not apply toplugin/http-serverhandlers, so this responsibility lives entirely in the plugin code. - Scope the 24 h
Cache-Control: public, max-age=86400to200 OKresponses only —206 Partial Contentbodies must never inherit the full-object cache directive (a CDN/browser would reuse them as if they were the whole object), and304 Not Modifiedalready carries the validator's own cache semantics.
Guarded by plugins/blob/main_test.go (unit, table-driven). Downstream consumers SHOULD pin an end-to-end k6 scenario in their own integration suite that exercises this protocol against a live gateway via derivedResourceUri.