Memory & Workspace

Agentica 提供两层记忆系统:运行时记忆(WorkingMemory)持久化记忆(Workspace)

运行时记忆:WorkingMemory

管理当前会话的消息历史,支持 token 感知的截断。

from agentica import Agent

agent = Agent(
    add_history_to_context=True,   # 将历史加入上下文
    num_history_turns=5,            # 保留最近 5 轮
)

会话摘要

WorkingMemory 支持自动生成会话摘要,在多轮对话后保留关键信息:

from agentica.memory import WorkingMemory

agent = Agent(
    working_memory=WorkingMemory(
        create_session_summary=True,            # 每轮结束后生成摘要
        update_session_summary_after_run=True,  # 自动更新
        max_messages=200,                       # 消息软上限(FIFO 淘汰)
    ),
)

会话摘要会注入到 System Prompt 末尾,同时被 CompressionManager.auto_compact() 直接复用——压缩时无需额外 LLM 调用。


持久化记忆:Workspace

基于文件的持久化记忆,存储跨会话的用户偏好、项目上下文和反馈记录:

workspace/
+-- users/
    +-- {user_id}/   # 多用户隔离(CLI 的 user_id 是 default)
        +-- AGENTS.md        # 这个 user 的常驻规则(人可改,agent 也可用 edit_file 改)
        +-- MEMORY.md        # 记忆索引(仅存条目链接,≤200行/25KB)
        +-- memory/          # 记忆内容文件(每条独立 .md)
            +-- feedback_python_style.md
            +-- project_deadline.md
            +-- user_background.md
        +-- conversations/   # 对话归档
            +-- 2026-04-01.md

没有 workspace 根目录的 AGENTS.md。常驻规则只在 users/{user_id}/AGENTS.md;项目规则在 repo 根的 AGENTS.md 链。

基本用法

from agentica import Agent, Workspace

agent = Agent(
    workspace=Workspace(path="./my_workspace", user_id="alice"),
)

记忆写入:write_memory_entry()

推荐使用 write_memory_entry() 写入带类型的记忆条目。每条记忆写入独立文件,并自动更新 MEMORY.md 索引。

workspace = Workspace("./workspace")
workspace.initialize()

# 写入用户偏好
await workspace.write_memory_entry(
    title="Python Style",
    content="User prefers concise, typed Python. Avoid unnecessary comments.",
    memory_type="feedback",           # user | feedback | project | reference
    description="python coding style typed concise",  # 相关性匹配关键词
)

# 写入项目上下文
await workspace.write_memory_entry(
    title="Release Deadline",
    content="v2.0 release is due end of April 2026.",
    memory_type="project",
    description="v2 release deadline april 2026",
)

每条记忆文件带 YAML frontmatter:

---
name: Python Style
description: python coding style typed concise
type: feedback
---

User prefers concise, typed Python. Avoid unnecessary comments.

四类型分类法

类型 存储内容 典型触发
user 用户角色、偏好、技术背景 "我是数据科学家"、"我用 Python 10 年了"
feedback 对 AI 行为的纠正和确认 "别 mock 数据库"、"这个方案很好"
project 非代码可推导的项目上下文 "合并冻结从周四开始"、"这是合规要求"
reference 外部系统指针 "pipeline bugs 在 Linear INGEST 项目"

feedback 类型同时记录失败("不要这样做")和成功("对,就这样")——只记录纠错会导致 AI 行为随时间漂移。


常驻规则:直接改 AGENTS.md,没有专门工具

「记住:以后都要 X」和「记住这件事 X」不是一回事,落盘位置不同:

常驻规则 一个事实
落盘位置 用户级:~/.agentica/workspace/users/{user_id}/AGENTS.md(CLI 的 user_id 是 default);项目级:<repo 根>/AGENTS.md memory/*.md + MEMORY.md 索引
何时进 system prompt 下个会话起全量注入(见下);本会话靠对话历史 只在后续提问与它相关时被召回
谁来写 人手写,或 agent 用 edit_file / write_file save_memory
适合 "always ..." / "never ..." / "从现在开始 ..." 用户是谁、某个决定为什么这么定、环境怎么搭的

规则这一侧没有专门的工具,也不需要固定格式:AGENTS.md 就是一个 markdown 文件,人和 agent 用同一种方式改它。写法说明在 bundled agentica skill 里(self_manage 只管 config.yaml / .env / 升级,不管常驻规则)。

外部 workflow(如 learn-from-experience)要把确认偏好写成常驻规则时,直接往
~/.agentica/workspace/users/{user_id}/AGENTS.md
追加普通行即可。经验卡片若进 prompt,是直接从 EXPERIENCE 相关性召回注入(## Learned Experiences),只保留用户纠正类correction);tool_error / success_pattern 不进 system prompt。事实记忆同理,走 get_relevant_memories,也不写进 AGENTS.md。


记忆召回:get_relevant_memories()

记忆注入采用相关性召回,而非全量 dump。

# 根据当前 query 返回最相关的 ≤5 条记忆
memory = await workspace.get_relevant_memories(
    query="how should I write python code",
    limit=5,
    already_surfaced=set(),   # 去重:本 session 已展示过的文件名
)

召回机制: 1. 解析 MEMORY.md 索引,获取所有条目的 title + description hook 2. 用 混合关键词 scoring(word-level + character 2-gram)对每条打分,支持中英文 3. 只加载 top-k 个文件内容,拼接后注入 system prompt 4. 自动 strip frontmatter,追加 drift-defense 提示

MEMORY.md 的大小有硬限制(200 行 / 25KB),超出时 FIFO 淘汰最旧条目,防止无限增长。

Agent 自动召回

Agent 使用 workspace 时,每次 run() 会自动以当前 query 为输入执行记忆召回:

from agentica import Agent, Workspace
from agentica.agent.config import WorkspaceMemoryConfig

agent = Agent(
    workspace=Workspace("./workspace"),
    long_term_memory_config=WorkspaceMemoryConfig(
        load_workspace_memory=True,
        max_memory_entries=5,   # 最多注入 5 条相关记忆
    ),
)

_surfaced_memories 跨 turn 追踪已展示的记忆文件,避免同一 session 内重复注入相同条目。


记忆漂移防御

记忆注入时自动追加一条提示,防止过时引用造成幻觉:

Note: memories reflect the state at write time. If a memory references a specific
file path, function, or flag, verify it still exists before recommending it.

会话快照与 prompt cache

System Prompt 里所有从「实时状态」读出来的部分,都在会话第一轮一次性冻结:

内容 冻结入口
工作区上下文(AGENTS.md 等) Workspace.freeze_snapshots()
工作区记忆 Workspace.freeze_snapshots()
经验(experiences) Workspace.freeze_snapshots()
skills 目录(session guidance) Agent.freeze_session_guidance()

原因是 prompt cache 按字节精确的前缀匹配,而 system message 位于后续每一个缓存断点的前缀里:中途改一行,失效的不只是 system 那个断点,而是连同整段对话历史一起重新计价。

经验和 skills 尤其要冻,因为它们是这个 agent 自己在会话中途写的:捕获钩子会在工具出错、用户纠正、批量 judge 时写入新的经验卡片,skill upgrade 钩子会在后台调 refresh_tool_system_prompts() 重排 skills 目录。也就是说,没有任何人提出要求,一次后台写入就让整段对话重新计价。

代价用一行指针补回来:注入的经验块会写明这是会话开始时选中的,并给出 EXPERIENCE.md 索引路径(Workspace.experience_index_path),需要最新的经验时 agent 自己 read_file 一次即可。skills 则不需要指针——新装的 skill 会立刻生效,因为 /skills 会重建 agent,而新 agent 会重新冻结。


Git 上下文(为什么不注入)

Workspace 不会把 Git 状态注入 System Prompt。分支、未提交变更、最近 commit 由 agent 需要时自己跑一次 git 获取(execute)。

原因是 prompt cache 按字节精确的前缀匹配,而 system message 位于后续每一个缓存断点的前缀里:git status --short 每轮变一行,失效的不只是 tools+system 那个断点,而是连同整段对话历史一起按 1.25x 重写。改成会话开始时冻结一次也不划算——省下了钱,换来的是一份会越来越旧的文件列表,而模型本来就从自己的工具结果里看见了每一次编辑。


对话归档

使用 ConversationArchiveHooks 自动将对话归档到每日日志文件:

from agentica import Agent, Workspace
from agentica.agent.config import WorkspaceMemoryConfig

agent = Agent(
    workspace=Workspace("./workspace"),
    long_term_memory_config=WorkspaceMemoryConfig(auto_archive=True),
)

归档写入 users/{user_id}/conversations/YYYY-MM-DD.md,使用 per-file asyncio.Lock 防止并发写冲突。


Session Log(JSONL)

基于追加写 JSONL 的会话日志,支持会话恢复和 fork:

from agentica import Agent

agent = Agent(session_id="my-session-001")
# 消息自动写入 .sessions/my-session-001.jsonl
# 下次以相同 session_id 创建 Agent 时自动恢复会话

支持 compact_boundary(压缩边界):恢复时从最后一个边界之后开始加载,跳过历史数据。


WorkspaceConfig

可自定义文件布局:

from agentica.workspace import Workspace, WorkspaceConfig

config = WorkspaceConfig(
    agent_md="AGENTS.md",        # workspace 级与 user 级共用同一个文件名
    memory_md="MEMORY.md",      # 记忆索引文件
    memory_dir="memory",         # 记忆内容文件目录
    users_dir="users",
    conversations_dir="conversations",
)

workspace = Workspace(path="./workspace", config=config)

下一步