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
8 changes: 8 additions & 0 deletions config.yaml.full
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ database:
region: cn-beijing # default Volcengine TOS Vector region
bucket:
account_id:
# [optional] for long-term memory backend="tos_context" (TOS ContextBucket). Requires tos>=2.9.4b1.
# Note: distinct from `tos` (object storage) and `tos_vector` (vector store); this is the ContextBucket memory service.
tos_context:
account_id: # [required] account ID for ContextBucket control-plane
control_endpoint: # [required] ContextBucket controller (control-plane) endpoint
bucket_name: # ContextBucket name; falls back to LongTermMemory `index`/`app_name`
endpoint: tos-cn-beijing.volces.com # default Volcengine TOS data-plane endpoint
region: cn-beijing # default Volcengine TOS region

# Dynamic config
nacos:
Expand Down
5 changes: 3 additions & 2 deletions docs/content/docs/framework/memory/long-term/index.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ ltm = LongTermMemory(backend="viking", app_name="ltm_demo")

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `backend` | `"local" \| "opensearch" \| "redis" \| "viking" \| "mem0"` or a backend instance | `"opensearch"` | Selects the backend, or pass a `BaseLongTermMemoryBackend` instance directly. `viking_mem` is deprecated and maps to `viking`. |
| `backend` | `"local" \| "opensearch" \| "redis" \| "viking" \| "mem0" \| "tos_context"` or a backend instance | `"opensearch"` | Selects the backend, or pass a `BaseLongTermMemoryBackend` instance directly. `viking_mem` is deprecated and maps to `viking`. |
| `backend_config` | `dict` | `{}` | Config passed to the backend constructor; if it lacks `index`, it's filled from `index` or `app_name`. |
| `top_k` | `int` | `5` | Number of most-similar chunks to retrieve. |
| `index` | `str` | `""` | Index/collection name for storing memories. Falls back to `app_name`, then `default_app`. |
| `app_name` | `str` | `""` | The owning application name; used for data isolation and as the `index` fallback. |
| `user_id` | `str` | `""` | **Deprecated**, kept only for backward compatibility. |

<Callout type="info">
Vector backends (`local`, `opensearch`, `redis`) embed memories, which requires `pip install "veadk-python[extensions]"` and an embedding model (env prefix `MODEL_EMBEDDING_`, falling back to `MODEL_AGENT_API_KEY`). `viking` and `mem0` are managed services and need no local embedding.
Vector backends (`local`, `opensearch`, `redis`) embed memories, which requires `pip install "veadk-python[extensions]"` and an embedding model (env prefix `MODEL_EMBEDDING_`, falling back to `MODEL_AGENT_API_KEY`). `viking`, `mem0`, and `tos_context` are managed services and need no local embedding.
</Callout>

## Backend contract: `BaseLongTermMemoryBackend`
Expand Down Expand Up @@ -70,6 +70,7 @@ Use `local` for debugging; prefer `viking` or `mem0` in production.
| `mem0` | Mem0 memory (managed) | Mem0 API key | Recommended for production | [Mem0](/en/docs/framework/memory/long-term/mem0) |
| `opensearch` | OpenSearch vector store | OpenSearch + embedding | Self-hosted vector search | [OpenSearch](/en/docs/framework/memory/long-term/opensearch) |
| `redis` | Redis vector store | Redis (RediSearch) + embedding | Self-hosted vector search | [Redis](/en/docs/framework/memory/long-term/redis) |
| `tos_context` | TOS ContextBucket (managed) | Volcengine account (AK/SK; temporary credentials also need `VOLCENGINE_SESSION_TOKEN`) + `tos>=2.9.4b1` | Server-side inference/retrieval, per-user isolation | [TOS ContextBucket](/en/docs/framework/memory/long-term/tos-context#configuration) |

## Binding to an Agent

Expand Down
5 changes: 3 additions & 2 deletions docs/content/docs/framework/memory/long-term/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ ltm = LongTermMemory(backend="viking", app_name="ltm_demo")

| 参数 | 类型 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `backend` | `"local" \| "opensearch" \| "redis" \| "viking" \| "mem0"` 或后端实例 | `"opensearch"` | 选择后端实现,也可直接传入一个 `BaseLongTermMemoryBackend` 实例。`viking_mem` 已废弃,自动转为 `viking`。 |
| `backend` | `"local" \| "opensearch" \| "redis" \| "viking" \| "mem0" \| "tos_context"` 或后端实例 | `"opensearch"` | 选择后端实现,也可直接传入一个 `BaseLongTermMemoryBackend` 实例。`viking_mem` 已废弃,自动转为 `viking`。 |
| `backend_config` | `dict` | `{}` | 传给后端构造函数的配置;若不含 `index`,会用 `index` 或 `app_name` 补齐。 |
| `top_k` | `int` | `5` | 检索时返回最相似的片段数量。 |
| `index` | `str` | `""` | 存储记忆所用的索引/集合名。为空时回退到 `app_name`,再为空则用 `default_app`。 |
| `app_name` | `str` | `""` | 拥有该记忆的应用名,常用作数据隔离与 `index` 的回退值。 |
| `user_id` | `str` | `""` | **已废弃**,仅为向后兼容保留。 |

<Callout type="info">
向量类后端(`local`、`opensearch`、`redis`)会对记忆做向量化(embedding),需要安装扩展依赖:`pip install "veadk-python[extensions]"`,并配置 embedding 模型(环境变量前缀 `MODEL_EMBEDDING_`,缺省时复用 `MODEL_AGENT_API_KEY`)。`viking` 与 `mem0` 是托管服务,无需本地 embedding。
向量类后端(`local`、`opensearch`、`redis`)会对记忆做向量化(embedding),需要安装扩展依赖:`pip install "veadk-python[extensions]"`,并配置 embedding 模型(环境变量前缀 `MODEL_EMBEDDING_`,缺省时复用 `MODEL_AGENT_API_KEY`)。`viking`、`mem0` 与 `tos_context` 是托管服务,无需本地 embedding。
</Callout>

## 后端契约:`BaseLongTermMemoryBackend`
Expand Down Expand Up @@ -70,6 +70,7 @@ class BaseLongTermMemoryBackend(ABC, BaseModel):
| `mem0` | Mem0 记忆库(托管) | Mem0 API Key | 生产推荐 | [Mem0](/cn/docs/framework/memory/long-term/mem0) |
| `opensearch` | OpenSearch 向量库 | OpenSearch + embedding | 自建向量检索 | [OpenSearch](/cn/docs/framework/memory/long-term/opensearch) |
| `redis` | Redis 向量库 | Redis(RediSearch) + embedding | 自建向量检索 | [Redis](/cn/docs/framework/memory/long-term/redis) |
| `tos_context` | TOS ContextBucket(托管) | 火山引擎账号(AK/SK,临时凭证另需 `VOLCENGINE_SESSION_TOKEN`)+ `tos>=2.9.4b1` | 服务端推理与检索、按用户隔离 | [TOS ContextBucket](/cn/docs/framework/memory/long-term/tos-context#配置) |

## 绑定到 Agent

Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/framework/memory/long-term/meta.en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"title": "Long-term memory",
"pages": ["index", "local", "vikingdb", "mem0", "opensearch", "redis"]
"pages": ["index", "local", "vikingdb", "mem0", "opensearch", "redis", "tos-context"]
}
2 changes: 1 addition & 1 deletion docs/content/docs/framework/memory/long-term/meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"title": "长期记忆",
"pages": ["index", "local", "vikingdb", "mem0", "opensearch", "redis"]
"pages": ["index", "local", "vikingdb", "mem0", "opensearch", "redis", "tos-context"]
}
91 changes: 91 additions & 0 deletions docs/content/docs/framework/memory/long-term/tos-context.en.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: "TOS ContextBucket (tos_context)"
---

The `tos_context` backend (`TosContextBucketLTMBackend`) uses the ContextBucket memory capability of Volcengine [TOS](https://www.volcengine.com/product/TOS) as long-term storage. It is a managed service: the server performs memory inference and retrieval, so no self-hosted vector store or local embedding is required.

The backend maps `index` (or `app_name`) to a single **ContextBucket**, and maps the runtime `user_id` to a **ContextSet** under that bucket, so memories are naturally isolated per user. The corresponding ContextBucket and ContextSet are created automatically on first use (lazy ensure).

## When to use

- Production with persistence and managed operations;
- When you want the ContextBucket memory capability of Volcengine TOS (server-side inference and retrieval);
- When you want strong isolation by `user_id` (one ContextSet per user).

## Requirements and installation

The ContextBucket API is currently only available in a **pre-release (beta)** TOS SDK: `tos>=2.9.4b1`. VeADK's core dependency is the stable `tos>=2.8.4` (used by TOS object storage and Viking DB), so it does **not** install the beta for you. Before using `backend="tos_context"`, upgrade the TOS SDK explicitly:

```bash
pip install --upgrade "tos>=2.9.4b1" --pre
```

<Callout type="warn">
pip / uv **ignore pre-releases by default**, so you must pass `--pre` (uv uses `--prerelease=allow`). Otherwise `2.9.4b1` won't be installed and you'll still hit the errors below at runtime.
</Callout>

## Common runtime errors and how to handle them

`tos_context` is fail-closed: when a dependency or config requirement is not met, it **raises at initialization** rather than degrading silently or writing bad data. Common errors:

| Error | Trigger | How to fix |
| :--- | :--- | :--- |
| `ImportError` | The `tos` SDK is not installed. | Install it: `pip install --upgrade "tos>=2.9.4b1" --pre`. |
| `RuntimeError` | `tos` is installed but too old (e.g. `2.8.4`, or stable `2.9.2`); `TosClientV2` lacks the ContextBucket methods. | Upgrade to the pre-release: `pip install --upgrade "tos>=2.9.4b1" --pre`. The error message includes the installed version and this command. |
| `ValueError` | `account_id` or `control_endpoint` is not configured. | Set the env vars `DATABASE_TOS_CONTEXT_ACCOUNT_ID` and `DATABASE_TOS_CONTEXT_CONTROL_ENDPOINT` (see the configuration table below). |

<Callout type="info">
**Why a `RuntimeError` instead of an `ImportError` when `tos` is installed?** ContextBucket support was added as new methods on the existing `TosClientV2` class, so an older release still imports fine — it just lacks those methods. At initialization VeADK probes for the required methods (`hasattr`) to decide whether the installed SDK actually supports ContextBucket, turning a silent "imports but fails on call" problem into a clear, actionable error at startup.
</Callout>

## Configuration

Authenticated via Volcengine AK/SK. Credentials are resolved in this order: explicit AK/SK **first** (env `VOLCENGINE_ACCESS_KEY` / `VOLCENGINE_SECRET_KEY`, with the STS token taken from `VOLCENGINE_SESSION_TOKEN`); **if both are not provided**, it falls back to the VeFaaS IAM credential file (`/var/run/secrets/iam/credential`) for the temporary AK/SK and STS token — the path used for keyless cloud deployments (VeFaaS / AgentKit). Other connection settings use the env prefix `DATABASE_TOS_CONTEXT_`; locally they can be placed under `database.tos_context.*` in `config.yaml` (flattened into the matching env vars).

| Field | Env var | Default | Description |
| :--- | :--- | :--- | :--- |
| `volcengine_access_key` | `VOLCENGINE_ACCESS_KEY` | — | Volcengine Access Key (long-term or STS temporary AK). |
| `volcengine_secret_key` | `VOLCENGINE_SECRET_KEY` | — | Volcengine Secret Key (long-term or STS temporary SK). |
| `session_token` | `VOLCENGINE_SESSION_TOKEN` | — | STS security token for temporary credentials (optional; only needed with a temporary AK/SK). |
| `account_id` | `DATABASE_TOS_CONTEXT_ACCOUNT_ID` | — | **Required**. Account ID for the ContextBucket control-plane APIs. |
| `control_endpoint` | `DATABASE_TOS_CONTEXT_CONTROL_ENDPOINT` | — | **Required**. ContextBucket controller (control-plane) endpoint. |
| `context_bucket_name` | `DATABASE_TOS_CONTEXT_BUCKET_NAME` | falls back to `index` | ContextBucket name. If unset, uses the `LongTermMemory` `index` (or `app_name`). |
| `endpoint` | `DATABASE_TOS_CONTEXT_ENDPOINT` | `tos-cn-beijing.volces.com` | TOS data-plane endpoint. |
| `region` | `DATABASE_TOS_CONTEXT_REGION` | `cn-beijing` | Region. |

<Callout type="warn">
`account_id` and `control_endpoint` are required; a missing value raises `ValueError` at initialization (fail-closed — no silent degradation).
</Callout>

<Callout type="info">
The STS token reuses the global `VOLCENGINE_SESSION_TOKEN` convention (consistent with TOS object storage and other components); the standalone `DATABASE_TOS_CONTEXT_SECURITY_TOKEN` is no longer used. It is not needed when using long-term AK/SK. If `VOLCENGINE_ACCESS_KEY` / `VOLCENGINE_SECRET_KEY` are not both provided, the VeFaaS IAM credential file is read instead; a missing file raises `FileNotFoundError`.
</Callout>

## Usage

```python
from veadk import Agent
from veadk.memory.long_term_memory import LongTermMemory

# index maps to the ContextBucket name and must satisfy the bucket naming rules (see Callout below)
ltm = LongTermMemory(
backend="tos_context",
index="demo-agent-memory",
top_k=5,
)
agent = Agent(
name="demo",
long_term_memory=ltm,
auto_save_session=True, # persist to long-term memory at session end
)
```

At init, if the ContextBucket doesn't exist, VeADK creates it; the first write/search for each `user_id` also creates the corresponding ContextSet if missing (enabling the `memory` scene).

<Callout type="info">
`index` (the ContextBucket name) must follow TOS bucket naming rules: **length 3–63**, containing only **lowercase letters, digits, and hyphens (`-`)**, and not starting or ending with a hyphen. Use `DATABASE_TOS_CONTEXT_BUCKET_NAME` to override the bucket name derived from `app_name`/`index`.
</Callout>

<Callout type="info">
Memories are isolated by `user_id`: different `user_id`s write to different ContextSets, and retrieval only matches memories of the same `user_id`. Use a consistent `user_id` for cross-session recall.
</Callout>
91 changes: 91 additions & 0 deletions docs/content/docs/framework/memory/long-term/tos-context.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: "TOS ContextBucket(tos_context)"
---

`tos_context` 后端(`TosContextBucketLTMBackend`)使用火山引擎 [TOS](https://www.volcengine.com/product/TOS) 的 ContextBucket 记忆能力作为长期记忆存储。它是托管服务,由服务端完成记忆推理(inference)与检索,无需自建向量库或本地 embedding。

后端把 `index`(或 `app_name`)映射为一个 **ContextBucket**,把运行时的 `user_id` 映射为该桶下的一个 **ContextSet**,从而按用户天然隔离记忆。首次使用时会自动创建对应的 ContextBucket 与 ContextSet(Lazy Ensure)。

## 何时使用

- 生产环境、需要持久化与托管运维;
- 希望使用火山引擎 TOS 的 ContextBucket 记忆能力(服务端推理与检索);
- 希望按 `user_id` 做强隔离(每个用户对应一个 ContextSet)。

## 依赖要求与安装

ContextBucket API 目前只在**预发布(beta)版本**的 TOS SDK 中提供:`tos>=2.9.4b1`。VeADK 的核心依赖为稳定版 `tos>=2.8.4`(供 TOS 对象存储、Viking DB 使用),**不会**自动为你安装 beta 版。因此在使用 `backend="tos_context"` 前,需要显式升级 TOS SDK:

```bash
pip install --upgrade "tos>=2.9.4b1" --pre
```

<Callout type="warn">
pip / uv 默认会**忽略预发布版本**,必须显式加 `--pre`(uv 使用 `--prerelease=allow`),否则不会安装上 `2.9.4b1`,运行时仍会命中下方的报错。
</Callout>

## 常见运行时报错与处理

`tos_context` 采用 fail-closed 设计:依赖或配置不满足时会**在初始化阶段直接抛错**,不会静默降级或写入错误数据。常见错误及处理如下:

| 报错类型 | 触发条件 | 处理方式 |
| :--- | :--- | :--- |
| `ImportError` | 环境中未安装 `tos` SDK。 | 安装 SDK:`pip install --upgrade "tos>=2.9.4b1" --pre`。 |
| `RuntimeError` | 已安装 `tos`,但版本过旧(如 `2.8.4`、`2.9.2` 稳定版),`TosClientV2` 缺少 ContextBucket 相关方法。 | 升级到预发布版:`pip install --upgrade "tos>=2.9.4b1" --pre`。报错信息会附带当前已安装版本号与该命令。 |
| `ValueError` | `account_id` 或 `control_endpoint` 未配置。 | 补齐环境变量 `DATABASE_TOS_CONTEXT_ACCOUNT_ID`、`DATABASE_TOS_CONTEXT_CONTROL_ENDPOINT`(见下方配置表)。 |

<Callout type="info">
**为什么装了 `tos` 还会报 `RuntimeError` 而不是 `ImportError`?** 因为 ContextBucket 能力是在既有的 `TosClientV2` 类上**新增方法**实现的,旧版本仍可 `import tos` 成功、只是缺少这些方法。VeADK 在初始化时会通过方法探测(`hasattr`)判断当前 SDK 是否真正支持 ContextBucket,从而把"能 import 但调用时静默失败"的隐性问题,转化为初始化阶段清晰、可操作的报错。
</Callout>

## 配置

通过火山引擎 AK/SK 鉴权。凭据解析顺序为:**优先**使用显式的 AK/SK(环境变量 `VOLCENGINE_ACCESS_KEY` / `VOLCENGINE_SECRET_KEY`,此时 STS Token 取自 `VOLCENGINE_SESSION_TOKEN`);**若二者未同时提供**,则回退到 VeFaaS IAM 凭证文件(`/var/run/secrets/iam/credential`),从中读取临时 AK/SK 与 STS Token——这是云上部署(VeFaaS / AgentKit)免密运行的路径。其余连接项使用环境变量前缀 `DATABASE_TOS_CONTEXT_`,本地可写在 `config.yaml` 的 `database.tos_context.*` 下(会被拍平为对应环境变量)。

| 配置项 | 环境变量 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- |
| `volcengine_access_key` | `VOLCENGINE_ACCESS_KEY` | — | 火山引擎 Access Key(可为长期或 STS 临时 AK)。 |
| `volcengine_secret_key` | `VOLCENGINE_SECRET_KEY` | — | 火山引擎 Secret Key(可为长期或 STS 临时 SK)。 |
| `session_token` | `VOLCENGINE_SESSION_TOKEN` | — | STS 临时凭证的 Security Token(可选,仅在使用临时 AK/SK 时需要)。 |
| `account_id` | `DATABASE_TOS_CONTEXT_ACCOUNT_ID` | — | **必填**。账号 ID,用于 ContextBucket 控制面接口。 |
| `control_endpoint` | `DATABASE_TOS_CONTEXT_CONTROL_ENDPOINT` | — | **必填**。ContextBucket 控制面(Controller)域名。 |
| `context_bucket_name` | `DATABASE_TOS_CONTEXT_BUCKET_NAME` | 回退到 `index` | ContextBucket 名。未设置时使用 `LongTermMemory` 的 `index`(或 `app_name`)。 |
| `endpoint` | `DATABASE_TOS_CONTEXT_ENDPOINT` | `tos-cn-beijing.volces.com` | TOS 数据面域名。 |
| `region` | `DATABASE_TOS_CONTEXT_REGION` | `cn-beijing` | 区域。 |

<Callout type="warn">
`account_id` 与 `control_endpoint` 为必填项,缺失会在初始化时直接抛出 `ValueError`(fail-closed,不会静默降级)。
</Callout>

<Callout type="info">
STS Token 复用全局约定 `VOLCENGINE_SESSION_TOKEN`(与 TOS 对象存储等其他组件一致),不再使用独立的 `DATABASE_TOS_CONTEXT_SECURITY_TOKEN`。使用长期 AK/SK 时无需设置。若 `VOLCENGINE_ACCESS_KEY` / `VOLCENGINE_SECRET_KEY` 未同时提供,会尝试读取 VeFaaS IAM 凭证文件;文件不存在时抛出 `FileNotFoundError`。
</Callout>

## 用法

```python
from veadk import Agent
from veadk.memory.long_term_memory import LongTermMemory

# index 会映射为 ContextBucket 名,必须满足桶命名规则(见下方 Callout)
ltm = LongTermMemory(
backend="tos_context",
index="demo-agent-memory",
top_k=5,
)
agent = Agent(
name="demo",
long_term_memory=ltm,
auto_save_session=True, # 会话结束自动写入长期记忆
)
```

初始化时若 ContextBucket 不存在,VeADK 会自动创建;每个 `user_id` 首次写入/检索时,若对应的 ContextSet 不存在也会自动创建(并启用 `memory` 场景)。

<Callout type="info">
`index`(即 ContextBucket 名)需满足 TOS 桶命名规则:**长度 3–63**,仅包含**小写字母、数字和连字符(`-`)**,且不能以连字符开头或结尾。可用 `DATABASE_TOS_CONTEXT_BUCKET_NAME` 覆盖由 `app_name`/`index` 推导出的桶名。
</Callout>

<Callout type="info">
记忆按 `user_id` 隔离:不同 `user_id` 写入的是不同的 ContextSet,检索时也只会命中同一 `user_id` 的记忆。跨会话召回时请确保使用一致的 `user_id`。
</Callout>
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ dependencies = [
"websockets>=15,<16", # Stream temporary AgentKit Sandbox conversations
"openviking-sdk>=0.1.3",
"python-frontmatter==1.1.0",
"tos>=2.8.4", # For TOS storage and Viking DB
"tos>=2.8.4", # For TOS storage and Viking DB
]

[project.scripts]
Expand Down
Loading