NOW LET US – AI RAG SaaS Studio TP.HCM
NOW LET US
Digital Product Studio
Back to news
DEV-TOOLS...6 min read

Shipping huggingface_hub every week with AI, open tools, and a human in the loop

Share
NOW LET US Article – Shipping huggingface_hub every week with AI, open tools, and a human in the loop

Hugging Face automated their huggingface_hub release cycle from weeks to a weekly cadence using GitHub Actions and open-weights AI models. By combining LLMs with deterministic guardrails, they streamline release notes generation while keeping a human in the loop for final approval.

huggingface_hub

is the Python client at the base of the Hugging Face ecosystem. transformers

, datasets

, diffusers

, sentence-transformers

and dozens of other libraries depend on it to talk to the Hub. Every week we don't ship a new release is a week of fixes and features stuck on main

. For a long time we released every 4 to 6 weeks. We now release every week from a single GitHub Actions workflow. We built it using open-source tools and open-weights models and kept a human in the loop at the one place where judgment matters. Nothing in this post requires a vendor contract, a closed model, or infrastructure you can't run yourself. That was a design goal from the start since we wanted a workflow other maintainers could pick up and adapt.

By the end of this post, you'll have everything you need to build your own.

The old process was partly automated, mostly manual.

Already in CI:

  • Publishing to PyPI once a tag was pushed.
  • Opening test branches in downstream libraries with the release candidate pinned.

Still manual, every single time:

  • Creating the release branch, bumping the version in __init__.py

, committing, tagging, pushing. - Watching the downstream CI runs and triaging failures.

  • Reading through every PR merged since the last release and writing release notes by hand: grouped by theme, with context, in a voice that didn't read like a git log

dump. - Cutting the stable release after the RC period.

  • Drafting an internal Slack announcement and social posts.
  • Opening the post-release PR to bump main

to the nextdev0

.

Writing good notes for a new version was the heavy part, aggregating tens of PRs on different topics. Nothing technically hard but a few hours of focused attention. Add the announcements on top and a minor release was easily a half-day of work spread over several days.

So we decided to streamline the whole thing. Looking at that list, the work splits in two.

Some steps are purely mechanical and can be automated: bumping the version, committing, tagging, pushing, opening downstream test branches, opening the post-release PR. Nobody needs to think about those. They just have to happen in the right order, every time, which is what a CI workflow is good at.

The rest is different. Writing release notes, deciding what to highlight, phrasing an announcement for a human audience: that's brain work. It's the kind of judgment that kept the release manual for years. This is where AI comes in, turning a blank page into a solid first draft in seconds. It's also where we have to be careful because a draft that looks confident and is subtly wrong is worse than no draft at all.

When we decided to fix this, we set one constraint up front: every moving part had to be something any maintainer could run themselves. No closed model behind an API we couldn't swap, no proprietary release platform, no secret sauce.

Here's the entire stack:

| Part | What it does | |---|---| GitHub Actions | Orchestrates the whole release | OpenCode | Agent runtime that drives the model | An open-weights model (currently GLM-5.2 from Z.ai) | Drafts the release notes and Slack announcement | HF Inference Providers | Serves the model | PyPI Trusted Publishing | Publishes the package |

The second principle: the model drafts, a human decides. Language models are good at turning thirty terse PR titles into readable release notes. They are not good at being trusted blindly. So the workflow is human-supervised: the model does the first pass, a deterministic script checks its work, and a human reviews and edits before anything ships (more on that below).

The full workflow is a single file, .github/workflows/release.yml

, triggered by hand from the Actions UI. It takes exactly one input:

on:
workflow_dispatch:
inputs:
release_type:
type: choice
options:
- minor-prerelease # cut an RC from main
- minor-release # promote the RC to final
- patch-release # bugfix on an existing release branch

From there, the jobs run roughly in this order:

**Prepare.**Compute the next version, create or reuse the release branch, bump__version__

, commit, tag, push.**Publish to PyPI.**Build and uploadhuggingface_hub

. In parallel, build and upload thehf

CLI as its own PyPI package.**Release notes.**Diff the commit range since the last tag, pull PR metadata from the GitHub API, and have the model draft a structured changelog (here's a recent one). Saved as adraftGitHub release.**Downstream test branches.**For RCs, open a branch intransformers

,datasets

,diffusers

,sentence-transformers

with the RC pinned, so their CI tells us fast if we broke something.**Slack announcement.**Read the notes and produce an internal announcement in our team voice.**Archive notes.**Upload both the raw AI draft and the human-edited version to a Hugging Face Bucket, side by side.**Post-release bump.**After a stable release, open a PR onmain

bumping to the nextdev0

.**Comment on shipped PRs.**Leave a "this shipped in vX.Y.Z" comment on every PR in the release.**Sync CLI docs.**Open a PR to our skills repo with the regeneratedhf

CLI skill docs.**Report to Slack.**Every step posts its status as a thread reply; a final job updates the root message with ✅ or ❌.

The remaining manual steps are reviewing and publishing the draft release notes, and reviewing and posting an internal Slack message. Those two steps are where we want a human in the loop.

Here's the failure mode everyone worries about with AI-generated release notes: the model quietly drops a PR or invents one that isn't in this release. A changelog that's almost right is worse than no changelog because nobody re-checks it.

We don't trust the generated release notes to be complete on the first try, we verify it deterministically. Before the model runs, a Python script retrieves all PRs that belong to the release and stores them as ground truth.

# Deterministic: extract PR numbers from squash-merge commits in the range.
PR_NUMBER_PATTERN = re.compile(r"\(#(\d+)\)$")
pr_numbers = [
int(m.group(1))
for commit in commits_since_last_tag
if (m := PR_NUMBER_PATTERN.search(commit.title))
]
save_manifest(pr_numbers) # the source of truth

Then model drafts the notes from them. Once done, we check its output against the initial list of PRs:

expected = set(load_manifest()) # what should be there
found = extract_pr_refs(notes_md) # what the model wrote (#1234 -> 1234)
missing = expected - found # silently dropped
extra = found - expected # belongs to a different release

If anything is missing or extra, we don't fail and we don't ship a wrong file. We hand the discrepancy back to the agent and ask it to fix exactly those PRs:

for _ in range(MAX_ITERATIONS):
missing, extra = validate(notes)
if not missing and not extra:
break # matches the manifest exactly
run_agent_fix(missing_prs=missing, extra_prs=extra)

This is the pattern that makes the whole thing trustworthy: a non-deterministic model wrapped in deterministic guardrails. The model is great at writing prose and unreliable at being exhaustive. So we let it write and let code enforce the consistency.

Completeness is one half. Accuracy is the other. A model summarizing a PR from its title alone will cheerfully invent a code example that doesn't match the real API.

To prevent that, when we fetch PR metadata we also pull the actual documentation diffs from each PR: the unified diff of any .md

file under docs/

that the PR touched.

def fetch_doc_diffs(pr):
return [
{"filename": f.filename, "status": f.status, "patch": f.patch}
for f in pr.get_files()
if f.filename.startswith("docs/") and f.filename.endswith(".md") and f.patch
]

That diff goes into the model's context so when it writes "here's the new CLI command," it's quoting the example the PR author actually wrote in the docs. That's the same logic as before: give the model real source material and a narrow job.

The prompts themselves liv

© 2026 Now Let Us. All rights reserved.

Source: Hugging Face Blog

Advertisement
Ad slot ready: 5887729102

More in this category

NOW LET US Related – WordStar: A Writer's Word Processor (1996)

dev-tools

WordStar: A Writer's Word Processor (1996)

An insightful look into why legendary authors like George R.R. Martin and Arthur C. Clarke preferred the classic DOS-based WordStar over modern word processors, highlighting its revolutionary touch-typing interface.

NOW LET US Related – Ultrasound imaging of the brain

dev-tools

Ultrasound imaging of the brain

A breakthrough in transcranial ultrasound imaging achieves 100x higher resolution than CT, opening new doors for non-invasive brain-computer interfaces and medical diagnostics.

NOW LET US Related – Introducing the FFASR Leaderboard: Benchmarking ASR in the Real World

dev-tools

Introducing the FFASR Leaderboard: Benchmarking ASR in the Real World

Treble Technologies and Hugging Face have launched the Far-Field ASR (FFASR) Leaderboard, the first open, community-driven benchmark designed to evaluate ASR models under realistic far-field acoustic conditions.

NOW LET US Related – Steam Machine launches today

dev-tools

Steam Machine launches today

Valve's highly anticipated Steam Machines have officially launched worldwide, running on the Linux-based SteamOS. This ambitious hardware initiative aims to bring PC gaming directly into the living room, challenging traditional consoles.

NOW LET US Related – Show HN: Oak – Git alternative designed for agents

dev-tools

Show HN: Oak – Git alternative designed for agents

Oak is an open-source version control system designed specifically for AI agents, offering branch-per-session workflows and lazy mounts for rapid repository editing.

NOW LET US Related – The text in Claude Code’s “Extended Thinking” output

dev-tools

The text in Claude Code’s “Extended Thinking” output

A developer discovered that Claude Code encrypts its local reasoning logs, leaving users with only a summary of the AI's thinking process. This raises transparency and auditing concerns, highlighting the limitations of proprietary AI models.

EXPLORE TOPICS

Discover All Categories

Deep dive into the specific technology sectors that matter most to you.