npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lucid-agents/scheduler

v0.3.2

Published

Pull-style scheduler for hiring agents and invoking them on a schedule with bound wallets

Readme

@lucid-agents/scheduler

A pull-style, lease-based scheduler for invoking remote Lucid services through their Agent Cards and Lucid HTTP entrypoint profile. The package depends on @lucid-agents/a2a helpers, but it is not an official A2A v1 scheduler.

Runtime extension

The scheduler requires a2a(). Install payments() before it when scheduled invocations may need x402 payment handling.

import { a2a } from '@lucid-agents/a2a';
import { createAgent } from '@lucid-agents/core';
import { payments, paymentsFromEnv } from '@lucid-agents/payments';
import { wallets, walletsFromEnv } from '@lucid-agents/wallet';
import {
  createMemoryStore,
  createSchedulerWorker,
  scheduler,
} from '@lucid-agents/scheduler';

const agent = await createAgent({ name: 'buyer', version: '1.0.0' })
  .use(wallets({ config: walletsFromEnv() }))
  .use(a2a())
  .use(payments({ config: paymentsFromEnv() }))
  .use(
    scheduler({
      store: createMemoryStore(),
      leaseMs: 30_000,
      defaultMaxRetries: 3,
      defaultConcurrency: 5,
    })
  )
  .build();

const { hire, job } = await agent.scheduler.createHire({
  agentCardUrl: 'https://worker.example',
  entrypointKey: 'daily-report',
  schedule: { kind: 'interval', everyMs: 86_400_000 },
  jobInput: { accountId: 'acct-123' },
});

const worker = createSchedulerWorker(agent.scheduler, 5_000);
worker.start();

// On shutdown:
worker.stop();
await agent.close();

If the buyer does not make paid calls, omit payments() entirely. The scheduler uses runtime.a2a.client.invoke and automatically asks runtime.payments for a payment-aware Fetch implementation when that capability exists. A paid buyer also needs a compatible agent wallet/signer and spending policy; payments configuration alone is not signing authority.

Jobs and schedules

Supported schedules are:

{ kind: 'once', at: Date.now() + 30_000 }
{ kind: 'interval', everyMs: 60_000 }

Cron expressions are not supported. Use addJob to add work to an existing hire, and pauseHire, resumeHire, cancelHire, pauseJob, or resumeJob for lifecycle control.

await agent.scheduler.addJob({
  hireId: hire.id,
  entrypointKey: 'hourly-sync',
  schedule: { kind: 'once', at: Date.now() + 30_000 },
  jobInput: { accountId: 'acct-123' },
  maxRetries: 5,
});

Agent cards are cached per hire and refreshed after agentCardTtlMs. The card's HTTP supportedInterfaces URL is used for invocation, including any base path.

Delivery and idempotency

Workers claim jobs through SchedulerStore.claimJob. A lease makes concurrent workers safe from intentionally executing the same due record at once, but a worker can fail after the remote call and before it saves completion. Delivery is therefore at least once.

Every job gets an idempotency seed unless the caller supplies one:

  • retries of the same occurrence reuse the same key;
  • every interval occurrence derives a distinct key from that seed, including caller-supplied seeds;
  • one-time jobs use a caller-supplied key unchanged;
  • seeds must contain 20–256 characters after trimming.

The key is sent as Idempotency-Key by the Lucid Agent Card/HTTP client. Lucid HTTP runtimes deduplicate it by default; other remote services must provide an equivalent target-side idempotency boundary.

Delivery remains at least once. A target-side idempotency record and idempotent downstream effects are required because a worker can finish the remote paid call and crash before it stores local success.

Durable stores

createMemoryStore() is suitable for tests and one-process development. A production scheduler should inject a durable implementation of SchedulerStore from @lucid-agents/types/scheduler.

The critical store operation is an atomic claimJob(jobId, workerId, leaseMs, now). recoverExpiredLeases() returns expired leased jobs to pending state for another worker. The extension calls an optional store close() method from runtime.close().

There is no lease heartbeat/renewal in this release. Set leaseMs longer than the worst-case discovery, payment, invocation, and final store write. The convenience worker does not call recoverExpiredLeases() automatically and can start overlapping ticks if one tick exceeds its interval; orchestrate recovery and rely on atomic claims.

For an externally managed worker loop, call:

await agent.scheduler.recoverExpiredLeases();
await agent.scheduler.tick({ workerId: 'worker-7', concurrency: 10 });

Standalone construction

createSchedulerRuntime is available when an application already has a Lucid runtime and wants to construct the scheduler without the extension helper:

import {
  createMemoryStore,
  createSchedulerRuntime,
} from '@lucid-agents/scheduler';

const schedulerRuntime = createSchedulerRuntime({
  runtime: agent,
  store: createMemoryStore(),
});

The supplied runtime must contain the A2A capability. Scheduler contracts are defined in @lucid-agents/types/scheduler.