From 26d357cc45cac02862d53c108e6010ac9003142d Mon Sep 17 00:00:00 2001 From: JuliaEdom Date: Mon, 29 Jun 2026 15:34:03 +0300 Subject: [PATCH] feat(deploy): Hugging Face Docker Space for the read-only demo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds deploy/hf-space (Dockerfile + README + DEPLOY runbook) to publish the serving API as a Hugging Face Docker Space. The Dockerfile builds from the public GitHub repo (clone of main), runs in demo mode (mirrors deploy/fly: seeded DuckDB, admin routes 404, mutations blocked except /v1/query), and serves on app_port 8000 as the HF-required UID 1000 user with a writable home. Verified on a Mac Docker daemon (x86_64, matching Spaces): image builds (30/30), container serves the seeded order entity, runs an NL query (revenue from seeded orders), and enforces the demo guards (admin 404, batch 403). /v1/health returns 200 (Docker healthcheck passes); its body honestly reports duckdb_pool live with Kafka/Flink/Iceberg as placeholder, since a single container does not run them. The Space create/push under the liovina account is an outward publish — gated; DEPLOY.md documents the exact steps. Co-Authored-By: Claude Opus 4.8 (1M context) --- deploy/hf-space/DEPLOY.md | 51 +++++++++++++++++++++++++++ deploy/hf-space/Dockerfile | 72 ++++++++++++++++++++++++++++++++++++++ deploy/hf-space/README.md | 50 ++++++++++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 deploy/hf-space/DEPLOY.md create mode 100644 deploy/hf-space/Dockerfile create mode 100644 deploy/hf-space/README.md diff --git a/deploy/hf-space/DEPLOY.md b/deploy/hf-space/DEPLOY.md new file mode 100644 index 0000000..be7f20f --- /dev/null +++ b/deploy/hf-space/DEPLOY.md @@ -0,0 +1,51 @@ +# Hugging Face Docker Space — deploy runbook + +Publishes the read-only demo (`Dockerfile` + `README.md` in this directory) as a +Hugging Face Docker Space. The Space builds the image itself from the public +GitHub repo, so only these two files are pushed to the Space repo. + +## Local / Mac build verification (do this before deploying) + +Docker is Mac-only in this setup (Windows does not run the daemon). The build +context is this directory; the repo is cloned inside the image. + +```bash +docker build -t agentflow-hf deploy/hf-space +docker run --rm -p 8000:8000 agentflow-hf & +sleep 25 +curl -fsS http://localhost:8000/v1/health +curl -fsS -H "X-API-Key: demo-key" http://localhost:8000/v1/entity/order/ORD-20260404-1001 +``` + +## Deploy (outward — gated) + +Creating/pushing a public Space under the `liovina` account is an external +publish. The HF token lives in `D:/VacancyRadar/.env` (`HF_TOKEN`); never print it. + +```bash +# 1. Create the Space (one-time) +huggingface-cli repo create agentflow-demo --repo-type space --space_sdk docker + +# 2. Push the two files to the Space repo root +# (clone the Space repo, copy Dockerfile + README.md, commit, push) +git clone https://huggingface.co/spaces/liovina/agentflow-demo /tmp/agentflow-space +cp deploy/hf-space/Dockerfile deploy/hf-space/README.md /tmp/agentflow-space/ +cd /tmp/agentflow-space && git add Dockerfile README.md \ + && git commit -m "AgentFlow read-only demo (docker sdk)" && git push +``` + +The Space builds the Dockerfile and serves on `app_port: 8000`. Live URL: +`https://liovina-agentflow-demo.hf.space`. + +## Verify live + +```bash +curl -fsS https://liovina-agentflow-demo.hf.space/v1/health +curl -fsS -H "X-API-Key: demo-key" \ + https://liovina-agentflow-demo.hf.space/v1/entity/order/ORD-20260404-1001 +``` + +## Refresh after a repo change + +The Space tracks `main` (`ARG AGENTFLOW_REF=main`). Trigger a rebuild from the +Space UI ("Factory rebuild"), or bump `AGENTFLOW_REF` to a tag for a pinned demo. diff --git a/deploy/hf-space/Dockerfile b/deploy/hf-space/Dockerfile new file mode 100644 index 0000000..475bec1 --- /dev/null +++ b/deploy/hf-space/Dockerfile @@ -0,0 +1,72 @@ +# AgentFlow — public read-only demo for Hugging Face Docker Spaces. +# +# Builds the serving API from the public GitHub repo and runs it in demo mode +# (seeded DuckDB, admin routes 404, mutating routes blocked except /v1/query). +# Mirrors Dockerfile.api / deploy/fly — the same single-container demo, repointed +# at Spaces' port + writable-home conventions. +# +# Local / Mac verify (context is this directory; the repo is cloned at build time): +# docker build -t agentflow-hf deploy/hf-space +# docker run --rm -p 8000:8000 agentflow-hf +# curl -fsS http://localhost:8000/v1/health +# curl -fsS -H "X-API-Key: demo-key" http://localhost:8000/v1/entity/order/ORD-20260404-1001 + +FROM python:3.11-slim@sha256:ae52c5bef62a6bdd42cd1e8dffef86b9cd284bde9427da79839de7a4b983e7ca AS builder + +WORKDIR /build +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +# Track main by default; pin to a tag/sha with --build-arg AGENTFLOW_REF=v1.5.0 +ARG AGENTFLOW_REF=main +RUN apt-get update \ + && apt-get install -y --no-install-recommends git \ + && rm -rf /var/lib/apt/lists/* +RUN git clone --depth 1 --branch "${AGENTFLOW_REF}" \ + https://github.com/brownjuly2003-code/agentflow.git /src +WORKDIR /src +RUN pip install --no-cache-dir --upgrade pip build hatchling \ + && python -m build --wheel --outdir /tmp/dist + +FROM python:3.11-slim@sha256:ae52c5bef62a6bdd42cd1e8dffef86b9cd284bde9427da79839de7a4b983e7ca + +WORKDIR /app +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV AGENTFLOW_ENTITY_CONTRACTS_DIR=/app/contracts/entities + +# Demo mode (mirrors deploy/fly/README.md): injected public key, admin routes +# return 404, mutating routes blocked except POST /v1/query[/explain], DuckDB +# seeded on first boot. Data lives under the demo user's writable home. +ENV AGENTFLOW_DEMO_MODE=true +ENV AGENTFLOW_SEED_ON_BOOT=true +ENV DEMO_API_KEY=demo-key +ENV DUCKDB_PATH=/home/user/data/agentflow-demo.duckdb +ENV AGENTFLOW_USAGE_DB_PATH=/home/user/data/agentflow-demo-api.duckdb + +COPY --from=builder /src/requirements.txt /app/requirements.txt +COPY --from=builder /src/config /app/config +COPY --from=builder /src/contracts /app/contracts +COPY --from=builder /tmp/dist /tmp/dist + +RUN pip install --no-cache-dir --upgrade pip \ + && pip install --no-cache-dir --upgrade setuptools==82.0.1 wheel==0.47.0 \ + && pip install --no-cache-dir -r requirements.txt \ + && wheel="$(find /tmp/dist -name '*.whl' -print -quit)" \ + && pip install --no-cache-dir "${wheel}[cloud]" \ + && pip install --no-cache-dir bcrypt PyYAML sqlglot \ + && rm -rf /tmp/dist + +# Hugging Face Spaces runs the container as UID 1000 with $HOME=/home/user. +RUN useradd -m -u 1000 user \ + && mkdir -p /home/user/data \ + && chown -R user:user /home/user/data +USER user +ENV HOME=/home/user + +EXPOSE 8000 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/v1/health', timeout=3).read()" || exit 1 + +CMD ["uvicorn", "src.serving.api.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/deploy/hf-space/README.md b/deploy/hf-space/README.md new file mode 100644 index 0000000..06ef76a --- /dev/null +++ b/deploy/hf-space/README.md @@ -0,0 +1,50 @@ +--- +title: AgentFlow Demo +colorFrom: gray +colorTo: indigo +sdk: docker +app_port: 8000 +pinned: false +--- + +# AgentFlow — live demo + +An event-native metrics layer: business metrics are produced by operational +events and stay live — the serving cache is invalidated when events arrive, so +reads reflect the latest state rather than a batch snapshot. + +This Space runs the serving API as a single read-only container, seeded with +demo data on boot. It is built from the public source at +[github.com/brownjuly2003-code/agentflow](https://github.com/brownjuly2003-code/agentflow). + +## Demo-mode behaviour + +- A public demo key (`demo-key`) is injected; no signup needed. +- Admin routes (`/v1/admin/*`, `/admin/*`) return `404`. +- Mutating routes are blocked, except `POST /v1/query` and `POST /v1/query/explain`. +- DuckDB demo data is seeded on first boot. + +## Try it + +`{SPACE}` is the Space URL (e.g. `https://liovina-agentflow-demo.hf.space`). + +```bash +# Liveness +curl -fsS {SPACE}/v1/health + +# Entity point-lookup (seeded order) +curl -fsS -H "X-API-Key: demo-key" \ + {SPACE}/v1/entity/order/ORD-20260404-1001 + +# Natural-language query (rule-based by default) +curl -fsS -X POST -H "X-API-Key: demo-key" -H "Content-Type: application/json" \ + -d '{"question": "revenue in the last hour"}' \ + {SPACE}/v1/query + +# Demo-mode guards +curl -i -H "X-Admin-Key: admin-secret" {SPACE}/v1/admin/usage # 404 +curl -i -X POST -H "X-API-Key: demo-key" -H "Content-Type: application/json" \ + -d '{"requests":[]}' {SPACE}/v1/batch # 403 +``` + +Interactive API docs are at `{SPACE}/docs`.