feat(hub): R2 bucket structure + Cloudflare Worker publish API (#1095)#1409
Conversation
Cloud distribution layer for the Agent Hub (Phase 3A-3C). A Cloudflare Worker fronting an R2 bucket: POST /publish validates an uploaded gaia-agent.yaml + artifact, enforces per-publisher auth, publisher scope, and version immutability, generates a server-side SHA-256, then rebuilds a lightweight index.json. GET routes serve the catalog, per-agent manifests, and artifact downloads. Isolated infra under workers/ only — no src/gaia changes, no dependency on the #1102 restructure. Field names mirror src/gaia/hub/manifest.py so the catalog is consumable by the same code that reads source manifests. Runnable locally with vitest (in-memory R2 fake) and wrangler dev (Miniflare). Deploy needs an R2 bucket + PUBLISH_TOKENS secret the maintainer provisions; see README.
SummarySolid, well-isolated foundation for the Agent Hub distribution layer — the design is sound and the security posture (server-side checksum, version immutability, publisher scoping, fail-loud auth) is exactly right. Code is clean, typed strict, and the in-memory R2 fake makes the 32 handler-level tests genuinely meaningful. The one thing worth fixing before this goes live: the Worker's manifest validation drifts from the canonical Issues🟡 Important1. Reserved-ID check missing — diverges from the canonical validator (
Suggested direction: mirror the reserved set in 2. 250 MiB default vs. the Worker memory limit; size check happens after full buffering ( The artifact is fully materialized in memory ( 3. No CORS headers on the catalog routes ( The PR positions 4. Nothing runs these 32 tests in CI No workflow under 🟢 Minor
Strengths
VerdictRequest changes — the design is right and most of this is mergeable as-is, but issue #1 (reserved-ID divergence making published agents un-installable, hidden by the Note: I reviewed the source and tests directly but did not run |
Why this matters
Until now the Agent Hub had a manifest format (
gaia-agent.yaml, #1091) but nowhere to publish agents to or download them from. This adds the cloud distribution layer: a Cloudflare Worker fronting an R2 bucket that lets vetted publishers upload an agent's manifest + artifact and serves a lightweight catalog thegaia agentCLI and Hub UI can read. Publishing is gated — bad tokens, out-of-scope authors, and attempts to overwrite a released version are all rejected loudly, and the artifact checksum is generated server-side so it can never be spoofed by the uploader.Implements Phase 3A–3C of the Agent Hub plan (#1095). Isolated infra — everything lives under
workers/agent-hub/; nosrc/gaiacode is touched and there is no dependency on the in-flight #1102 restructure. JSON field names mirrorsrc/gaia/hub/manifest.pyso the catalog is consumable by the same code that reads source manifests.R2 bucket layout
Wiring secrets for deploy (maintainer)
Deploy needs Cloudflare resources not in the repo:
npx wrangler r2 bucket create gaia-agent-hub(name matcheswrangler.toml)npx wrangler secret put PUBLISH_TOKENS— JSON map of token → publisher, e.g.{"<amd-token>":{"publisher":"AMD","authors":["AMD"]},"<admin-token>":{"publisher":"Hub Admin","authors":["*"]}}. Theauthorslist bounds whichauthorvalues a token may publish under;"*"is reserved for hub admins.npx wrangler deploy(optionally uncomment theroutesline to bindhub.amd-gaia.ai/*).Full instructions and the JSON schemas are in
workers/agent-hub/README.mdandworkers/agent-hub/schemas/.Test plan
cd workers/agent-hub && npm install && npm test— 32 tests pass (auth rejection, publisher-scope + ownership, version immutability, server-side checksum, index rebuild, download routes, manifest validation, semver ordering)npm run typecheck— clean (tsc --noEmit, strict)npm run deploy:dry-run(wrangler deploy --dry-run) — config valid, bundle builds, R2 binding + vars resolvedPUBLISH_TOKENSsecret, thenwrangler deployand smoke-testPOST /publish+GET /index.jsonRefs #1095 · spec:
docs/spec/agent-hub-restructure.mdx(Phase 3, R2 distribution). No dependency on #1102.