Microsoft Agent Framework — Harness 模块:文件记忆、访问和存储 目录1. 模块职责2. 从一个例子理解 Files它解决什么问题、为什么值得用3. FileMemory vs FileAccess 对比4. 类型清单5. FileMemory5.1 FileMemoryProvider5.2 FileMemoryProviderOptions / FileMemoryState / FileListEntry6. FileAccess6.1 FileAccessProvider6.2 FileAccessProviderOptions含裁剪开关6.3 两条现成的自动审批规则7. FileStore存储后端7.1 AgentFileStore抽象7.2 FileSystemAgentFileStore7.3 InMemoryAgentFileStore7.4 数据模型与助手8. 行为要点9. 扩展与最佳实践10. 与其它模块的关系11. 小结基于 MAF .NET1.13.0。 程序集Microsoft.Agents.AI核心包 · 源码目录dotnet/src/Microsoft.Agents.AI/Harness/{FileMemory,FileAccess,FileStore}/1. 模块职责给智能体读写、编辑文件的能力分成三块FileMemory文件记忆智能体的私人草稿纸——会话隔离的工作目录用来把计划、中间结论、下载的大块数据落盘避免被上下文压缩丢掉。FileAccess文件访问公共工作区——跨会话、跨智能体共享的持久目录用来读输入数据、写交付产物。FileStore存储后端上面两者共同依赖的存储抽象AgentFileStore可插拔本地磁盘 / 内存 / 远端对象存储。两个 Provider 都不直接碰文件系统只跟这个抽象打交道。FileMemory 与 FileAccess 都是AIContextProvider区别只在作用域 默认策略两者各自向模型暴露 7 个工具含新的按子串 / 按行编辑让智能体能像用 IDE 一样改文件。2. 从一个例子理解 Files把这三块想象成智能体的三样东西一叠只有自己看的便签FileMemory、一个跟同事共用的文件柜FileAccess、以及决定这些纸到底放哪、怎么存的柜子本身FileStore。举个例子。你让一个数据分析助理干活working 目录里有一份 sales.csv帮我分析季度趋势写一份报告。它大致这么走用FileAccess的file_access_read读那份共享的sales.csv别人放进公共工作区的输入。分析过程中把中间统计、清洗后的数据用FileMemory的file_memory_write存进自己的草稿纸——哪怕后面对话被压缩这些结论还在需要时file_memory_read调回。报告初稿想改个措辞不必整篇重写用file_memory_replace子串替换或file_access_replace_lines按行改做小改动。最终报告用FileAccess的file_access_write写回公共工作区交付——但写操作默认要审批会先弹给你确认。它解决什么问题、为什么值得用防遗忘长任务里模型的记性受上下文窗口限制中间结论很容易被压缩砍掉。FileMemory 把它们外化成会话内持久的文件并每轮把记忆索引念给模型、需要时再拉正文——省 token 又不丢关键产物。能协作FileAccess 提供一个跨会话、跨智能体共享的目录天然适合读别人给的输入、写交付物让智能体的产出能被外部消费。可换后端 默认安全落盘细节全甩给AgentFileStore抽象换 Blob / S3 / 内存只需实现一个子类而默认实现拒绝路径穿越让给智能体开文件权限在默认情况下就是沙箱化的。能精改replace/replace_lines让智能体像用编辑器一样做小改动而不是每次整篇重写——省 token、也更不容易改坏无关内容。3. FileMemory vs FileAccess 对比两个 Provider 长得像都是AIContextProvider、都靠AgentFileStore落盘、工具几乎同名但定位与默认策略截然不同。先用一张表建立全局再逐块细看。维度FileMemoryFileAccess定位智能体私人草稿纸公共工作区作用域会话隔离每会话一个工作目录跨会话 / 跨智能体共享默认根目录{cwd}/agent-file-memory/{时间戳}_{guid}无框架默认opt-in调用方提供 store命名空间扁平不能建子目录文件名带/被拒支持子目录工具前缀file_memory_*file_access_*工具数7write / read / delete / ls / grep / replace / replace_lines7同名另有 3 个开关裁剪会话状态有FileMemoryState.WorkingFolder无StateKeys []write覆盖默认覆盖默认不覆盖需overwritetruegrep范围非递归只搜当前工作目录递归支持**跨子目录工具是否需审批否普通工具是默认全部ApprovalRequiredAIFunction额外机制伴生描述文件 memories.md索引注入两条现成自动审批规则 3 个裁剪开关注入消息每轮注入记忆索引不注入消息典型用途存研究报告 / 中间结论 / 下载内容读输入数据集 / 写交付产物一句话记忆FileMemory 偏会话内防遗忘隔离、默认覆盖、有索引、免审批FileAccess 偏共享读写真实产物共享、默认不覆盖、强制审批。装配方式也不同HarnessAgent 默认装配 FileMemoryFileAccess 是 opt-in——只有给HarnessAgentOptions.FileAccessStore设了 store 才会启用。4. 类型清单子模块类型可见性职责FileMemoryFileMemoryProviderpublic会话级文件记忆 ProviderFileMemoryFileMemoryProviderOptionspublic自定义指令FileMemoryFileMemoryStatepublic会话状态工作目录路径FileMemoryFileListEntrypublicls返回项名字 类型 描述FileAccessFileAccessProviderpublic共享目录文件访问 ProviderFileAccessFileAccessProviderOptionspublic自定义指令 工具 / 审批裁剪开关FileStoreAgentFileStorepublic抽象存储后端契约7 个方法FileStoreFileSystemAgentFileStorepublic本地磁盘实现沙箱化FileStoreInMemoryAgentFileStorepublic内存实现测试用FileStoreFileStoreEntrypublic目录条目名字 类型file/directoryFileStoreFileSearchResultpublic搜索结果文件名 片段 命中行FileStoreFileSearchMatchpublic单条命中行号 行内容FileStoreFileLineEditpublicreplace_lines入参行号 新行文本FileStoreFileEditorinternalreplace/replace_lines的读-改-写助手FileStoreStorePathsinternal路径规范化 glob 工具5. FileMemory5.1 FileMemoryProvider会话级文件记忆 ProviderAIContextProviderIDisposable。构造时必须传一个AgentFileStore可选传stateInitializer给每个新会话定制工作目录比如按用户 / 会话分子目录和FileMemoryProviderOptions。运行期ProvideAIContextAsync每轮做三件事确保会话工作目录存在注入记忆使用守则 7 个工具若记忆索引memories.md非空就把它作为一条 user 消息注入——告诉模型这些是你之前存过的文件可以用file_memory_read读。工具7 个工具名都以public const string暴露如WriteToolName工具名说明file_memory_write存文件默认覆盖同名文件可带 description落成伴生描述文件file_memory_read按名读file_memory_delete按名删连带删伴生描述文件、重建索引file_memory_ls列文件带各自描述可用 glob 过滤隐藏内部文件file_memory_grep用正则搜文件内容不区分大小写非递归file_memory_replace子串查找替换old_string未找到、或出现多次而未开replace_all则失败file_memory_replace_lines按 1 基行号整行替换new_line为空串即删除该行行号越界或重复则失败三个关键机制伴生描述文件存文件时可附一段描述落成文件名去扩展名_description.md列文件 / 索引时会带出这段描述帮模型判断这文件里是什么、值不值得读。写文件时不带描述会删掉旧的描述文件。**记忆索引memories.md**每次写 / 删都会重建最多 50 条汇总各文件名 描述。它被每轮注入给模型当记忆目录也是受系统保留的内部文件——连同各_description.md一起对ls/grep隐藏且file_memory_write不允许写这些保留名。扁平命名空间记忆是会话内一块平铺空间文件名不能带路径分隔符想写进子目录会被拒ArgumentException。5.2 FileMemoryProviderOptions / FileMemoryState / FileListEntryFileMemoryProviderOptions—— 只有一个Instructions整段替换默认记忆守则。FileMemoryState—— 会话状态只有一个WorkingFolder相对存储根的工作目录路径按会话隔离。FileListEntry——file_memory_ls的返回项NameType记忆项恒为file 可选Description。6. FileAccess6.1 FileAccessProvider共享目录文件访问 ProviderAIContextProviderIDisposable。与 FileMemory 不同它没有会话状态StateKeys []因为它操作的是跨会话共享的同一个目录AgentFileStore在构造前就该限定到那个目录ProvideAIContextAsync也只注入指令 工具不注入任何消息。工具默认 7 个工具名同样以public const string暴露工具名说明file_access_write存文件默认不覆盖需显式overwritetruefile_access_read按名读file_access_delete按名删file_access_ls列某目录的直接子文件 子目录子目录在前可 glob 过滤file_access_grep递归用正则搜内容支持**glob结果路径重挂到 store 根file_access_replace子串查找替换同 FileMemory 的 replace 语义file_access_replace_lines按行替换同 FileMemory 的 replace_lines 语义默认所有工具都要审批各自包成ApprovalRequiredAIFunction。6.2 FileAccessProviderOptions含裁剪开关Instructions—— 整段替换默认文件访问守则默认守则内置未经用户明确要求别删 / 别覆盖的软约束。DisableWriteTools—— 置true只暴露只读工具read/ls/grep把改动存储的 4 个工具write / delete / replace / replace_lines整个藏起来。DisableReadOnlyToolApproval—— 关掉 read / ls / grep 的审批。DisableWriteToolApproval—— 关掉 write / delete / replace / replace_lines 的审批DisableWriteToolstrue时此项无意义。6.3 两条现成的自动审批规则因为默认全要审批、频繁手工点很烦FileAccessProvider提供两条public static规则配合ToolApprovalAgentOptions.AutoApprovalRules用ReadOnlyToolsAutoApprovalRule—— 只自动放过只读工具read / ls / grep写 / 删 / 改仍要人工确认。AllToolsAutoApprovalRule—— 所有文件工具都放过含 write / delete / replace / replace_lines仅在完全可信环境用。它们的类型是FuncToolAutoApprovalRuleContext, ValueTaskbool只按工具名匹配——命中本 Provider 的工具名返回true其它返回false让后续规则继续评估。源码里带一条安全提示正因为只看名字若有别的工具恰好取了同名比如可配置名的 shell 工具也会被连带自动放过、绕过人工闸门所以别让工具重名。7. FileStore存储后端7.1 AgentFileStore抽象所有文件操作的契约基类。路径一律用正斜杠、相对某个实现自定的根、且不得用..逃逸根目录由各实现强制。7 个抽象方法方法作用WriteAsync写创建或覆盖ReadAsync读不存在返回nullDeleteAsync删返回是否真的删了ListChildrenAsync列目录直接子项返回FileStoreEntry列表子目录在前FileExistsAsync判文件存在SearchAsync正则搜内容不区分大小写支持 glob 过滤 是否递归CreateDirectoryAsync建目录注意编辑不在抽象里——replace/replace_lines是 Provider 层用内部助手FileEditor做读出全文 → 改 → 写回Store 只需实现读 / 写。原先分开的列文件和列目录已合并成一个ListChildrenAsync靠FileStoreEntry.Type区分 file / directory。7.2 FileSystemAgentFileStore本地磁盘实现构造时传根目录不存在会自动创建。拒绝路径穿越..段或绝对路径一律抛ArgumentException并不跟随符号链接 / reparse point枚举目录时跳过、解析读写路径时直接拒绝——两道一起挡住爬出根目录。这意味着它天然是个沙箱化文件系统智能体只能在你给定的根目录里操作。搜索时正则带 5 秒超时防 ReDoS 灾难性回溯命中处截 ±50 字符片段读写用 UTF-8。7.3 InMemoryAgentFileStore内存实现用大小写不敏感的ConcurrentDictionarystring,string存目录概念用路径前缀模拟不维护真实目录结构CreateDirectoryAsync是空操作。适合测试和不需要持久化的轻量场景。7.4 数据模型与助手FileStoreEntry—— 目录条目NameType常量Filefile /Directorydirectory由ListChildrenAsync返回。FileSearchResult——FileNameSnippet首个命中附近的片段MatchingLinesListFileSearchMatch。FileSearchMatch——LineNumber1 起Line该行内容。FileLineEdit——replace_lines的入参LineNumber1 起NewLine字面替换文本空串即删除该行。FileEditorinternal—— 两个 Provider 共享的编辑助手ApplyReplace子串替换Ordinal、ApplyReplaceLines按行替换。StorePathsinternal负责路径规范化与 glob 匹配。8. 行为要点两个 Provider 的默认覆盖策略相反FileMemory 的write默认覆盖草稿纸随手更新FileAccess 的write默认不覆盖真实产物防误删。审批边界只在 FileAccessFileAccess 的工具默认全要审批FileMemory 的不要——因为草稿纸是智能体私有、低风险公共工作区才需要人盯着。grep 一个非递归、一个递归FileMemory 的 grep 只搜当前会话工作目录扁平FileAccess 的 grep 递归全树、支持**。记忆索引是推 / 拉设计索引名字 描述每轮自动推给模型正文要模型自己调read拉——省 token又能扛住上下文压缩。保留名不可写memories.md和各_description.md是 FileMemory 的内部文件对模型隐藏、且禁止write占用这些名字。**编辑工具会挑剔**replace在old_string未找到、或出现多次而没开replace_all时会失败replace_lines在行号越界或重复时会失败——这是刻意的改不准就别改避免误伤。自动审批规则按名匹配方便但要保证没有别的工具跟file_access_*重名否则会被连带放过。9. 扩展与最佳实践可定制 / 扩展点换存储后端实现一个AgentFileStore子类7 个方法就能把文件落到 Azure Blob、S3、数据库等FileMemoryProvider/FileAccessProvider完全不用改。通过HarnessAgentOptions.FileMemoryStore/FileAccessStore注入。定制工作目录给FileMemoryProvider传stateInitializer按用户 / 会话把工作目录分到不同子目录实现更细的隔离。裁剪 FileAccess 的能力面只想让智能体看不改就DisableWriteTools信任环境想免审批就配DisableReadOnlyToolApproval/DisableWriteToolApproval或挂自动审批规则。改守则两个 Provider 的Instructions都可整段替换改语气、讲中文、收紧 / 放宽纪律。最佳实践把 FileMemory 当工作便签别当持久业务库它按会话隔离——每个会话默认用独立工作目录{时间戳}_{guid}新会话看不到旧会话的记忆框架也不做自动清理或跨会话检索。需要长期留存 / 审计 / 跨会话复用的产物写到 FileAccess 的共享目录或另建业务存储。**生产环境别默认用AllToolsAutoApprovalRule**优先ReadOnlyToolsAutoApprovalRule——放过只读、把写 / 删 / 改留给人工确认AllTools只在完全可信、隔离的环境用。大文件配描述存大块内容时带一段 description索引里就能看到摘要模型不必把每个文件都读一遍才知道里面是什么——省 token。优先用replace/replace_lines做小改比整篇write重写更省、更不容易改坏无关部分但记得它改不准会失败必要时先read看清再改。给 FileAccess 的 store 限定到最小根目录FileSystemAgentFileStore的根就是智能体能碰的全部范围根开得越小越安全它已拒路径穿越、不跟随符号链接。10. 与其它模块的关系HarnessAgent门面默认装配 FileMemory用DisableFileMemory关闭或用FileMemoryStore换后端默认根为{cwd}/agent-file-memory/{时间戳}_{guid}FileAccess 是 opt-in——只有设了HarnessAgentOptions.FileAccessStore才装配没有DisableFileAccess开关不设 store 即不启用。ToolApprovalFileAccess 的工具默认要审批正是ToolApprovalAgent 自动审批规则ReadOnlyToolsAutoApprovalRule/AllToolsAutoApprovalRule类型FuncToolAutoApprovalRuleContext, ValueTaskbool的典型用武之地。CompactionFileMemory 的设计动机之一就是被压缩砍掉的内容还能从文件读回两者在长会话里互补——索引每轮注入更是让模型记得自己存过什么。11. 小结这三块共同构成 Harness 的文件能力层。核心区分是作用域 默认策略FileMemory 偏会话内防遗忘隔离、默认覆盖、有索引、免审批FileAccess 偏共享读写真实产物共享、默认不覆盖、强制审批两者都新增了replace/replace_lines让智能体能像用 IDE 一样精改文件。所有落盘细节都甩给AgentFileStore抽象7 个方法换 Blob / S3 / 内存只需实现一个子类、不动 Provider。而FileSystemAgentFileStore拒绝路径穿越、跳过符号链接这两点让给智能体开文件权限在默认情况下就是沙箱化的。Microsoft Agent Framework官方仓库https://github.com/microsoft/agent-frameworkInkwell本项目开源仓库https://github.com/shuaihuadu/inkwellHarness 系列文章Microsoft Agent Framework — Harness 装进来的那些零件逐个拆开看Microsoft Agent Framework — Harness 中 Agent 的待办清单Todo 模块Microsoft Agent Framework — Harness 模块AgentMode引入地址