Note
This page has been superseded by Distributed Storage — Redis. Content below is kept for reference.
Redis State Store¶
agentscope-extensions-redis persists AgentScope agent state in Redis. The unified RedisClientAdapter abstracts over Jedis, Lettuce, and Redisson, covering Standalone, Cluster, and Sentinel deployment modes.
Add the dependency¶
<dependency>
<groupId>io.agentscope</groupId>
<artifactId>agentscope-extensions-redis</artifactId>
<version>${agentscope.version}</version>
</dependency>
The module does not pin a Redis client — bring whatever you already use (Jedis / Lettuce / Redisson).
Quickstart (Lettuce, standalone)¶
import io.lettuce.core.RedisClient;
import io.agentscope.core.state.AgentStateStore;
import io.agentscope.extensions.redis.state.RedisAgentStateStore;
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
AgentStateStore stateStore = RedisAgentStateStore.builder()
.lettuceClient(redisClient)
.build();
Wiring each client¶
Jedis¶
import redis.clients.jedis.UnifiedJedis;
UnifiedJedis jedis = new redis.clients.jedis.JedisPooled("localhost", 6379);
AgentStateStore stateStore = RedisAgentStateStore.builder()
.jedisClient(jedis) // UnifiedJedis, JedisCluster, JedisSentineled all work
.build();
Lettuce cluster¶
import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.RedisURI;
RedisClusterClient clusterClient = RedisClusterClient.create(
RedisURI.create("redis://localhost:7000"));
AgentStateStore stateStore = RedisAgentStateStore.builder()
.lettuceClusterClient(clusterClient)
.build();
Redisson¶
import org.redisson.Redisson;
import org.redisson.config.Config;
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
RedissonClient redisson = Redisson.create(config);
AgentStateStore stateStore = RedisAgentStateStore.builder()
.redissonClient(redisson)
.build();
Redisson also supports
useClusterServers()/useSentinelServers()/useMasterSlaveServers(); pass the resultingRedissonClienttoredissonClient(...).
Custom key prefix¶
By default, all keys look like agentscope:session:{userSegment}/{sessionId}:... (where userSegment is the userId, or __anon__ for anonymous sessions). When several projects share the same Redis, override it:
AgentStateStore stateStore = RedisAgentStateStore.builder()
.lettuceClient(redisClient)
.keyPrefix("myapp:session:")
.build();
Key layout¶
The (userId, sessionId) pair is packed into a single slot id {userSegment}/{sessionId} (userSegment = userId, or __anon__ when userId is null).
Type |
Key pattern |
|---|---|
Single value |
|
List |
|
List hash |
|
Session index |
|
The _keys index makes delete(userId, sessionId) and exists(userId, sessionId) O(1) without needing KEYS *.
Wire into an agent¶
ReActAgent agent = ReActAgent.builder()
.name("assistant")
.model(model)
.stateStore(stateStore)
.build();
After this, your Memory, Workspace, Plan, etc. are persisted through Redis automatically. The slot each call reads / writes is chosen per-call from the RuntimeContext:
RuntimeContext rc = RuntimeContext.builder()
.userId("alice")
.sessionId("session-1")
.build();
agent.call(msg, rc).block();
Custom adapter¶
If you target a Redis-compatible store (KeyDB, Tair, …), implement RedisClientAdapter and inject it via clientAdapter(...):
AgentStateStore stateStore = RedisAgentStateStore.builder()
.clientAdapter(new MyCustomAdapter(...))
.build();
Builder reference¶
Method |
Notes |
|---|---|
|
Jedis standalone / cluster / sentinel |
|
Lettuce standalone / sentinel |
|
Lettuce cluster |
|
Redisson, any deployment mode |
|
Custom adapter |
|
Default |
The client setters are mutually exclusive — set exactly one.