- Book: AI That Acts
- The series: AI in TypeScript — 5 books, from your first LLM call to agents in production — all five here
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
openai-node 7.0.0 came out on July 27, 2026, with one item under breaking changes: the SDK now requires Node.js 22. Three months later, 7.44.0, a minor release, carries the line "Breaking change in a minor release." It says callers that directly access item.content or item.role on Live Decision items "may no longer compile." 7.43.0, a few days earlier, has the same label for a change to DecisionInputMessage.
Type "upgrade openai to v7" into a coding agent. It bumps the version and starts reading type errors. It has never seen those release notes. Every fix it makes is a guess about what changed, and in a diff a guess that compiles looks just like a fix that follows the release note.
The order I'd use: find out what the new version demands, read what changed in every release you are skipping, record what actually broke in your code. Then the agent gets all three as its brief. Steps 1 to 3 are plain gh, npm, git and tsc in a terminal. From step 4 on I use Hermes IDE, which I build, so weigh that part accordingly.
The running example is a TypeScript app in ~/code/app on openai@6.49.0, the release that the 7.0.0 notes compare against, going to 7.47.0, the latest release as of October 31. Swap in your own package and versions.
Step 1: Ask npm what the new version demands
Four read-only commands in your main checkout. Nothing changes on disk.
cd ~/code/app npm outdated openai npm view openai@7.47.0 engines peerDependencies node --version npm explain zod npm outdated shows Current, Wanted and Latest. Wanted is the highest version your package.json range allows, so with ^6.49.0 it stays on 6.x while Latest shows 7.x. npm prints that row in yellow, its colour for a newer version outside your range.
npm view reads the target's manifest from the registry before you install anything. The 7.47.0 package.json sets "node": ">=22.0.0" and lists optional peers, among them zod at ^3.25 || ^4.0 and ws at ^8.21.0.
Both fields bite later than you'd think. npm's package.json docs say that unless you set engine-strict, the engines field "will only produce warnings." On Node 20 the install goes through and you find out in CI or at runtime. Peers bite only if you already have them. openai marks zod and ws optional, and the same docs say "Npm will not automatically install optional peer dependencies." But if your tree already holds a zod or ws outside those ranges, a conflicting requirement "may cause an error if the tree cannot be resolved correctly." npm explain zod prints the chain of dependencies behind each copy of zod you have, so you know whether your code or some other package owns it.
If node --version prints anything below 22, that is its own change. Make it before the SDK bump, or at least name it in the brief.
Step 2: Pull every release note in the range
First, keep all the working files out of git. Every file in this tutorial starts with .upgrade-:
echo '.upgrade-*' >> .gitignore The major release's own notes are one call to gh release view:
gh release view v7.0.0 -R openai/openai-node \ --json body -q .body Those are the notes most people read, and for this upgrade they say the least. To get every release between your version and the target, list them all with gh api and filter them with jq. Save this filter as .upgrade-between.jq:
.[][] | select(.draft | not) | select(.tag_name | test("^v[0-9]+\\.[0-9]+\\.[0-9]+$")) | (.tag_name | ltrimstr("v") | split(".") | map(tonumber)) as $v | select($v > $from and $v <= $to) | "## \(.tag_name) (\(.published_at[0:10]))\n\n\(.body // "")\n" Then fetch, filter and search:
gh api --paginate --slurp \ 'repos/openai/openai-node/releases?per_page=100' \ > .upgrade-releases.json jq -r --argjson from '[6,49,0]' --argjson to '[7,47,0]' \ -f .upgrade-between.jq .upgrade-releases.json \ > .upgrade-changelog.md grep -n -i 'breaking' .upgrade-changelog.md --paginate --slurp returns one array of pages, which is why the filter starts with .[][]. The test line skips prerelease tags such as -beta.1, whose parts aren't plain numbers. Each tag becomes an array like [7,44,0], and jq orders arrays lexically, element by element, so 7.10.0 lands above 7.9.0 where a string comparison would put it below. The output is newest first.
That grep is your short list. For this range it catches at least the three entries from the top of this post: the Node 22 requirement and the two minor releases labelled breaking. The rest of .upgrade-changelog.md is what the agent reads when an error doesn't match any of them.

The breaking change you need is rarely in the major release's notes alone.
Step 3: Bump in a throwaway worktree and save what broke
You want the real failure list before the agent starts, and you don't want your main checkout sitting on a half-upgraded lockfile meanwhile. A detached git worktree is a second folder on the same commit, with no branch to clean up afterwards.
git worktree add --detach ../app-probe cd ../app-probe npm ci npm install openai@7.47.0 npx tsc --noEmit --pretty false \ > ../app/.upgrade-tsc.txt 2>&1 npm test > ../app/.upgrade-tests.txt 2>&1 cd ../app git worktree remove --force ../app-probe npm ci comes first because a new worktree holds tracked files only, so there is no node_modules yet. --noEmit type-checks without writing any output. --pretty false matters when output goes to a file: pretty is on by default and adds colour and context, and the plain form is easier for you and the agent to read line by line. Both outputs are written back into the main folder, so they outlive the probe.
--force is there only because the probe holds an uncommitted bump on purpose. Git's docs say remove refuses an unclean worktree without it. Keep that refusal on any worktree that holds work you care about.
grep -c 'error TS' .upgrade-tsc.txt counts the type errors. If both files come back clean, the upgrade may be one line plus the Node change.
Step 4: Write the brief and start the task
Save this as .upgrade-brief.md, edited for your versions:
Upgrade openai from 6.49.0 to 7.47.0. Read before editing: - .upgrade-changelog.md: every release note in range - .upgrade-tsc.txt, .upgrade-tests.txt: what broke 1. Run `npm install openai@7.47.0`, then `npx tsc --noEmit` and `npm test`. If the failures differ from the files, stop and say so. 2. Fix one failure per turn. Start each reply with the error line you fixed. 3. Name the release note each fix follows. If no note explains a failure, stop and ask. 4. Don't edit or delete tests. Don't add @ts-ignore, @ts-expect-error or `as any`. 5. 7.x needs Node.js 22. Update "engines" and the Node version in CI to match, in its own turn. 6. Done when tsc and npm test both pass. Rules 1 and 2 keep you and the agent on the same failure list, one entry per reply, which is what the review in step 5 needs. Rule 3 forces every change to point at a note, and rule 4 shuts the cheapest way to turn a suite green.
Next, the recipe Hermes runs for every new task's worktree, from the recipe docs:
# .hermes/worktree.toml copy = [".upgrade-*"] done_when = ["npx tsc --noEmit", "npm test"] copy brings files from your project folder into the same path in the worktree, but only files git ignores. If a pattern matches a tracked file, Hermes refuses the whole recipe and setup doesn't run. That is why the .gitignore line came first in step 2. done_when holds the default checks for the task's Done-When, here the same two commands as rule 6.
The first time Hermes sees the recipe, and whenever it changes, it asks you to choose Run setup or Skip. Choose Run setup: per the docs, Skip "starts the session without setup." Commit the recipe and the .gitignore line together.
Then press ⌘N (Ctrl+Shift+N on Windows and Linux), pick Claude Code or Codex, and type Read .upgrade-brief.md and follow it. The agent starts in a real terminal on a new hermes/ branch, in its own worktree, with that line as its first prompt. Your main checkout stays on 6.49.0 and keeps working while it runs. Hermes never answers a permission prompt for you, so when the agent asks to run npm install, you answer in its terminal.

The ⌘N New task sheet in Hermes 2.3.4: chips for Claude Code, the project, a new hermes/ worktree, Accept edits, model and effort, and the "Hermes will run" preview of the claude command.
Step 5: Review one failure per turn, then land
Because of rule 2, every agent reply should map to one line in .upgrade-tsc.txt or .upgrade-tests.txt. The "Agent replies" strip under the session shows one chip per reply with the lines it changed. Click a chip to see that reply's changes, or to restore your files to that point.
⌘G (Ctrl+Shift+G on Windows and Linux) opens the Review Desk, which shows changes by turn or by file, with risk flags. Read it by turn with the failure list open beside it. For each turn, check three things: the diff touches the code the error line points at, it follows the release note the agent named, and it leaves the tests alone. Switch to the by-file view for that last one.
A line comment goes back to the agent that wrote the line. Say a turn silences the 7.44.0 error with a cast: comment on it and ask for the narrowing the release notes suggest, checking 'content' in event.item before reading message fields.

The Review Desk (⌘G) in By turn view in Hermes 2.3.4: two turns listed with their file and line counts, turn 1's diff, the changed-files list, and a commit message drafted from the turns.
Without Hermes, the same review from inside the task's worktree is two commands. The agent's edits usually sit uncommitted until you land, so compare the working tree, not commits:
git status --short git diff main -- '*.test.ts' The first lists every file the agent touched. The second should print nothing; any output there means a test was edited. When the checks pass, Land commits, opens a pull request or merges locally, into the branch the task started from. For a dependency upgrade, take the pull request: CI runs the Node versions and environments your laptop doesn't. Watch it with gh pr checks --watch. If CI disagrees, don't merge. Paste the failing job's output into a new .upgrade-ci.txt and tell the agent to read it. If you landed locally instead and main goes red, Land can be undone.
What this doesn't replace
Bots already open the bump PR, and both of the common ones put release notes in it. A Dependabot PR carries Release notes, Changelog and Commits sections. Renovate's docs say it filters the releases to the versions the PR updates and embeds them in the PR body. If you already use one, that is step 2 done for you. What they don't give the agent is your failure list and the rules.
You don't need Hermes for the brief. Claude Code's overview lists updating dependencies among the jobs it handles, and the Codex CLI runs commands in your terminal too. Hand either one .upgrade-brief.md in a plain worktree and the method holds. Hermes adds the task's own branch and worktree, the per-turn review and Land with undo, all on your machine. It isn't affiliated with OpenAI, Anthropic or any agent vendor.
I haven't run this upgrade on a real app myself. How many errors you get, and which notes they trace to, depends on which parts of the SDK your code touches. That is why you capture them before the agent starts.
If this was useful
I build Hermes IDE, free and source-available (BSL 1.1) on macOS, Windows and Linux: download it or star it on GitHub if the task-per-worktree flow saves you a broken main.
If the app you're upgrading calls tools through an LLM SDK, AI That Acts is the book about that layer: tool calling, functions and a first working agent, in TypeScript. That is the code a release like 7.44.0 reaches into.
The whole AI in TypeScript series, from your first LLM call to agents in production, is here.

