Session 管理:会话创建、持久化与恢复

Agent 和用户的对话不是一个一个独立请求的——多轮对话需要"会话"的概念,把上下文串起来。Session 就是这个会话的抽象。

什么是 Session

Session(会话)是 Agent 和用户之间的一次完整对话过程。在 Session 里,Agent 记得之前说过什么、用户问过什么,保持上下文连贯。

用户: 你好                              Session 1
Agent: 你好,有什么可以帮你?
用户: 上海天气怎么样?                    Session 1(继续)
Agent: 上海今天晴天,22度
用户: 那北京呢?                        Session 1(上下文保持)
Agent: 北京今天多云,18度

如果没有 Session,每次请求都是独立的,Agent 就不知道"那北京呢"是在问什么。


Session 的生命周期

创建 Session → 交互(N 轮)→ 结束 Session

创建 Session

session, err := sessions.NewSession(ctx,
    sessions.WithUserID("user-123"),
    sessions.WithAgentID("my-agent"),
)

创建时指定:

  • UserID:用户标识
  • AgentID:Agent 标识

交互

response, err := session.Run(ctx, "上海天气怎么样")
// response = "上海今天晴天,22度"

response, err := session.Run(ctx, "那北京呢")
// response = "北京今天多云,18度"(记得上文)

结束 Session

session.End(ctx)

Session 持久化:会话不丢

默认情况下 Session 数据存在内存里,进程重启就丢了。持久化让 Session 跨进程、跨服务保持。

使用 Redis 持久化

import "github.com/go-redis/redis/v8"

redisClient := redis.NewClient(&redis.Options{
    Addr: "localhost:6379",
})

store := sessions.NewRedisStore(redisClient, "sessions:", time.Hour*24)

session, err := sessions.NewSession(ctx,
    sessions.WithUserID("user-123"),
    sessions.WithAgentID("my-agent"),
    sessions.WithStore(store),  // 持久化存储
)

恢复 Session

用户重新访问时,从存储里恢复:

session, err := store.LoadSession(ctx, "session-id-xxx")
if err != nil {
    // Session 不存在,创建新的
    session, _ = sessions.NewSession(ctx, ...)
}

多用户 Session 管理

生产环境里,一个 Agent 服务多个用户。需要为每个用户维护独立的 Session:

type SessionManager struct {
    store sessions.Store
    mu    sync.Map  // userID -> session
}

func (m *SessionManager) GetSession(ctx context.Context, userID string) (*Session, error) {
    if s, ok := m.mu.Load(userID); ok {
        return s.(*Session), nil
    }

    // 不存在则创建新的
    s, err := sessions.NewSession(ctx,
        sessions.WithUserID(userID),
        sessions.WithAgentID("my-agent"),
        sessions.WithStore(m.store),
    )
    if err != nil {
        return nil, err
    }
    m.mu.Store(userID, s)
    return s, nil
}

这样每个用户有独立的会话上下文,互不干扰。


Session 配置参数

参数说明默认值
SessionTTLSession 过期时间24 小时
MaxTurns最大对话轮数无限制
IdleTimeout空闲超时30 分钟
session, err := sessions.NewSession(ctx,
    sessions.WithUserID("user-123"),
    sessions.WithAgentID("my-agent"),
    sessions.WithTTL(time.Hour*48),      // 48 小时过期
    sessions.WithMaxTurns(100),           // 最多 100 轮
)

常见问题

Q:Session 存 Redis 太大了 A:Session 数据含历史上下文,定期压缩或清理。可以用 session.Compress() 压缩历史消息。

Q:用户换设备了,Session 能恢复吗 A:只要 Session ID 不变,从存储加载即可。Session ID 可以存在 Cookie 或本地存储里。

Q:Session 太多了,占用内存 A:用带过期时间的 Redis Session,Redis 会自动清理长期不活跃的 Session。


下一步

Session 管理了对话历史,接下来看 State——如何读写 Agent 内部的状态,在多轮对话中保持自定义数据。

Tool Confirmation 与安全认证 | State 读写 →


想跟着学更多 Go ADK 实战?关注「全栈之巅-梦兽编程」公众号,每周更新 Go / AI 编程实战干货。