
Foxl v0.2.21 upgrades two foundational dependencies: the Strands Agent SDK reaches stable 1.0 (from release-candidate), and Express jumps from v4 to v5. Neither is visible to the user as a new button or feature, but both change how the agent loop runs under the hood.
Strands SDK v1.0.0
The headline feature is concurrent tool execution, now the default. When the LLM requests multiple tools in a single turn — say, reading two files and checking git status — the SDK runs them in parallel instead of sequentially. The LLM already knows which combinations are safe (it won't ask to write a file and read it in the same batch), so this is a free latency win on multi-tool turns.
The second addition is cancellation hooks. The SDK now fires BeforeInvocationEvent before each agent loop iteration and BeforeModelCallEvent before each API call. Foxl hooks into both: when you press Stop, the agent checks these gates before spending tokens on the next call. Previously, a stop signal could only take effect after the current API response finished streaming. Now it intercepts before the request is sent.
invocationState
The SDK also introduces invocationState — a per-invocation mutable context bag that travels with every hook event. Foxl uses it to route tool events (start/end) back to the correct agent without a global Map. Each agent.stream() call passes its own onToolEvent callback via invocationState, and the hook reads it directly from event.invocationState. One fewer piece of shared mutable state.
Express 5
Express 5 is the first major release since 2014. The changes that matter for Foxl:
- Async error handling: rejected promises in route handlers are caught automatically. No more
try/catch wrappers just to avoid unhandled rejections crashing the server. - New path-to-regexp: wildcard routes changed syntax.
:param(*) becomes *param, unnamed * becomes *splat, and wildcard captures return arrays instead of strings. Every workspace file route, the webhook endpoint, and the SPA catch-all were migrated.
What broke (and how we fixed it)
Three workspace endpoints returned 500 after the Express 5 upgrade. The cause: req.params.filename changed from "SOUL.md" (string) to ["SOUL.md"] (array). Nested paths like memory/daily/2026-04-30.md became ["memory", "daily", "2026-04-30.md"]. The fix is a one-liner: Array.isArray(p) ? p.join('/') : p at each route handler.
Test coverage
Added 11 new Playwright e2e tests in sdk-upgrade-e2e.spec.ts covering Express 5 wildcard routing, chat stop/cancellation, server health, and provider endpoints. All 32 API-level functional tests pass. The full 526-test suite runs with the same pass rate as before the upgrade — the 112 existing UI-locator failures are pre-existing and unrelated to this change.
Upgrade summary
| Package | Before | After |
|---|
@strands-agents/sdk | 1.0.0-rc.5 | 1.0.0 |
express | 4.18 | 5.2 |
@types/express | 4.17 | 5.0 |