Белешка
Приступ овој страници захтева ауторизацију. Можете покушати да се пријавите или промените директоријуме.
Приступ овој страници захтева ауторизацију. Можете покушати да промените директоријуме.
An agent harness, sometimes called an AI harness, is the runtime scaffolding that turns a language model into an agent that can perform work. It drives model and tool calls, manages conversation state and context, applies approval policies, and can keep the agent progressing through a multistep task.
Agent Framework provides an opinionated, batteries-included Harness for research, coding, data analysis, and other long-running work. You provide a chat client and customize only the capabilities your application needs.
Architecture
The Harness composes existing Agent Framework building blocks rather than defining a separate agent runtime:
- Chat client — connects the agent to a model.
- Chat pipeline — adds function invocation, message injection, per-service-call history persistence, and optional compaction.
- Agent and context providers — add session-scoped instructions, tools, memory, todo state, operating modes, and optional capabilities.
- Middleware and decorators — add approval handling, observability, and optional bounded looping.
- Application UX — streams responses, displays progress, and collects input such as tool approvals.
The resulting object remains a normal Agent Framework agent: a HarnessAgent that derives from AIAgent in .NET, an Agent returned by create_harness_agent in Python, or a provider-backed *agent.Agent configured with harness.AgentConfig in Go. Its sessions use the same session and context provider abstractions as other agents.
Harness capability matrix
| Capability | Harness behavior | Canonical guidance |
|---|---|---|
| Function invocation | Enabled with a configurable per-request iteration limit. Go provider constructors own the tool-invocation loop. | Function tools |
| Per-service-call history persistence | Persists history after each model call in a tool-calling run. | Sessions |
| Compaction | Enabled when token limits or a custom strategy are supplied in .NET and Python. Go requires explicit provider composition. | Compaction |
| Todo tracking | Enabled by default. | Planning and todos |
| Agent modes | Plan and execute modes are enabled by default. | Planning and todos |
| File memory and file access | Session file memory is enabled by default; shared file access is opt-in. | Context providers |
| Tool approval | Standing approvals and auto-approval rules are enabled by default. | Tool approval |
| OpenTelemetry | Agent observability is enabled by default. | Observability |
| Web search | Added by default where the selected chat client supports it. | Web search |
| Agent Skills | Enabled by default in .NET and Go; opt-in through a provider or paths in Python. | Agent Skills |
| Background agents | Optional parallel delegation to named child agents in .NET and Python. No packaged Go background-agent provider. | Background agents |
| Shell execution | Composed from the shell package; the Python factory can wire it automatically. | Shell tools |
| Looping | Optional bounded re-invocation driven by evaluators or predicates. | Agent looping |
Background-agent delegation is separate from provider-managed background responses. Background agents run child agents on delegated tasks; background responses poll or resume one provider request by using a continuation token.
Tip
For coding-agent guidance that helps compose a Python harness application,
install
agent-framework-builder-python.
This external coding-agent skill is separate from the runtime Agent Skills
capability listed in the matrix.
Create a harness agent
The Microsoft.Agents.AI.Harness package exposes HarnessAgent in the Microsoft.Agents.AI namespace. Create one from any IChatClient with AsHarnessAgent, or construct HarnessAgent directly:
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
AIAgent agent = chatClient.AsHarnessAgent();
AgentResponse response = await agent.RunAsync("Plan a weekend trip to Seattle.");
Console.WriteLine(response.Text);
Use HarnessAgentOptions to set harness-level operating guidance, agent-specific instructions, and feature options:
AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions
{
Name = "research-agent",
HarnessInstructions = "Use tools deliberately and report verified results.",
ChatOptions = new ChatOptions
{
Instructions = "You are a research assistant focused on academic sources.",
},
MaxContextWindowTokens = 128_000,
MaxOutputTokens = 16_384,
});
HarnessAgent.DefaultInstructions supplies the default harness guidance. HarnessInstructions appears before ChatOptions.Instructions.
Customize the composition
Default capabilities have targeted options, including DisableTodoProvider, DisableAgentModeProvider, DisableFileMemory, DisableAgentSkillsProvider, DisableWebSearch, DisableToolAutoApproval, DisableOpenTelemetry, and DisableCompaction.
Add custom context providers with AIContextProviders. Opt in to file access with FileAccessStore, background delegation with BackgroundAgents, and looping with LoopEvaluators.
Create a harness agent
The create_harness_agent factory returns a fully configured Agent:
from agent_framework import create_harness_agent
from agent_framework.openai import OpenAIChatClient
agent = create_harness_agent(
client=OpenAIChatClient(model="gpt-4o"),
)
session = agent.create_session()
response = await agent.run("Plan a weekend trip to Seattle.", session=session)
print(response.text)
Set harness-level and agent-specific instructions separately:
agent = create_harness_agent(
client=client,
name="research-agent",
harness_instructions="Use tools deliberately and report verified results.",
agent_instructions="You are a research assistant focused on academic sources.",
max_context_window_tokens=128_000,
max_output_tokens=16_384,
)
DEFAULT_HARNESS_INSTRUCTIONS supplies the default harness guidance. harness_instructions appears before agent_instructions.
Customize the composition
Disable defaults with options such as disable_todo, disable_mode, disable_file_memory, disable_web_search, disable_tool_auto_approval, and disable_compaction.
Replace built-in providers with todo_provider or mode_provider, and add providers with context_providers. Skills are opt-in through skills_provider or skills_paths; file access, background agents, shell tooling, and looping are also opt-in.
File access uses the supplied store as one shared workspace by default. To isolate files by the active session ID, enable session-scoped file access:
from agent_framework import FileSystemAgentFileStore, create_harness_agent
file_store = FileSystemAgentFileStore("agent-files")
agent = create_harness_agent(
client=client,
file_access_store=file_store,
file_access_session_scoped=True,
)
For intentional sharing across selected sessions, construct FileAccessProvider(store=file_store, scope="tenant-1") directly and add it through context_providers. The scope is an opaque key that maps to a provider-managed folder, not a path. Scoped access fails closed instead of using the shared store root when neither an active session ID nor an explicit scope is available.
When file access is enabled, use file_access_grep to find 1-based line numbers, file_access_read_lines to inspect an inclusive range, and file_access_replace_lines to edit whole lines. file_access_read_lines prefixes each line with its number and a tab; omit that prefix when passing the line text as expected_line. The expected text prevents a stale or mismatched line number from editing the wrong line.
file_access_grep uses case-insensitive regular expressions, accepts patterns up to 256 characters, and applies a 10-second budget to the entire search. Invalid or overlong patterns and searches that exceed the budget return an error. Narrow the directory or pattern before retrying.
Important
file_access_grep returns matching line text with its line terminator. A custom AgentFileStore.search() implementation must return 1-based line numbers that address the same lines as AgentFileStore.split_lines() over the text returned by read().
Note
create_harness_agent is released. Background agents, file access, and looping remain experimental, and shell tooling comes from the pre-release agent-framework-tools package.
The Go agent/harness package assembles middleware, context providers, and history defaults for a normal provider-backed agent. Call harness.AgentConfig(harness.Config{}, agent.Config{...}), handle its error, and pass the returned configuration to the provider constructor. It doesn't introduce a separate agent type or tool-execution loop.
Create a harness agent
The composite sample configures a Foundry-backed harness agent:
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/microsoft/agent-framework-go/agent"
"github.com/microsoft/agent-framework-go/agent/harness"
"github.com/microsoft/agent-framework-go/examples/internal/demo"
"github.com/microsoft/agent-framework-go/message"
"github.com/microsoft/agent-framework-go/provider/foundryprovider"
)
workingDirectory, err := os.Getwd()
if err != nil {
return fmt.Errorf("get working directory: %w", err)
}
cfg, err := harness.AgentConfig(harness.Config{WorkingDirectory: workingDirectory}, agent.Config{
Name: "HarnessAssistant",
Middlewares: []agent.Middleware{logger},
})
if err != nil {
return err
}
a := foundryprovider.NewAgent(
demo.FoundryProjectEndpoint,
demo.FoundryTokenCredential(),
foundryprovider.ModelDeployment(demo.FoundryModel),
foundryprovider.AgentConfig{
Config: cfg,
DisableStoreOutput: true,
Instructions: "Help with software engineering tasks. Use memory and todos to track the current session's work.",
},
)
Customize the composition
The helper enables the following defaults:
| Component | Go harness default |
|---|---|
| Planning | Session-backed todo tools and plan/execute modes, starting in plan mode |
| File memory | Persistent files under agent-file-memory, with an isolated working folder per session |
| Skills | File-backed discovery from the working directory, excluding the memory subtree |
| Web search | A hosted web-search declaration, unless the caller already supplied one |
| Approval | Standing-approval and auto-approval middleware for tools that require approval |
| History | In-memory history with per-service-call persistence |
| Message injection | A per-agent agent.MessageInjector |
| Tracing | Agent, tool, and supported model-call instrumentation |
Use harness.Config to disable components or override their configuration. Disable hosted web search when the selected service or deployment doesn't support it. File-backed skill scripts require an explicitly configured script runner.
The helper retains caller tools, middleware, context providers, and an explicitly configured history provider. With a Foundry model deployment, use DisableStoreOutput: true when local history owns the conversation.
Compaction, looping, and shell tools aren't added by the Go helper. Configure them explicitly when needed. The packaged background-agent delegation provider described in the other SDKs isn't available in Go.
See Create a Go harness agent for setup and the Go harness configuration guide for defaults and overrides.
Sample terminal UX
The Harness doesn't prescribe an application interface. The repository includes sample terminal applications that stream output, display todos and the current mode, surface tool-approval prompts, and provide commands such as /todos, /mode, and /exit.
Important
These console projects are samples, not shipped framework components. Use them as runnable examples or as a starting point for your own terminal experience.
The .NET sample entry point is HarnessConsole.RunAgentAsync:
using Harness.Shared.Console;
await HarnessConsole.RunAgentAsync(
agent,
userPrompt: "Ask me anything to get started.");
Customize the sample with observers, tool formatters, command handlers, and HarnessConsoleOptions. See the .NET Harness samples.
The Python sample uses the Textual-based console package beside the Harness samples:
from console import run_agent_async
await run_agent_async(agent)
Customize the sample with observers, formatters, commands, and UI components. See the Python Harness samples.
The Go repository includes a composite harness sample with approval handling and a separate interactive chat CLI demo. The chat CLI uses a plain agent; it isn't an equivalent of the C# or Python Harness console.