Files
microsoft--agent-framework/python/samples/02-agents/harness/harness_data_processing.py
westey a2018b40f9 Python: [BREAKING] Require approval for file-access tools with read-only auto-approval (#6599)
* Require approvals for file-access and expose auto approval funcs for it

* Scope file-access auto-approval rules to local tools; fix base-Agent sample

Address PR #6599 review feedback:
- read_only/all_tools auto-approval rules now reject any call carrying a
  server_label so they stay scoped to FileAccessProvider's local tools and
  never auto-approve a same-named hosted tool.
- Expand the FileAccessProvider docstring to explain the runtime effect of
  approval_mode="always_require" and point to ToolApprovalMiddleware /
  create_harness_agent.
- Fix the base-Agent file_access_data_processing sample, which would otherwise
  stop executing file tools under the new always_require defaults, by adding
  ToolApprovalMiddleware with all_tools_auto_approval_rule.
- Add tests covering hosted (server_label) calls and update docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clean up comments

* Update sample after merge

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-23 09:51:12 +00:00

141 lines
5.8 KiB
Python

# /// script
# requires-python = ">=3.10"
# dependencies = [
# "agent-framework",
# "textual>=6.2.1",
# "rich>=13.7.1",
# "azure-identity",
# "python-dotenv",
# ]
# ///
# Run with any PEP 723 compatible runner, e.g.:
# uv run samples/02-agents/harness/harness_data_processing.py
# Copyright (c) Microsoft. All rights reserved.
"""Harness Data Processing Assistant with Console UI and tool approvals.
Demonstrates ``create_harness_agent`` configured with a ``FileAccessProvider``
to give an agent access to a folder of CSV data files. The agent can read,
analyze, and extract information from the data, then write results back as new
files via the ``file_access_*`` tools.
This sample also demonstrates **tool approval**. The ``FileAccessProvider``
registers all of its tools with ``approval_mode="always_require"``, so every
file operation would normally prompt the host for approval. To keep read-only
exploration frictionless while still guarding mutations, the agent is given the
:meth:`FileAccessProvider.read_only_tools_auto_approval_rule` auto-approval
rule. With this rule:
- Read-only tools (read, list files, list subdirectories, search) are
auto-approved and run without prompting.
- Write tools (save and delete) still require explicit approval, so you are
asked before the agent modifies the file store.
The sample includes a pre-populated ``working/`` folder with sales transaction
data. The ``FileAccessProvider`` is pointed at that folder (resolved relative to
this script) so it works regardless of the current working directory. Ask the
agent to analyze the data, produce summaries, or create new output files. For
example::
Please process the sales.csv file by first filtering it to only North region
sales, and then calculating the sum of sales by person. I'd like to write the
results of the processing to north_region_totals.csv
When the agent reads ``sales.csv`` it proceeds automatically, but when it tries
to save ``north_region_totals.csv`` you are prompted to approve the write.
Unused harness features (todos, plan/execute mode, web search) are disabled to
keep this a simple, conversational data-interaction sample.
Environment variables:
FOUNDRY_PROJECT_ENDPOINT — Azure AI Foundry project endpoint URL
FOUNDRY_MODEL — Model deployment name
Authentication:
Run ``az login`` before running this sample.
"""
import asyncio
from pathlib import Path
from agent_framework import FileAccessProvider, FileSystemAgentFileStore, create_harness_agent
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
from console import build_default_observers, run_agent_async
from dotenv import load_dotenv
DATA_ANALYST_INSTRUCTIONS = """\
You are a data analyst assistant. You have access to a folder of data files via the file_access_* tools.
## Getting started
- Start by listing available files with file_access_list_files to see what data is available.
- Read the files to understand their structure and contents.
## Working with data
- When asked to analyze data, read the relevant files first, then perform the analysis.
- Show your analysis clearly with tables, summaries, and key insights.
- When calculations are needed, work through them step by step and show your reasoning.
## Writing output
- When asked to produce output files (e.g., reports, summaries, filtered data), use file_access_save_file to write them.
- Use appropriate file formats: CSV for tabular data, Markdown for reports.
- Confirm what you wrote and where.
## Important
- Never modify or delete the original input data files unless explicitly asked to do so.
- If asked about data you haven't read yet, read it first before answering.
- Always explain your reasoning and thought process as you work through tasks.
- Always explain what you learned and what you are going to do next between tool calls, so the user can
follow along with your thought process.
"""
MAX_CONTEXT_WINDOW_TOKENS = 1_050_000
MAX_OUTPUT_TOKENS = 128_000
async def main() -> None:
load_dotenv()
# Resolve the working/ folder bundled alongside this script. The agent reads
# the seed data from here and writes any output files back into it.
working_dir = Path(__file__).parent / "working"
# Create the chat client.
# For authentication, run `az login` in terminal or replace AzureCliCredential
# with your preferred authentication option.
client = FoundryChatClient(credential=AzureCliCredential())
# Create a harness agent with data-analyst instructions. Unused features are
# disabled. The read_only_tools_auto_approval_rule auto-approves the
# FileAccessProvider's read-only tools, so only write operations prompt.
agent = create_harness_agent(
client=client,
max_context_window_tokens=MAX_CONTEXT_WINDOW_TOKENS,
max_output_tokens=MAX_OUTPUT_TOKENS,
name="DataAnalyst",
description="A data analyst assistant that reads, analyzes, and processes data files.",
agent_instructions=DATA_ANALYST_INSTRUCTIONS,
file_access_store=FileSystemAgentFileStore(working_dir),
auto_approval_rules=[FileAccessProvider.read_only_tools_auto_approval_rule],
disable_todo=True,
disable_mode=True,
disable_web_search=True,
)
# Run the harness console. This sample has no plan/execute mode, so it uses
# the default observers (no planning observer) and no initial mode.
await run_agent_async(
agent,
session=agent.create_session(),
observers=build_default_observers(),
title="📊 Data Analyst",
placeholder="Ask me to analyze the data files, produce summaries, or create output files...",
max_context_window_tokens=MAX_CONTEXT_WINDOW_TOKENS,
max_output_tokens=MAX_OUTPUT_TOKENS,
)
if __name__ == "__main__":
asyncio.run(main())