Scheduling a Future Agent Invocation with Effect

SkillProductivity

Lets your agent schedule its own future runs, like delayed tasks, timed executions, reminders, or cancelable timers.

Use Scheduling a Future Agent Invocation with Effect in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add Scheduling a Future Agent Invocation with Effect and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the Scheduling a Future Agent Invocation with Effect skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Scheduling a Future Agent Invocation with EffectStart free
About this skill

Scheduling a future agent invocation from Effect-based Golem agent code. Use for delayed calls, timed agent execution, reminders, or cancelable schedules with @golemcloud/effect-golem.

What this skill tells your AI

The instructions your AI receives, as published by golemcloud/golem in golem-skills/skills/effect/golem-schedule-future-call-effect/SKILL.md and read by ahel’s review.

A scheduled invocation asks Golem to call a typed remote agent method at a future wall-clock time. Submitting the schedule returns immediately after the host accepts it; it does not wait for the target method to run and does not expose that method's eventual result.

This skill covers agent-to-agent scheduling from Effect code. For scheduling from a shell with golem agent invoke --schedule-at, use the Effect CLI scheduling skill instead.

Schedule a Typed Remote Method

Obtain the target's typed client, construct the WIT wall-clock datetime, and yield the method's .schedule(scheduledAt, input) Effect:

import { Effect, Ref } from "effect";
import { DelayedRecorderDefinition } from "./delayed-recorder.js";

// In an implementation where `state` is the snapshot Ref and `name` is
// the agent's agent id field:
const scheduleReport = () =>
  Effect.gen(function* () {
    const { count: newCount } = yield* Ref.updateAndGet(state, ({ count }) => ({
      count: count + 1,
    }));

    const atMillis = Date.now() + 30_000;
    const scheduledAt = {
      seconds: BigInt(Math.floor(atMillis / 1_000)),
      nanoseconds: Math.floor(atMillis % 1_000) * 1_000_000,
    };

    const recorder = yield* DelayedRecorderDefinition.client.get({ name });
    yield* recorder.recordCount.schedule(scheduledAt, { value: newCount });
    return newCount;
  }).pipe(Effect.orDie);

Here state is the snapshot-backed Ref initialized by the agent implementation. Keep the application's normal Ref or snapshot state pattern rather than replacing it with a Promise or a local timer. Effect.orDie converts typed client and scheduling infrastructure failures into defects because the example handler declares no public error. If callers should recover from scheduling failure, map it to a domain error declared in the method's error schema instead.

Exact Call Shape

  • Target.client.get(...) takes the complete named agent id record.
  • Remote method inputs are named records. Pass {} for a method declared with input: {}.
  • .schedule(...) takes the absolute datetime first and the method input second.
  • Both client.get(...) and .schedule(...) are lazy Effects and must be yielded.
  • Yielding .schedule(...) waits only for schedule submission, not for future execution.
  • Scheduling reports only submission failures. The target method's later success or typed failure is not returned to the caller.

For a no-parameter method:

const scheduleIncrement = Effect.gen(function* () {
  const counter = yield* CounterDefinition.client.get({ name: "my-counter" });
  yield* counter.increment.schedule(scheduledAt, {});
});

Do not translate the Promise-based TypeScript SDK mechanically. In this Effect SDK there is no generated .scheduleCancelable() variant, and .schedule(...) does not accept a JavaScript Date, an ISO string, or an epoch-millisecond number directly.

Datetime Representation

The schedule time is an absolute Unix timestamp represented as:

const scheduledAt = {
  seconds: 1_700_000_000n,
  nanoseconds: 0,
};

seconds is a bigint. nanoseconds is the fractional part of the second as a number from 0 through 999_999_999. Convert milliseconds explicitly as shown above; passing Date.now() + delayMs directly has the wrong type and units.

Treat the requested time as a lower bound. Scheduler polling and already queued work on the target agent can delay execution beyond that instant.

Cancellation

Every .schedule(...) call returns a Client.ScheduledInvocation. Keep the returned handle only when later cancellation is required:

const cancelBeforeStart = Effect.gen(function* () {
  const scheduled = yield* recorder.recordCount.schedule(scheduledAt, {
    value,
  });

  // Later, before the invocation starts:
  yield* scheduled.cancel();
});

Cancellation is best-effort and becomes a no-op once execution has started. Dropping the handle does not cancel the schedule. The handle wraps a live host resource and is not schema-serializable:

  • it may be retained in an ordinary in-memory Ref while the agent instance remains live;
  • do not put it in Snapshot.define(...) state;
  • the pinned SDK exposes no stable schedule id or API for reopening the handle after restoration.

When recovery-safe stopping is required, persist a logical flag or generation number and let a stale scheduled invocation observe that state and exit without doing work.

Use Cases

  • Schedule the next occurrence of a periodic task after the current run finishes.
  • Delay order processing until a cooling-off period expires.
  • Deliver reminders or notifications at a chosen wall-clock time.
  • Schedule retries with bounded backoff without sleeping inside the current invocation.

Use a scheduled RPC rather than setTimeout, Effect.sleep, or a forked in-process fiber when the work must survive suspension and execute as a separate durable agent invocation.

Signals

GitHub stars
2k
Forks
210
Last commit
Oct 2026
Advanced
Item type
skill
Key
golem-schedule-future-call-effect
Source
github.com/golemcloud/golem