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
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,56 @@ export REDISVL_VECTOR_DIMENSIONS=768 # Required for Ollama

See **[LLM Providers](https://redis.github.io/agent-memory-server/llm-providers/)** for complete configuration options.

## Redis Cloud Agent Memory migration

Redis Cloud Agent Memory Service stores long-term memories in a Cloud service key layout, while local `agent-memory-server` stores records in the RedisVL index layout. If you copy Redis data from a Cloud Agent Memory store into a local Redis deployment, run the migration command before rebuilding the local search index.

Cloud exports observed in Redis use keys like:

```text
memory:<store_id>:ltm:<memory_id>
```

with fields such as `id`, `owner_id`, and `text_vector`. Local `agent-memory-server` indexes keys like:

```text
memory_idx:<memory_id>
```

with fields such as `id_`, `user_id`, and `vector`. The migration copies source hashes into local-shaped hashes, converts Cloud millisecond timestamps to seconds, and downcasts Cloud float64 vector blobs to RedisVL's local FLOAT32 vector format when needed. Source keys are not deleted.

Dry run first:

```bash
uv run agent-memory migrate-cloud-long-term-memory \
--store-id <redis-cloud-agent-memory-store-id>
```

Apply the migration:

```bash
uv run agent-memory migrate-cloud-long-term-memory \
--store-id <redis-cloud-agent-memory-store-id> \
--apply
```

Then rebuild the local index:

```bash
uv run agent-memory rebuild-index
```

Useful options:

```text
--source-pattern <pattern> Override the source SCAN pattern.
--target-prefix <prefix> Override the local target prefix, default memory_idx.
--batch-size <n> Tune SCAN/write batch size.
--overwrite Replace existing target keys instead of skipping them.
```

See [Redis Cloud Agent Memory migration](docs/redis-cloud-migration.md) for the full schema mapping and Cloud-to-local workflow.

## Documentation

📚 **[Full Documentation](https://redis.github.io/agent-memory-server/)** - Complete guides, API reference, and examples
Expand Down
75 changes: 75 additions & 0 deletions agent_memory_server/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,81 @@ async def run_migrations():
click.echo("Memory migrations completed successfully.")


@cli.command("migrate-cloud-long-term-memory")
@click.option(
"--store-id",
default=None,
help="Redis Cloud Agent Memory store ID. Builds source pattern memory:<store-id>:ltm:*.",
)
@click.option(
"--source-pattern",
default=None,
help="Explicit source SCAN pattern. Defaults to memory:<store-id>:ltm:* or memory:*:ltm:*.",
)
@click.option(
"--target-prefix",
default=None,
help="Local RedisVL memory key prefix. Defaults to REDIS_MEMORY_REDISVL_INDEX_PREFIX/memory_idx.",
)
@click.option("--batch-size", default=500, show_default=True, type=int)
@click.option(
"--apply",
"apply_changes",
is_flag=True,
help="Actually write migrated memory_idx:<id> hashes. Without this, runs dry-run only.",
)
@click.option(
"--overwrite",
is_flag=True,
help="Overwrite existing target keys. By default existing local records are skipped.",
)
def migrate_cloud_long_term_memory_command(
store_id: str | None,
source_pattern: str | None,
target_prefix: str | None,
batch_size: int,
apply_changes: bool,
overwrite: bool,
):
"""Copy Redis Cloud Agent Memory Service LTM hashes into local AMS schema.

This migrates cloud-exported hashes shaped as memory:<store_id>:ltm:<id>
with fields id/owner_id/text_vector into the local RedisVL schema shaped as
memory_idx:<id> with fields id_/user_id/vector. Source keys are never deleted.
"""
import asyncio

from agent_memory_server.redis_cloud_migration import (
migrate_cloud_long_term_memory,
)

configure_logging()

async def run_migration():
redis = await get_redis_conn()
return await migrate_cloud_long_term_memory(
redis,
store_id=store_id,
source_pattern=source_pattern,
target_prefix=target_prefix,
batch_size=batch_size,
dry_run=not apply_changes,
overwrite=overwrite,
)

stats = asyncio.run(run_migration())
result = stats.as_dict()
result["dry_run"] = not apply_changes
result["overwrite"] = overwrite
result["source_pattern"] = source_pattern or (
f"memory:{store_id}:ltm:*" if store_id else "memory:*:ltm:*"
)
result["target_prefix"] = target_prefix or settings.redisvl_index_prefix
click.echo(json.dumps(result, indent=2, sort_keys=True))
if not apply_changes:
click.echo("Dry run only. Re-run with --apply to write migrated target keys.")


@cli.command()
@click.option(
"--batch-size",
Expand Down
Loading