Skip to content
Draft
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 .changeset/calm-rivers-session.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agents": minor
---

Graduate the Session API to the stable `agents/sessions` entry point. The previous `agents/experimental/memory/session` path remains available as a deprecated compatibility re-export.
2 changes: 1 addition & 1 deletion docs/agents/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ The differentiator is not "we have durable state" — it is what happens when a
- [Server-Driven Messages](./server-driven-messages.md) - Autonomous agent workflows: scheduled follow-ups, queue processing, webhooks, chained reasoning
- TODO: [Using AI Models](./using-ai-models.md) - OpenAI, Anthropic, Workers AI, and other providers
- TODO: [RAG (Retrieval Augmented Generation)](./rag.md) - Vector search with Vectorize
- [Sessions (Experimental)](./sessions.md) - Persistent conversation storage with tree-structured messages, context blocks, compaction, and search
- [Sessions](./sessions.md) - Persistent conversation storage with tree-structured messages, context blocks, compaction, and search
- [Workspace (Experimental)](https://github.com/cloudflare/agents/blob/main/docs/shell/index.md) - Durable virtual filesystem backed by SQLite + R2
- [Codemode (Experimental)](https://github.com/cloudflare/agents/blob/main/docs/agents/codemode.md) - LLM-generated executable code for tool orchestration
- [Client Tools Continuation](./client-tools-continuation.md) - Handling tool calls across client/server
Expand Down
47 changes: 18 additions & 29 deletions docs/agents/sessions.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# Sessions (Experimental)
# Sessions

The Session API provides persistent conversation storage for agents, with tree-structured messages, context blocks, compaction, full-text search, and AI-controllable tools. By default it uses Durable Object SQLite; external Postgres storage is also available for apps that need shared database access, analytics, or cross-DO queries.

> **Experimental.** The Session API is under `agents/experimental/memory/session`. The API surface is stable but may evolve before graduating to the main package.

## Quick Start

```typescript
import { Agent } from "agents";
import { Session } from "agents/experimental/memory/session";
import { Session } from "agents/sessions";

class MyAgent extends Agent {
session = Session.create(this)
Expand Down Expand Up @@ -53,10 +51,7 @@ const session = Session.create(this)
**Direct constructor** — takes a `SessionProvider` and options directly. Used when you want full control over providers.

```typescript
import {
AgentSessionProvider,
AgentContextProvider
} from "agents/experimental/memory/session";
import { AgentSessionProvider, AgentContextProvider } from "agents/sessions";

const session = new Session(new AgentSessionProvider(this), {
context: [
Expand Down Expand Up @@ -182,7 +177,7 @@ All providers also support an optional `init(label)` method, called before first
**`AgentContextProvider`** — SQLite-backed writable context. This is what you get by default when using the builder without an explicit provider.

```typescript
import { AgentContextProvider } from "agents/experimental/memory/session";
import { AgentContextProvider } from "agents/sessions";

// Explicit usage — key determines the SQLite row
new AgentContextProvider(this, "memory");
Expand All @@ -191,7 +186,7 @@ new AgentContextProvider(this, "memory");
**`R2SkillProvider`** — Cloudflare R2 bucket for on-demand document loading. Skills are listed in the system prompt as metadata; the model loads full content on demand via `load_context`.

```typescript
import { R2SkillProvider } from "agents/experimental/memory/session";
import { R2SkillProvider } from "agents/sessions";

Session.create(this).withContext("skills", {
provider: new R2SkillProvider(env.SKILLS_BUCKET, { prefix: "skills/" })
Expand All @@ -203,7 +198,7 @@ Descriptions are stored in R2 custom metadata (`description` key).
**`AgentSearchProvider`** — SQLite FTS5 searchable context. Entries are indexed and searchable by the model via `search_context`.

```typescript
import { AgentSearchProvider } from "agents/experimental/memory/session";
import { AgentSearchProvider } from "agents/sessions";

Session.create(this).withContext("knowledge", {
description: "Searchable knowledge base",
Expand Down Expand Up @@ -363,7 +358,7 @@ Compaction summarizes older messages to keep conversations within token limits.
### Setup

```typescript
import { createCompactFunction } from "agents/experimental/memory/utils/compaction-helpers";
import { createCompactFunction } from "agents/sessions";

const session = Session.create(this)
.withContext("memory", { maxTokens: 1100 })
Expand Down Expand Up @@ -451,7 +446,7 @@ const session = Session.create(this)
### Creating a SessionManager

```typescript
import { SessionManager } from "agents/experimental/memory/session";
import { SessionManager } from "agents/sessions";

const manager = SessionManager.create(this)
.withContext("soul", { provider: { get: async () => "You are helpful." } })
Expand Down Expand Up @@ -795,7 +790,7 @@ import {
PostgresSessionProvider,
PostgresContextProvider,
PostgresSearchProvider
} from "agents/experimental/memory/session";
} from "agents/sessions";
import { Client } from "pg";

class MyAgent extends Agent<Env> {
Expand Down Expand Up @@ -884,15 +879,12 @@ The migration SQL above includes both tables with tsvector columns and GIN index

## Utilities

Exported from `agents/experimental/memory/utils`:
Exported from `agents/sessions`:

### Token Estimation

```typescript
import {
estimateStringTokens,
estimateMessageTokens
} from "agents/experimental/memory/utils/tokens";
import { estimateStringTokens, estimateMessageTokens } from "agents/sessions";

estimateStringTokens("Hello world"); // heuristic: max(chars/4, words*1.3)
estimateMessageTokens(messages); // sum with 4 tokens per-message overhead
Expand All @@ -911,7 +903,7 @@ import {
computeSummaryBudget,
buildSummaryPrompt,
COMPACTION_PREFIX
} from "agents/experimental/memory/utils/compaction-helpers";
} from "agents/sessions";
```

- `createCompactFunction(options)` — Full compaction implementation. See [Compaction](#compaction).
Expand All @@ -926,7 +918,7 @@ import {

## Exports

Everything is exported from `agents/experimental/memory/session`:
Session APIs and compaction utilities are exported from `agents/sessions`. The previous `agents/experimental/memory/session` and `agents/experimental/memory/utils` paths remain as deprecated compatibility re-exports.

```typescript
import {
Expand Down Expand Up @@ -966,10 +958,10 @@ import {
type StoredCompaction,
type SqlProvider,
type PostgresConnection
} from "agents/experimental/memory/session";
} from "agents/sessions";
```

Compaction utilities from `agents/experimental/memory/utils/compaction-helpers`:
Compaction utilities from `agents/sessions`:

```typescript
import {
Expand All @@ -979,16 +971,13 @@ import {
COMPACTION_PREFIX,
type CompactResult,
type CompactOptions
} from "agents/experimental/memory/utils/compaction-helpers";
} from "agents/sessions";
```

Token utilities from `agents/experimental/memory/utils/tokens`:
Token utilities from `agents/sessions`:

```typescript
import {
estimateStringTokens,
estimateMessageTokens
} from "agents/experimental/memory/utils/tokens";
import { estimateStringTokens, estimateMessageTokens } from "agents/sessions";
```

---
Expand Down
2 changes: 1 addition & 1 deletion docs/think/lifecycle-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ configureSession(session: Session): Session | Promise<Session>

```typescript
import { Think, Session } from "@cloudflare/think";
import { createCompactFunction } from "agents/experimental/memory/utils/compaction-helpers";
import { createCompactFunction } from "agents/sessions";
import { generateText } from "ai";

export class MyAgent extends Think<Env> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { createExecuteTool } from "@cloudflare/think/tools/execute";
import { createWorkspaceTools } from "@cloudflare/think/tools/workspace";
import { createExtensionTools } from "@cloudflare/think/tools/extensions";
import { createQuickActionTools } from "@cloudflare/think/tools/browser";
import { createCompactFunction } from "agents/experimental/memory/utils";
import { AgentSearchProvider } from "agents/experimental/memory/session";
import { createCompactFunction } from "agents/sessions";
import { AgentSearchProvider } from "agents/sessions";
import type {
TurnContext,
TurnConfig,
Expand Down
2 changes: 1 addition & 1 deletion experimental/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ The code here is for exploration, prototyping, and validating patterns that may
- **[forever.md](./forever.md)** — Design doc for durable long-running execution. Covers `keepAlive`, `runFiber` (checkpointing, eviction recovery), and `AIChatAgent` chat recovery via `onChatRecovery`. Built into the `Agent` and `AIChatAgent` base classes.
- **[forever-fibers/](./forever-fibers/)** — Example of `Agent.runFiber()` for durable background work with real-time progress tracking.
- **[forever-chat/](./forever-chat/)** — Example of `AIChatAgent` with `chatRecovery` for multi-provider chat recovery (Workers AI, OpenAI, Anthropic).
- **[session-memory](./session-memory/)** — Example of the Session API for conversation history with automatic compaction. Demonstrates `agents/experimental/memory/session` with micro-compaction and LLM-based summarization.
- **[session-memory](./session-memory/)** — Example of the Session API for conversation history with automatic compaction. Demonstrates `agents/sessions` with micro-compaction and LLM-based summarization.
11 changes: 4 additions & 7 deletions experimental/session-memory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ import {
routeAgentRequest,
type StreamingResponse
} from "agents";
import { Session } from "agents/experimental/memory/session";
import {
createCompactFunction,
truncateOlderMessages
} from "agents/experimental/memory/utils";
import { Session } from "agents/sessions";
import { createCompactFunction, truncateOlderMessages } from "agents/sessions";
import { generateText, streamText, convertToModelMessages } from "ai";

export class ChatAgent extends Agent<Env> {
Expand Down Expand Up @@ -173,7 +170,7 @@ Compaction replaces older messages with a summary overlay, keeping the conversat
Built-in compaction implementation. Returns a function compatible with `onCompaction()`.

```typescript
import { createCompactFunction } from "agents/experimental/memory/utils";
import { createCompactFunction } from "agents/sessions";

createCompactFunction({
// Required: LLM call for summarization
Expand Down Expand Up @@ -238,7 +235,7 @@ You can pass any function to `onCompaction()`. It receives the full message hist
`truncateOlderMessages` truncates tool outputs and long text in older messages before sending to the LLM. Does not mutate the stored messages. Structured tool outputs keep their container shape, with large nested fields truncated in place.

```typescript
import { truncateOlderMessages } from "agents/experimental/memory/utils";
import { truncateOlderMessages } from "agents/sessions";

const truncated = truncateOlderMessages(history, {
keepRecent: 4, // recent messages left intact (default: 4)
Expand Down
7 changes: 2 additions & 5 deletions experimental/session-memory/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ import {
routeAgentRequest,
type StreamingResponse
} from "agents";
import { Session } from "agents/experimental/memory/session";
import {
truncateOlderMessages,
createCompactFunction
} from "agents/experimental/memory/utils";
import { Session } from "agents/sessions";
import { truncateOlderMessages, createCompactFunction } from "agents/sessions";
import type { UIMessage } from "ai";
import { createWorkersAI } from "workers-ai-provider";
import {
Expand Down
4 changes: 2 additions & 2 deletions experimental/session-multichat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Demonstrates the experimental `SessionManager` API for managing multiple indepen
`SessionManager` creates and manages multiple `Session` instances, each with isolated message history but shared context block configuration.

```typescript
import { SessionManager } from "agents/experimental/memory/session";
import { createCompactFunction } from "agents/experimental/memory/utils";
import { SessionManager } from "agents/sessions";
import { createCompactFunction } from "agents/sessions";

export class MultiSessionAgent extends Agent<Env> {
manager = SessionManager.create(this)
Expand Down
7 changes: 2 additions & 5 deletions experimental/session-multichat/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ import {
routeAgentRequest,
type StreamingResponse
} from "agents";
import { SessionManager } from "agents/experimental/memory/session";
import {
truncateOlderMessages,
createCompactFunction
} from "agents/experimental/memory/utils";
import { SessionManager } from "agents/sessions";
import { truncateOlderMessages, createCompactFunction } from "agents/sessions";
import type { UIMessage } from "ai";
import { createWorkersAI } from "workers-ai-provider";
import {
Expand Down
2 changes: 1 addition & 1 deletion experimental/session-planetscale/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
PostgresSessionProvider,
PostgresContextProvider,
PostgresSearchProvider
} from "agents/experimental/memory/session";
} from "agents/sessions";
import type { UIMessage } from "ai";
import { createWorkersAI } from "workers-ai-provider";
import { generateText, convertToModelMessages, stepCountIs } from "ai";
Expand Down
7 changes: 2 additions & 5 deletions experimental/session-search/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ All providers receive their block label via `init(label)` during setup — no ne
`AgentSearchProvider` is the built-in implementation using Durable Object SQLite with FTS5 full-text search.

```typescript
import {
Session,
AgentSearchProvider
} from "agents/experimental/memory/session";
import { Session, AgentSearchProvider } from "agents/sessions";

Session.create(this)
.withContext("soul", {
Expand Down Expand Up @@ -81,7 +78,7 @@ Content is stored in two SQLite tables within the Durable Object:
For multi-chat agents, `SessionManager` can expose conversation history search across all sessions:

```typescript
import { SessionManager } from "agents/experimental/memory/session";
import { SessionManager } from "agents/sessions";

SessionManager.create(this)
.withContext("memory", { maxTokens: 1100 })
Expand Down
10 changes: 2 additions & 8 deletions experimental/session-search/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,8 @@ import {
routeAgentRequest,
type StreamingResponse
} from "agents";
import {
AgentSearchProvider,
Session
} from "agents/experimental/memory/session";
import {
createCompactFunction,
truncateOlderMessages
} from "agents/experimental/memory/utils";
import { AgentSearchProvider, Session } from "agents/sessions";
import { createCompactFunction, truncateOlderMessages } from "agents/sessions";
import type { UIMessage } from "ai";
import {
convertToModelMessages,
Expand Down
2 changes: 1 addition & 1 deletion experimental/session-skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Think handles the entire chat lifecycle — streaming, tool calls, message persi
```typescript
import { Think } from "@cloudflare/think";
import type { Session } from "@cloudflare/think";
import { R2SkillProvider } from "agents/experimental/memory/session";
import { R2SkillProvider } from "agents/sessions";

export class SkillsAgent extends Think<Env> {
getModel() {
Expand Down
4 changes: 2 additions & 2 deletions experimental/session-skills/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
*/

import { callable, routeAgentRequest } from "agents";
import { R2SkillProvider } from "agents/experimental/memory/session";
import { createCompactFunction } from "agents/experimental/memory/utils";
import { R2SkillProvider } from "agents/sessions";
import { createCompactFunction } from "agents/sessions";
import { generateText } from "ai";
import type { Session } from "@cloudflare/think";
import { Think } from "@cloudflare/think";
Expand Down
3 changes: 3 additions & 0 deletions packages/agents/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Each export maps to a public entry point that users `import` from. These are the
| `agents/email` | `src/email.ts` | Email routing, resolvers, header signing |
| `agents/workflows` | `src/workflows.ts` | `AgentWorkflow` — Workflows integrated with Agents |
| `agents/schedule` | `src/schedule.ts` | Scheduling types |
| `agents/sessions` | `src/sessions/index.ts` | Conversation history, context, compaction, search, skills, and providers |
| `agents/observability` | `src/observability/index.ts` | Observability event types and emitters |
| `agents/ai-chat-agent` | `src/ai-chat-agent.ts` | Legacy AI chat agent (prefer `@cloudflare/ai-chat`) |
| `agents/ai-react` | `src/ai-react.tsx` | Legacy AI React hooks (prefer `@cloudflare/ai-chat`) |
Expand Down Expand Up @@ -70,6 +71,8 @@ src/
auth-context.ts
worker-transport.ts

sessions/ # Session history, context, compaction, search, providers

observability/ # Observability event system
index.ts
base.ts
Expand Down
5 changes: 5 additions & 0 deletions packages/agents/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@
"import": "./dist/workflows.js",
"require": "./dist/workflows.js"
},
"./sessions": {
"types": "./dist/sessions/index.d.ts",
"import": "./dist/sessions/index.js",
"require": "./dist/sessions/index.js"
},
"./experimental/memory/session": {
"types": "./dist/experimental/memory/session/index.d.ts",
"import": "./dist/experimental/memory/session/index.js",
Expand Down
1 change: 1 addition & 0 deletions packages/agents/scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const entries = [
"src/mcp/x402.ts",
"src/observability/index.ts",
"src/codemode/ai.ts",
"src/sessions/index.ts",
"src/experimental/memory/session/index.ts",
"src/experimental/memory/utils/index.ts",
"src/browser/index.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/agents/src/chat/orphan-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* (steps (c)/(d) of the chat-recovery orphan path) goes through.
*
* It is the **write subset** of the `SessionProvider` interface
* (`experimental/memory/session`): `getMessage` + `appendMessage` +
* (`sessions`): `getMessage` + `appendMessage` +
* `updateMessage`. Target-id resolution (step (b)) stays a per-host hook, so
* `getLatestLeaf` is intentionally omitted here.
*
Expand Down
Loading
Loading