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
2 changes: 1 addition & 1 deletion python/packages/core/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ The vector store API is experimental under the shared `VECTOR_STORES` feature ID
- **`FileSystemAgentFileStore`** - Disk-backed store rooted under a configurable directory. Enforces relative-path normalization, root containment, and rejects symlink/reparse-point segments to prevent escape.
- **`FileSearchResult`** / **`FileSearchMatch`** - `SerializationMixin` DTOs returned by `search`, carrying the matching file name, a context snippet, and the matching lines with 1-based line numbers. Implementers should report each matching line verbatim, including its own terminator, so it can be reused as a `file_access_replace_lines` `new_line`; the pattern itself is matched against the line with its whole terminator removed, so `^`/`$` anchor to the line's text on a CRLF file as they already did on an LF one. A custom store populates these DTOs from its own `search`; the verbatim text is a recommendation, but the line number is not — it must address `split_lines`.
- **`FileStoreEntry`** - `SerializationMixin` DTO returned by `list_children`, carrying an entry `name` and `type` (`"file"` or `"directory"`).
- **`FileAccessProvider`** - `ContextProvider` that adds shared file-access tools (`file_access_write`, `file_access_read`, `file_access_read_lines`, `file_access_delete`, `file_access_ls`, `file_access_grep`, `file_access_replace`, `file_access_replace_lines`) plus default usage instructions to each invocation. `file_access_ls` enumerates direct children (both files and subdirectories) as `{name, type}` entries with an optional `glob_pattern`, so the agent can walk the tree level by level; `file_access_grep` searches recursively from an optional base `directory` and returns relative `file_name` paths, scoped via an `fnmatch` `glob_pattern` (where `*` crosses `/`, e.g. `*.md`, `reports/*`). `file_access_replace` substitutes `old_string` with `new_string` (failing if not found, or if multiple matches and `replace_all` is false); `file_access_replace_lines` replaces whole 1-based lines with literal text (each `new_line` includes its own trailing newline; an empty `new_line` deletes the line, including its line break). `file_access_read_lines` returns a 1-based inclusive line range, one line per row as `<line_number>\t<line>`; `end_line` may be omitted to read to the end of the file, and an `end_line` past the last line clamps to it. Everything after the tab is verbatim, including the line's own terminator (which therefore doubles as the row separator), so a row's text can be fed straight back as a `file_access_replace_lines` `new_line` without losing a `\r\n`. Its line numbering comes from the same `_split_lines_keepends` split as `file_access_replace_lines` and as the stores in this package, so with one of those a number reported by grep addresses the same line in all three tools, including the trailing empty line of a newline-terminated file; grep itself runs through `AgentFileStore.search`, which must number by the same split but does not inherit it, so a store overriding `search` owns its numbering and nothing verifies it at run time. All tools are registered with `approval_mode="always_require"` by default, so every file operation needs host approval. Pass `disable_write_tools=True` to advertise only the read-only tools. To run unattended you can disable approval at the source with `disable_readonly_tool_approval=True` (read, read_lines, ls, grep) and/or `disable_write_tool_approval=True` (write, delete, replace, replace_lines), which register the affected tools with `approval_mode="never_require"`; alternatively, keep approval on and pass one of the static auto-approval rules to `ToolApprovalMiddleware` (via `auto_approval_rules`): `FileAccessProvider.read_only_tools_auto_approval_rule` approves only the read-only tools (read, read_lines, ls, grep), while `FileAccessProvider.all_tools_auto_approval_rule` approves every file-access tool including the write tools. Both rules reject any call carrying a `server_label` so they stay scoped to this provider's local tools and never auto-approve a same-named hosted tool. The tool names are also exposed as class constants (`WRITE_TOOL_NAME`, `READ_TOOL_NAME`, `READ_LINES_TOOL_NAME`, `DELETE_TOOL_NAME`, `LS_TOOL_NAME`, `GREP_TOOL_NAME`, `REPLACE_TOOL_NAME`, `REPLACE_LINES_TOOL_NAME`). Unlike `MemoryContextProvider`, the store is intentionally shared across sessions and agents.
- **`FileAccessProvider`** - `ContextProvider` that adds shared file-access tools (`file_access_write`, `file_access_read`, `file_access_read_lines`, `file_access_delete`, `file_access_ls`, `file_access_grep`, `file_access_replace`, `file_access_replace_lines`) plus default usage instructions to each invocation. `file_access_ls` enumerates direct children (both files and subdirectories) as `{name, type}` entries with an optional `glob_pattern`, so the agent can walk the tree level by level; `file_access_grep` searches recursively from an optional base `directory` and returns relative `file_name` paths, scoped via an `fnmatch` `glob_pattern` (where `*` crosses `/`, e.g. `*.md`, `reports/*`). `file_access_replace` substitutes `old_string` with `new_string` (failing if not found, or if multiple matches and `replace_all` is false); `file_access_replace_lines` replaces whole 1-based lines with literal text (each `new_line` includes its own trailing newline; an empty `new_line` deletes the line, including its line break). `file_access_read_lines` returns a 1-based inclusive line range, one line per row as `<line_number>\t<line>`; `end_line` may be omitted to read to the end of the file, and an `end_line` past the last line clamps to it. Everything after the tab is verbatim, including the line's own terminator (which therefore doubles as the row separator), so a row's text can be fed straight back as a `file_access_replace_lines` `new_line` without losing a `\r\n`. Its line numbering comes from the same `_split_lines_keepends` split as `file_access_replace_lines` and as the stores in this package, so with one of those a number reported by grep addresses the same line in all three tools, including the trailing empty line of a newline-terminated file; grep itself runs through `AgentFileStore.search`, which must number by the same split but does not inherit it, so a store overriding `search` owns its numbering and nothing verifies it at run time. All tools are registered with `approval_mode="always_require"` by default, so every file operation needs host approval. Pass `disable_write_tools=True` to advertise only the read-only tools. To run unattended you can disable approval at the source with `disable_readonly_tool_approval=True` (read, read_lines, ls, grep) and/or `disable_write_tool_approval=True` (write, delete, replace, replace_lines), which register the affected tools with `approval_mode="never_require"`; alternatively, keep approval on and pass one of the static auto-approval rules to `ToolApprovalMiddleware` (via `auto_approval_rules`): `FileAccessProvider.read_only_tools_auto_approval_rule` approves only the read-only tools (read, read_lines, ls, grep), while `FileAccessProvider.all_tools_auto_approval_rule` approves every file-access tool including the write tools. Both rules reject any call carrying a `server_label` so they stay scoped to this provider's local tools and never auto-approve a same-named hosted tool. The tool names are also exposed as class constants (`WRITE_TOOL_NAME`, `READ_TOOL_NAME`, `READ_LINES_TOOL_NAME`, `DELETE_TOOL_NAME`, `LS_TOOL_NAME`, `GREP_TOOL_NAME`, `REPLACE_TOOL_NAME`, `REPLACE_LINES_TOOL_NAME`). Unlike `MemoryContextProvider`, the store is intentionally shared across sessions and agents; pass `session_scoped=True` (with an optional explicit `scope`) to confine tool operations to a working folder derived from the session id or scope via the shared `_storage_key_segment` derivation (the provider fails closed when neither is available).

### File Memory Harness (`_harness/_file_memory.py`)

Expand Down
8 changes: 8 additions & 0 deletions python/packages/core/agent_framework/_harness/_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ def _assemble_context_providers(
disable_file_memory: bool,
file_memory_store: AgentFileStore | None,
file_access_store: AgentFileStore | None,
file_access_session_scoped: bool,
file_access_disable_write_tools: bool,
file_access_disable_readonly_tool_approval: bool,
file_access_disable_write_tool_approval: bool,
Expand Down Expand Up @@ -196,6 +197,7 @@ def _assemble_context_providers(
disable_write_tools=file_access_disable_write_tools,
disable_readonly_tool_approval=file_access_disable_readonly_tool_approval,
disable_write_tool_approval=file_access_disable_write_tool_approval,
session_scoped=file_access_session_scoped,
)
)

Expand Down Expand Up @@ -330,6 +332,7 @@ def create_harness_agent(
disable_file_memory: bool = False,
file_memory_store: AgentFileStore | None = None,
file_access_store: AgentFileStore | None = None,
file_access_session_scoped: bool = False,
file_access_disable_write_tools: bool = False,
file_access_disable_readonly_tool_approval: bool = False,
file_access_disable_write_tool_approval: bool = False,
Expand Down Expand Up @@ -454,6 +457,10 @@ def create_harness_agent(
opt-in: when None (default), no FileAccessProvider is added and the agent has no
file access tools. When set, a FileAccessProvider is added, giving the agent shared
read/write file tools backed by the supplied store.
file_access_session_scoped: When True, the FileAccessProvider confines tool operations
to a working folder derived from the active session id, so files are isolated per
session instead of shared across sessions. When False (default), the shared-store
semantics are preserved. Only used when file_access_store is set.
file_access_disable_write_tools: When True, the FileAccessProvider advertises only its
read-only tools (read, read_lines, ls, grep); the write tools (write, delete, replace,
replace_lines) are hidden. When False (default), all tools are advertised. Only
Expand Down Expand Up @@ -608,6 +615,7 @@ def create_harness_agent(
disable_file_memory=disable_file_memory,
file_memory_store=file_memory_store,
file_access_store=file_access_store,
file_access_session_scoped=file_access_session_scoped,
file_access_disable_write_tools=file_access_disable_write_tools,
file_access_disable_readonly_tool_approval=file_access_disable_readonly_tool_approval,
file_access_disable_write_tool_approval=file_access_disable_write_tool_approval,
Expand Down
1 change: 1 addition & 0 deletions python/packages/core/agent_framework/_harness/_agent.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def create_harness_agent(
disable_file_memory: bool = False,
file_memory_store: AgentFileStore | None = None,
file_access_store: AgentFileStore | None = None,
file_access_session_scoped: bool = False,
file_access_disable_write_tools: bool = False,
file_access_disable_readonly_tool_approval: bool = False,
file_access_disable_write_tool_approval: bool = False,
Expand Down
Loading
Loading