Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b19b28b
refactor(agents): extract dynamic-agent types, identity, and RPC bridges
mattzcarey Sep 1, 2026
76eff23
refactor(agents): move the sub-agent registry into dynamic-agents/reg…
mattzcarey Sep 1, 2026
94fb065
refactor(agents): move lifecycle routing and root facet bookkeeping i…
mattzcarey Sep 1, 2026
7dde09d
refactor(agents): move facet resolution, teardown, and fiber recovery…
mattzcarey Sep 1, 2026
64a6893
refactor(agents): move WebSocket forwarding and facet invocation into…
mattzcarey Sep 1, 2026
1d1830b
refactor(agents): move facet-context restore into DynamicAgents
mattzcarey Sep 1, 2026
cd960db
feat(agents): this.dynamicAgents capability facade over facet children
mattzcarey Sep 1, 2026
7c4efbc
refactor(agents): no new package surface — legacy sub-agent methods r…
mattzcarey Sep 1, 2026
59a165b
feat(examples): next/chats and next/dynamic-agents
mattzcarey Sep 1, 2026
ddd846a
feat(examples): full-stack React + Vite UIs for next/chats and next/d…
mattzcarey Sep 1, 2026
4af737b
docs: reposition sub-agents as dynamic agents; light touches + multi-…
mattzcarey Sep 1, 2026
c5a91a2
chore: fix unused import + dependency version alignment (sherif/oxlin…
mattzcarey Sep 1, 2026
35f40e5
chore: add changeset
mattzcarey Sep 1, 2026
ee97319
fix(agents): address dynamic-agent review findings
mattzcarey Sep 1, 2026
08d4187
fix(example): make chat index projection idempotent
mattzcarey Sep 1, 2026
b65572b
fix(example): close chat projection and deletion races
mattzcarey Sep 1, 2026
189deba
refactor(example): keep the chat topology example focused
mattzcarey Sep 1, 2026
7a99490
refactor(example): keep the chat topology example focused
mattzcarey Sep 1, 2026
32a6d0a
Merge remote-tracking branch 'origin/main' into chore/facets-investig…
mattzcarey Sep 1, 2026
e76fa00
fix(agents): address public API review
mattzcarey Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/dynamic-agents-capability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"agents": minor
---

Extract facet ("sub-agent") machinery into `packages/agents/src/dynamic-agents/`, add the `this.dynamicAgents` capability facade, and reposition facets as an isolation primitive rather than the recommended way to model many chat sessions.

`Agent`'s facet routing, WebSocket forwarding, virtual connections, and registry (~2,400 of `index.ts`'s ~12,150 lines) move into a dedicated module registered as a Lifecycle capability (`capabilityId: "dynamic-agents"`); its hot paths stay composition-root wired since the capability-runner hook contract can't express request-rewrite-and-continue or post-claim WebSocket forwarding. No wire- or storage-visible identifier changes.

The public surface gains `this.dynamicAgents.{get,abort,delete,has,list}` plus the `DynamicAgentClass` and `DynamicAgentStub` type names. `SubAgentClass` and `SubAgentStub` remain as compatibility aliases. `subAgent()` / `abortSubAgent()` / `deleteSubAgent()` / `hasSubAgent()` / `listSubAgents()` are unchanged in behavior and now delegate to the same capability — `@deprecated` in place, not removed. `/sub/` URLs, `useAgent({ sub })`, `parentAgent()`, and `onBeforeSubAgent` are untouched.

`docs/agents/sub-agents.md` is rewritten: verified workerd facet semantics (separate isolate, own SQLite, no independent alarms, bounded nesting depth, machine-pinned tree), a corrected claim about WebSocket frame forwarding (every frame wakes the root parent — it was never true that frames go directly to the child post-upgrade), and an explicit decision rule for facets vs. independent Durable Objects. Two new examples: `examples/next/dynamic-agents` (a supervisor running user-submitted Durable Object code as facets via Worker Loader — what facets are for) and `examples/next/chats` (one top-level DO per chat plus a per-user push-based index — the recommended many-chats pattern), both with a React + Vite UI and workers-pool tests.
3 changes: 2 additions & 1 deletion design/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ Keep it concise. A few paragraphs is fine. These are records, not essays.
| `rfc-sub-agent-routing.md` | RFC | Sub-agent external addressability — nested URLs, `onBeforeSubAgent`, per-call bridge |
| `rfc-helper-sub-agent-orchestration.md` | RFC | Agent tool orchestration — `runAgentTool`, `agentTool`, event forwarding |
| `rfc-detached-agent-tools.md` | RFC | Detached ("background") agent-tool runs — `detached` mode, durable named-method completion hook |
| `rfc-think-multi-session.md` | RFC | Multi-session Think / Chats pattern — parent directory + per-chat child DOs |
| `rfc-think-multi-session.md` | RFC | Proposed `Chats` base-class pattern using facet-backed chat children |
| `rfc-user-chat-durable-objects.md` | RFC | Proposed replacement topology — one user hub plus one independent top-level Durable Object per chat |
| `rfc-chat-recovery-work-budget.md` | RFC | Decouple chat-recovery duration from the runaway guard — work budget + `shouldKeepRecovering` (accepted) |
| `rfc-chat-recovery-foundation.md` | RFC | Shared chat recovery foundation — internal engine, adapters, behavior convergence, and testing strategy |
| `rfc-ai-chat-maintenance.md` | RFC | AIChatAgent first-class stance, shared chat toolkit, multi-session example direction |
Expand Down
599 changes: 599 additions & 0 deletions design/rfc-user-chat-durable-objects.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion docs/agents/agent-tools.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Agent Tools

Agent tools let one chat agent dispatch another chat-capable sub-agent as part
of its work. The child is a real sub-agent with its own Durable Object storage,
of its work — per-run, parent-supervised delegation is the flagship use case
for facet-backed dynamic agents. The child is a real sub-agent with its own Durable Object storage,
messages, tools, resumable stream, and drill-in URL. The parent keeps a small
run registry so clients can render the child timeline, replay it after refresh,
and clean it up later.
Expand Down
2 changes: 1 addition & 1 deletion docs/agents/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The differentiator is not "we have durable state" — it is what happens when a

- [State Management](./state.md) - Managing agent state with `setState()`, `initialState`, and `onStateChanged()`
- [Routing](./routing.md) - How `routeAgentRequest()` and agent naming works
- [Sub-agents](./sub-agents.md) - Parent/child DO composition via facets, nested routing, and direct child connections
- [Dynamic agents](./sub-agents.md) - Facet-backed child agents for code the parent supervises (dynamic/generated code, per-run tool agents, sandboxes) — not the recommended primitive for many independent peers like chats
- [HTTP & WebSockets](./http-websockets.md) - Request handling and real-time connections
- [Callable Methods](./callable-methods.md) - The `@callable` decorator and client-server method calls
- [Readonly Connections](./readonly-connections.md) - Restricting which connections can modify state
Expand Down
2 changes: 1 addition & 1 deletion docs/agents/long-running-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ This pattern has several advantages for long-running agents:

## Delegating to sub-agents

A project manager does not do everything itself. It delegates specialized work to sub-agents — child Durable Objects (facets) spawned under the parent. Each facet has its own isolated SQLite state and runs in parallel, but stays colocated on the same machine as the parent.
A project manager does not do everything itself. It delegates specialized work to sub-agents — child Durable Objects (facets) spawned under the parent. Each facet has its own isolated SQLite state and runs in parallel, but stays colocated on the same machine as the parent. This per-run, parent-supervised delegation is the use case facets are for; see [When to use dynamic agents](./sub-agents.md#when-to-use-dynamic-agents) before reaching for one to model long-lived independent peers.

```typescript
export class ProjectManager extends Agent<Env, ProjectState> {
Expand Down
Loading
Loading