microsoft / microsoft/agent-framework

Python: [Feature]: Better FileAccessProvider for python harness

Open
#6,770 2 comments 0 reactions 1 assignee View on GitHub

@westey-m is already working on this.

Since Jun 29, 2026.

harness python
Dominant language
Python
Stars
13.6k
Forks
2.3k
Avg merge
2d 45m
Merged PRs (30d)
358

Description

Description

The existing preview feature is lacking some key tools for editing files, and the tooling name / conventions differs from existing frameworks that popular model providers train on.

Description

  • No surgical editing. To change three lines, the model must re-emit the entire file via save_file. That burns tokens, races with concurrent edits, and frequently corrupts large files when the model "rewrites from memory."
  • No read-only/read-write split. There's no first-class way to give a sub-agent read access only, so "safe to delegate investigation" agents have to be hand-rolled.
  • No per-tool approval gating. Destructive operations (delete/overwrite) can't be individually gated behind an approval step.
  • Fixed workdir. The store's root is set at construction, so one agent instance can't safely serve multiple working directories (parallel tasks/sessions) without rebuilding the agent.

Proposal: ship richer file capabilities as ContextProviders (so they inject per-run), split into a read tier and an edit tier:

  • Read tierread, list_files, grep (recursive, grep -rn-style regex with include glob filtering), glob (**-aware path matching).
  • Edit tier (extends read) — write, edit (exact-string replace, with replace_all), apply_patch (unified diff: modify/add/delete/rename), delete_file.

Cross-cutting:

  • Per-run workdir scoping: resolve the workdir from session.state["workdir"] at before_run, falling back to a construction default, so a single agent instance serves many workdirs concurrently.
  • Path safety: workdir-relative paths only, with traversal/symlink protection.
  • Approval modes per tool: gate delete_file (and optionally edit/apply_patch) behind always_require.
Code Sample
from agent_framework import (
    Agent,
    FileReadAccessProvider,
    FileEditAccessProvider # subclasses Read
)


# Editing agent: read + write/patch tools, workdir-scoped, delete gated.
editor = Agent(
    client=client,
    instructions=...,
    context_providers=[
        FileEditToolsProvider(
            default_workdir="/work/project-a",
            require_delete_approval=True,   # delete_file -> always_require
            require_edit_approval=False,    # edit/apply_patch auto-run
        ),
    ],
)

# Read-only sub-agent: gets read/list_files/grep/glob ONLY — safe to delegate.
investigator = Agent(
    client=client,
    instructions=...,
    context_providers=[FileReadToolsProvider(default_workdir="/work/project-a")],
)




session_a.state["workdir"] = "/work/task-a"
session_b.state["workdir"] = "/work/task-b"

await asyncio.gather(
    editor.run("refactor module X", session=session_a),
    editor.run("fix failing test", session=session_b),
)  # each run's file tools are scoped to its own directory


**Surgical edits instead of whole-file rewrites:**


# exact-string edit
edit(file_name="src/app.py", old_string="DEBUG = True", new_string="DEBUG = False", replace_all=True)

# unified-diff patch (add/modify/delete/rename), the format models produce best
apply_patch(file_name="src/app.py", patch="--- a/src/app.py\n+++ b/src/app.py\n@@ ...")


**Search the tree without reading every file:**


grep(pattern=r"def create_agent", include="*.py")   # recursive, like grep -rn
glob(pattern="**/*.sysml")                          # recursive path match


**Approval loop for gated destructive ops** (when `require_delete_approval=True`):


result = await editor.run("remove the obsolete config", session=session_a)
for req in result.user_input_requests:   # delete_file surfaces here for approval
    ...
Language/SDK

Both

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.