Skip to content

feat(deploy): cloudflare-worker agent directories gain sub-agents, schedules, channels, memory and projectInstructions - #392

Merged
LinuxDevil merged 1 commit into
mainfrom
fix/lou-s5-wdir
Oct 4, 2026
Merged

LinuxDevil merged 1 commit into
mainfrom
fix/lou-s5-wdir

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

What was missing

lousho build --target=cloudflare-worker rejected an agent directory containing subagents/, schedules/, channels/, memory/ or a config with projectInstructions, pointing users at node-server/docker instead (#298).

What changed

The scaffold (src/deploy/adapters/cloudflare-dir.ts) now embeds all of it into the generated agent.module.ts, and the Worker runtime (src/deploy/runtime.worker.ts, src/deploy/workerAgentDir.ts) serves it:

  • Sub-agents — subagents/<name>/ directories are embedded recursively with the same layout rules and resolved with resolveAgentDir()'s semantics (a description is required, the parent's model is inherited). The parent gets a delegate_to_<name> tool (workerAgentDir.ts, runtime.worker.ts:workerDelegateTool).
  • Schedules — schedule files are evaluated at build time by the new src/deploy/evalModule.ts (esbuild + the Worker SDK plugin) so their cron expressions reach wrangler.toml's [triggers] crons (workerDirCrons() in cloudflare.ts applies the same UTC / five-field / day-name rules as spec triggers). The generated worker.ts exports scheduled() only when schedules exist, routed through handleWorkerAgentDirScheduled.
  • Channels — channel modules are mounted under /channels by the new mountFetchChannels() (src/channels/fetchChannels.ts), a Fetch-native sibling of mountChannels(); the channel logic itself moved into src/channels/channelCore.ts, shared by both mounts. Early-acknowledged turns keep running under ctx.waitUntil.
  • Memory — new kvMemory() provider (src/deploy/workerMemory.ts), bound per request to the AGENT_CHECKPOINTS KV namespace under memory/<scopeKey> keys (custom binding name supported; in-memory fallback when unbound, same as workerStore()). Exported from the package root, the /kv subpath and the Worker SDK.
  • Project instructions — projectInstructions: true reads AGENTS.md/CLAUDE.md at build time and embeds the text; a JSON/YAML options object is honoured too. An options object hidden in an agent.ts config is refused at Worker start with a clear error.

A JSON/YAML config is now validated at scaffold time for the whole directory tree (sub-agents without a description fail the build, not the first request); agent.ts configs are still checked at Worker start. The Worker SDK subset (workerSdk.ts / workerSdkExports.ts) grew the directory-facing names (defineSchedule, defineChannel, the channel factories, defineMemory, inMemoryMemory, kvMemory), and the missing-export hint lists them.

Tests

  • src/deploy/adapters/cloudflare.dir.test.ts — real scaffold + tsup build of a new worker-agent-dir-full fixture (sub-agent, schedule, channel, kvMemory() memory, AGENTS.md), then the built bundle's fetch()/scheduled() driven in-process; plus scaffold refusals (bad schedule export, timezone cron, sub-agent without description).
  • src/deploy/workerAgentDir.test.ts — resolution and runtime coverage for every new folder.
  • src/channels/fetchChannels.test.ts — the Fetch router's routes, early respond + waitUntil, error mapping.
  • src/deploy/workerMemory.test.ts — kvMemory() binding semantics.
  • npm run build, npm run docs:llms (llms-full.txt regenerated); full vitest run suite green (4260+ tests; the only failures seen were a missing packages/create-lousho-agent dist build and a flaky 5s shell timeout, both passing after a rebuild/retry).

Closes #298

… schedules, channels, memory and projectInstructions (#298)

The cloudflare-worker target rejected an agent directory with subagents/,
schedules/, channels/, memory/ or a projectInstructions config. The build
now embeds all of them:

- subagents/<name>/ directories are embedded recursively in the generated
  agent.module.ts and resolved with resolveAgentDir()'s rules (description
  required, model inherited from the parent); the parent gets a
  delegate_to_<name> tool.
- schedules/ files are evaluated at scaffold time (evalModule bundles them
  with the Worker SDK plugin) so their cron expressions reach wrangler.toml's
  [triggers] crons, and the generated worker exports scheduled() only when
  schedules exist. Cloudflare's UTC / five-field / day-name rules apply.
- channels/ are mounted under /channels through mountFetchChannels(), a
  Fetch-native sibling of mountChannels() sharing the new channelCore().
- memory/ slots can use kvMemory(): a provider bound per request to the
  AGENT_CHECKPOINTS KV namespace (memory/<scopeKey> keys), exported from the
  package root and the /kv subpath.
- projectInstructions reads AGENTS.md/CLAUDE.md at build time and embeds the
  text instead of reading a file the Worker has no access to.

Closes #298
@LinuxDevil
LinuxDevil merged commit 9585532 into main Oct 4, 2026
1 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloudflare Worker target: sub-agents, schedules, channels and memory from an agent directory

1 participant