github cloudflare/agents agents@0.30.0

6 hours ago

This release adds support for Pi 1.4 and makes PiHarness recover more reliably from evictions, crashes and storage errors.

Highlights

  • Pi 1.4 support: agents/harness/pi now runs on Pi 1.4.
  • Hibernation while Pi's tasks sleep: PiHarness passes Pi's onWake through your harness factory, so a Durable Object sleeps until Pi's next task is due instead of staying in memory.
  • One wake job per object: PiHarness wakes from Pi's wake(), so a task stopped by Pi's restart limit no longer keeps the object awake.
  • Parked tasks: tasks stopped by Pi's restart limit show as parked in pending(), and retry() runs them again.
  • Recovery: Pi reopens after a storage error instead of failing every call until the object restarts, and the wake job survives failed steps with backoff.
  • Fixes: Lifecycle no longer keeps evicted Durable Objects in memory, and it arms a fallback alarm when startup fails. pi-ai now reports cut-off model streams with wording Pi treats as transient, so Pi retries them.

Upgrading

  1. Update Pi to ~1.4.0 (@earendil-works/pi-durable, pi-ai, pi-agent-core) and install @earendil-works/chord alongside them. Pi 1.4 migrates session storage to a schema Pi 1.3 cannot open, so a deployment cannot roll back past this release.

  2. Check pi-durable's 1.4.0 changelog for its breaking changes, such as the removal of TaskRuntime.sleep(), the new sleeping task status, and the restart limit that parks a crash-looping task after 5 restarts.

  3. Pass onWake to Harness.open, as in the diff below. Without it, the harness still works but logs a warning, and the object stays in memory while Pi's tasks sleep.

  4. If you create Pi's registry at module scope, move it into your class, as a field or in the factory. Our tool examples showed module scope before this release. Pi keeps every Harness subscribed to its registry until it closes, and an evicted object never closes it, so a module-level registry keeps every evicted object's harness in memory.

    - const registry = createRegistry();
      export class Assistant extends Agent<Env> {
    +   registry = createRegistry();
        harness = new PiHarness({
          harness: ({ storage, context, onWake }) =>
    -       Harness.open(storage, { models, registry }, context)
    +       Harness.open(storage, { models, registry: this.registry, onWake }, context)
        });
      }
  5. Keep the harness factory safe to run more than once. It now runs again when Pi reopens after a storage error.

  6. Handle the new parked status if you switch on PiPendingOperation.status.

Existing objects need no migration step. Wake jobs left by earlier releases are handed over to the new wake job on first start.

Minor Changes

  • #2617 cfe9d0f Thanks @ben-reitz! - Support Pi 1.4: the Pi peer range is now ~1.4.0. Pi 1.4 migrates SQLite session storage to a schema that Pi 1.3 cannot open, so a deployment cannot roll back past this release. See Pi harness.

  • #2619 4b535dc Thanks @ben-reitz! - PiHarness hands its factory an onWake to pass to Harness.open, so the Durable Object can hibernate while Pi's tasks sleep. Add it to your factory: harness: ({ storage, context, onWake }) => Harness.open(storage, { ...options, onWake }, context). Without it the harness still works and logs a warning. See Pi harness.

  • #2624 3954859 Thanks @ben-reitz! - PiHarness shows operations stopped by Pi's restart limit as parked in pending(), and retry() runs them again. See Pi harness.

Patch Changes

  • #2644 f404547 Thanks @ben-reitz! - Lifecycle arms a fallback alarm while its job queue holds jobs, before startup runs in an alarm and after a startup that queued jobs throws, so a failed startup cannot leave queued jobs without a wake. See Lifecycle.

  • #2653 fc4cd24 Thanks @ben-reitz! - Stop Lifecycle startup keeping an evicted Durable Object in memory when a capability's startup leaves a promise pending, as PiHarness does when it opens Pi. See Pi harness.

  • #2643 e117121 Thanks @ben-reitz! - agents/models/pi-ai reports a cut-off or idle model stream with wording pi's retry policy treats as transient, so pi retries the turn instead of failing it. See Models with pi-ai.

  • #2617 cfe9d0f Thanks @ben-reitz! - agents/harness/pi now uses chord's own context helpers, so install @earendil-works/chord alongside pi-durable and pi-ai. See Pi harness.

  • #2648 000fcaf Thanks @ben-reitz! - PiHarness opens pi again after a storage error closes it, instead of failing every call until the object restarts. See How recovery works.

  • #2618 3e91ded Thanks @ben-reitz! - PiHarness wakes from Pi's wake() with one job per object, so a task parked by Pi's restart limit no longer keeps the Durable Object awake. See Pi harness.

  • #2649 91a8f61 Thanks @ben-reitz! - PiHarness keeps its wake job when a step fails, retrying with a backoff up to 10 minutes, and counts a memory-limit reset during the job's wait against the alarm memory-limit breaker. See How recovery works.

Don't miss a new agents release

NewReleases is sending notifications on new releases.