Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
- **Agents: Rename ordinary sessions beginning with `task:`.** Session names with that prefix are now reserved for framework-owned delegated-task history. Flue retains detached child history until parent deletion or application-owned retention cleanup, and no stored records are deleted automatically during upgrade.
- **Agents: Clear or migrate persisted beta session state before upgrading.** Session records now persist one opaque `aff_<ULID>` provider-affinity key instead of deriving affinity from agent instance, harness, and session names. This keeps prompt-cache and routing-affinity identifiers bounded and distinct for nested tasks. Existing version-4 beta session records are rejected; storage keys are unchanged.
- **Cloudflare: Rename generated Durable Object identities.** Generated bindings now use `FLUE_<NAME>_AGENT`, `FLUE_<NAME>_WORKFLOW`, and `FLUE_REGISTRY`; generated classes use `Flue<Name>Agent`, `Flue<Name>Workflow`, and `FlueRegistry`. Existing deployments must append authored Wrangler `renamed_classes` migrations for deployed agent and workflow classes and update authored direct binding access such as `env.Assistant` to `env.FLUE_ASSISTANT_AGENT`.
- **Cloudflare: Use fresh SQLite-backed generated agent classes.** Generated agent Durable Objects now require SQLite for durable submission admission and ordering. Introduce classes through Wrangler `new_sqlite_classes`, not legacy `new_classes`. Already deployed KV-backed classes cannot be converted to SQLite in place. This pre-1.0 upgrade does not adopt in-flight direct prompts or dispatched inputs from earlier generated-agent identities; use a fresh class identity and treat the deployment as a hard execution-state boundary.
- **Cloudflare: Upgrade Cloudflare Agents SDK within the audited range.** Install `agents >=0.14.1 <0.15.0` for the published scheduling and Fiber behavior audited by this release.
- **Cloudflare: Capture request metadata before durable direct admission.** Route middleware sees the original inbound request, but SQL-backed direct processing uses a deterministic internal `Request`. Do not rely on later operation-time `ctx.req` to preserve original headers, cookies, query parameters, URL, or body.
- **Cloudflare: Remove public agent WebSocket adapters.** `CloudflareAgentWebSocketOptions`, `connectCloudflareAgentWebSocket(...)`, and `messageCloudflareAgentWebSocket(...)` are now internal generated-agent coordinator details. Use generated Flue agent routing instead of importing these helpers from `@flue/runtime/cloudflare`.

### Fixes & Other Changes

Expand All @@ -19,6 +23,7 @@
- **Cloudflare: Preserve workflow-run history parity.** Cloudflare workflow storage now ignores events for unknown runs, resets same-ID event history when a run is initialized, preserves absent optional fields separately from explicit `null`, and retains explicit terminal `null` results during recovery.
- **Harden persisted workflow-event identity.** Workflow history now treats `(runId, eventIndex)` as one immutable append-only event identity and SSE resume cursor across Node and Cloudflare. Malformed or duplicate persisted events fail instead of producing ambiguous history, and pre-event stream failures no longer fabricate cursor `0`.
- **Cloudflare: Own Durable Object routing.** Flue now resolves generated agent and workflow bindings explicitly instead of deriving public routes from the Agents SDK environment scanner, then forwards requests through the Agents SDK custom-routing helper. Public routes remain independent from generated Durable Object identities.
- **Cloudflare: Queue direct and dispatched agent input through one durable lifecycle.** Direct HTTP, SSE, WebSocket, and `dispatch(...)` submissions now share SQLite-backed same-session ordering. Transport loss does not cancel accepted backend work. Interrupted attempts reconcile conservatively: Flue requeues only when safe, recognizes persisted completion, and otherwise records a visible session interruption instead of blindly replaying provider work. Terminal operational payload copies become eligible for bounded lazy cleanup after a seven-day internal inspection and duplicate-forwarding horizon, and session deletion rejects while durable submissions remain queued or running.

## 0.9.1 - 2026-06-02

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export async function run({ init, payload }: FlueContext) {

A support agent can also run on Cloudflare without a container by using Flue's default virtual sandbox. Populate its filesystem with the context the agent needs, then it can search that content with its built-in `grep`, `glob`, and `read` tools.

Because this agent is deployed to Cloudflare, message history and session state are automatically persisted for you. So you (or your customer) can revisit this support session days, weeks, or years later and pick up exactly where you left off.
Cloudflare Durable Objects persist stored conversation history across later requests. The default virtual sandbox remains in memory, so seed any files each time you need them or choose a durable sandbox connector for long-lived workspace state.

```ts
// .flue/workflows/support.ts
Expand Down Expand Up @@ -281,7 +281,7 @@ curl http://localhost:3583/agents/hello/session-xyz \
-d '{"message": "Hello from another conversation"}'
```

Agent instances own sandbox state such as files written across prompt and dispatched-input interactions. Harnesses group related session state within an instance. Sessions persist message history and conversation metadata inside a harness. On Cloudflare, session data is backed by Durable Objects and survives across requests. On Node.js, sessions are stored in memory by default unless you provide a custom store.
Agent instances provide a stable identity boundary for prompt and dispatched-input interactions. Harnesses group related session state within an instance. Sessions persist message history and conversation metadata inside a harness. Sandbox-file durability depends on the configured sandbox or connector; the default virtual filesystem is in memory. On Cloudflare, session conversation data is backed by Durable Objects and survives across requests. On Node.js, sessions are stored in memory by default unless you provide a custom store.

In production, generate a stable URL `<id>` for the agent instance you want to preserve. Use `harness.session(threadName)` when you need multiple conversations inside the same harness.

Expand Down Expand Up @@ -418,7 +418,7 @@ await job.ready;
await job.invoke({ text: 'Summarize me' });
```

An exported `websocket` middleware can authenticate its own agent or workflow socket endpoint. Use a custom `app.ts` for centralized authentication or mounted prefixes, applying ordinary Hono middleware before `app.route('/api', flue())`; the same routing model works on Node and Cloudflare. Include the custom mount in `baseUrl: 'https://example.com/api'` and use `websocketUrl: (url) => { url.searchParams.set('token', socketToken); return url; }` for URL-carried or signed handshake authentication. HTTP `token` and `headers` options do not automatically apply to WebSocket upgrades; browsers should use cookies or application-designed URL authentication, while Node clients needing implementation-specific headers can provide a custom `websocket` factory. Avoid header-mutating middleware around WebSocket upgrade routes. `flue dev --target cloudflare` requires `wrangler` as a peer dependency in your project (`npm install --save-dev wrangler`).
An exported `websocket` middleware can authenticate its own agent or workflow socket endpoint. Use a custom `app.ts` for centralized authentication or mounted prefixes, applying ordinary Hono middleware before `app.route('/api', flue())`; the same routing model works on Node and Cloudflare. Include the custom mount in `baseUrl: 'https://example.com/api'` and use `websocketUrl: (url) => { url.searchParams.set('token', socketToken); return url; }` for URL-carried or signed handshake authentication. HTTP `token` and `headers` options do not automatically apply to WebSocket upgrades; browsers should use cookies or application-designed URL authentication, while Node clients needing implementation-specific headers can provide a custom `websocket` factory. Avoid header-mutating middleware around WebSocket upgrade routes. Install `wrangler` in Cloudflare projects that use Wrangler commands such as `wrangler deploy` or secret management; `flue dev --target cloudflare` no longer requires it as an `@flue/cli` peer dependency.

#### Loading environment variables

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
"pagefind": "^1.5.2",
"typescript": "^6.0.3",
"vite": "^7.3.3",
"wrangler": "^4.59.3"
"wrangler": "^4.97.0"
}
}
6 changes: 3 additions & 3 deletions apps/docs/src/content/docs/api/agent-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ Accepts input for asynchronous delivery to a continuing agent session. The creat

`await dispatch(...)` resolves when the current runtime accepts and queues the input. It does not wait for model processing, tool calls, or an agent reply. Dispatched activity belongs to the continuing agent session: it does not create workflow-run history and does not appear in `/runs` or `flue logs`.

Delivery durability depends on the generated target. Node uses a process-lifetime in-memory queue by default. Cloudflare durably admits delivery to the target agent Durable Object and may retry processing after an interruption. Design external side effects to be idempotent. See [Deploy Agents on Node.js](/docs/ecosystem/deploy/node/) and [Deploy Agents on Cloudflare](/docs/ecosystem/deploy/cloudflare/).
Delivery durability depends on the generated target. Node uses a process-lifetime in-memory queue by default. Cloudflare durably admits delivery to the target agent Durable Object, orders it with direct prompts for the same session, and reconciles interruptions conservatively. It retries only when replay safety is provable; external effects still require application-level idempotency. See [Deploy Agents on Node.js](/docs/ecosystem/deploy/node/) and [Deploy Agents on Cloudflare](/docs/ecosystem/deploy/cloudflare/).

## `init(...)`

Expand Down Expand Up @@ -319,7 +319,7 @@ Creates a new session. Defaults to `'default'`. Throws if it already exists.
delete(name?: string): Promise<void>;
```

Deletes a session's stored conversation state. Defaults to `'default'`. No-op when missing. Rejects if the open session has an active operation. Session-management requests for one name are applied in request order.
Deletes a session's stored conversation state. Defaults to `'default'`. No-op when missing. Rejects if the open session has an active operation. On Cloudflare, it also rejects while the session has accepted durable submissions queued or running. Session-management requests for one name are applied in request order.

### `harness.shell(...)`

Expand Down Expand Up @@ -526,7 +526,7 @@ Triggers conversation compaction immediately. Resolves without work when there i
delete(): Promise<void>;
```

Deletes this session's stored conversation state. Rejects while an operation is active. Once deletion starts, the session is unusable and concurrent calls share the same deletion work.
Deletes this session's stored conversation state. Rejects while an operation is active. On Cloudflare, it also rejects while accepted durable submissions are queued or running for the session. Once deletion starts, the session is unusable and concurrent calls share the same deletion work.

#### `CallHandle<T>`

Expand Down
5 changes: 3 additions & 2 deletions apps/docs/src/content/docs/api/data-persistence-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,16 @@ Treat `SessionData` as potentially sensitive. It can include model-visible text,
| State category | Controlled by |
| -------------------------------------------------------------- | ------------------------------------------------------ |
| Agent session messages and compaction state | `SessionStore` / `persist` or the target default |
| Cloudflare agent submission admission, ordering, and terminal inspection rows | The owning agent Durable Object SQLite store |
| Sandbox files, installed dependencies, and workspace artifacts | The configured sandbox or connector |
| Workflow run records and persisted run events | Workflow-run runtime storage, not `SessionStore` alone |
| Mutations performed through tools or external APIs | The external system and application idempotency policy |

A persisted conversation does not make sandbox files durable. A durable workspace does not retain conversation history unless session persistence does as well.
A persisted conversation does not make sandbox files durable. A durable workspace does not retain conversation history unless session persistence does as well. On Cloudflare, a created agent's `persist` override replaces canonical session snapshots only: Flue still stores operational submission rows locally in the owning Durable Object SQLite database. Those rows can contain submitted payloads while queued and running. Terminal rows become eligible for bounded lazy cleanup after seven days and are removed during later agent activity; an entirely idle Durable Object may retain eligible rows longer. The same eligibility horizon bounds duplicate-delivery protection for repeated forwarding of one `dispatchId`; it does not create a public submission lookup API.

## Identity and deletion

Session data is stored under keys derived from Flue identity boundaries: agent instance or workflow invocation ownership, harness name, and session name. The stored record contains a separate opaque provider-affinity key. Delegated `task(...)` calls use internal child sessions whose retained history remains parent-owned; names beginning with `task:` are reserved for those children and cannot be selected as ordinary sessions. Deleting a parent session removes its stored conversation data and retained child task-session tree; application-owned stores may apply broader retention separately. Deletion does not undo external effects or remove sandbox files.
Session data is stored under keys derived from Flue identity boundaries: agent instance or workflow invocation ownership, harness name, and session name. The stored record contains a separate opaque provider-affinity key. Delegated `task(...)` calls use internal child sessions whose retained history remains parent-owned; names beginning with `task:` are reserved for those children and cannot be selected as ordinary sessions. Deleting a parent session removes its stored conversation data and retained child task-session tree; application-owned stores may apply broader retention separately. On Cloudflare, deletion rejects while the session still has queued or running durable submissions and removes settled operational payload copies after snapshot deletion succeeds. Deletion does not undo external effects or remove sandbox files.

## Implementing a store

Expand Down
Loading