{"id":523,"date":"2026-11-11T10:45:31","date_gmt":"2026-11-11T18:45:31","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/go\/?p=523"},"modified":"2026-11-11T10:46:41","modified_gmt":"2026-11-11T18:46:41","slug":"preconfigured-agents-with-microsoft-agent-framework-for-go","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/go\/preconfigured-agents-with-microsoft-agent-framework-for-go\/","title":{"rendered":"Preconfigured agents with Microsoft Agent Framework for Go"},"content":{"rendered":"<p>Microsoft Agent Framework for Go helps you build agents that track tasks, save and revisit notes, load reusable skills, and call your application&#8217;s tools.\nApproval rules let your application handle tool calls that require a user&#8217;s decision.\nTracing provides timing and error data for investigating model and tool calls.<\/p>\n<p>Combining these capabilities means configuring context providers, middleware, history, and session state.\nRepeating that setup for each agent gets tedious when you want the same defaults.<\/p>\n<p>We addressed that repeated setup with an agent harness, available through the <code>agent\/harness<\/code> package.\nAn agent harness is the application code that coordinates tool execution and supplies context between model calls.<\/p>\n<p>The package is available since v0.2.0 of <a href=\"https:\/\/github.com\/microsoft\/agent-framework-go\">Microsoft Agent Framework for Go<\/a>.\nThe framework remains in public preview.<\/p>\n<h2>What the harness configures<\/h2>\n<p><code>harness.AgentConfig<\/code> returns an <code>agent.Config<\/code> with the harness defaults added.\nThe helper combines your tools with the built-in tools and includes the middleware and context providers you supply.\nUse this configuration with your provider constructor to create the agent.<\/p>\n<p>The agent&#8217;s <code>CreateSession<\/code> method creates an <code>agent.Session<\/code> object that holds conversation state.\nPass the same session to successive <code>RunText<\/code> calls using <code>agent.WithSession<\/code> to continue the conversation.<\/p>\n<p>The default configuration includes:<\/p>\n<ul>\n<li><strong>Default instructions:<\/strong> The harness supplies Agent Framework&#8217;s <code>harness.DefaultInstructions<\/code> text.\nIt tells the model to break complex tasks into steps, verify results with tools, and report progress between tool calls.<\/li>\n<li><strong>To-do tools:<\/strong> These tools read and update a structured task list in the session, so later requests can see which work remains unfinished.<\/li>\n<li><strong>Plan and execute modes:<\/strong> The agent starts in plan mode, with mode-specific instructions for discussing a plan or carrying it out.\nNote that these modes don&#8217;t deny tool use or do any sandboxing and only instruct the agent how to behave.<\/li>\n<li><strong>FileMemory:<\/strong> The agent can save and update plans or findings on disk, then retrieve them by filename in later requests.<\/li>\n<li><strong>Conversation history:<\/strong> By default, the history provider holds messages in memory and saves them after each model call, including intermediate tool calls and results.\nThe agent can use these tool results when answering a follow-up request.<\/li>\n<li><strong>Skills:<\/strong> File-backed skills keep task instructions and YAML metadata in <code>SKILL.md<\/code>, alongside optional supporting files such as reference documents or templates.\nThe agent can load the relevant instructions and files on demand instead of including every procedure in its initial prompt.\nDefault discovery looks in the working directory and excludes <code>agent-file-memory<\/code>.\nA skill can also contain scripts, such as Python files, which run only if your application supplies a script runner.<\/li>\n<li><strong>Tool approvals:<\/strong> The middleware remembers standing approvals for the session and can apply your automatic approval rules, avoiding repeated prompts for matching calls.\nFor calls that still require approval, your application receives a request that you can present to the user and answer through the same session.<\/li>\n<li><strong>Hosted web search:<\/strong> The model can request web results from the service, so your application does not need its own search client.\nSupport depends on the selected API and deployment.\nUse <code>DisableWebSearch<\/code> to omit the tool when it is unavailable or unnecessary.<\/li>\n<li><strong>Message injection:<\/strong> Your application can queue additional input for the session during a run, such as a revised requirement.\nThe injector supplies the queued messages between model calls.\nQueueing allows your application to avoid throwing away the work being done by the current model call.\nTo cancel instead, use a Go context created with <a href=\"https:\/\/pkg.go.dev\/context#WithCancel\"><code>context.WithCancel<\/code><\/a>.<\/li>\n<li><strong>Tracing:<\/strong> OpenTelemetry records agent runs, supported model calls, and local tool calls separately.\nEach record includes its duration and any errors.\nModel-call records also include provider-reported token usage.<\/li>\n<\/ul>\n<p>The <a href=\"https:\/\/learn.microsoft.com\/en-us\/agent-framework\/concepts\/harness?pivots=programming-language-go\">harness guide<\/a> documents the <code>harness.Config<\/code> settings and their defaults.<\/p>\n<h2>Running an agent with Foundry<\/h2>\n<p>This example runs two requests against a planning assistant for a Go <code>net\/http<\/code> service.\nThe first asks the agent to outline a health-check endpoint, record the work as to-do items, and save the plan to <code>healthcheck.md<\/code>.\nThe second asks the agent to read the saved plan and list the unfinished tasks from the same session.\nIt requires Go 1.26 or later:<\/p>\n<pre><code class=\"language-bash\">go mod init example.com\/harness\r\ngo get github.com\/microsoft\/agent-framework-go@v0.2.0<\/code><\/pre>\n<p>Use a Foundry project with a model deployment that supports the Responses API and function calling.\nSet <code>FOUNDRY_PROJECT_ENDPOINT<\/code> to the <a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/foundry\/how-to\/create-projects\">project endpoint<\/a>, such as <code>https:\/\/&lt;resource-name&gt;.services.ai.azure.com\/api\/projects\/&lt;project-name&gt;<\/code>.\nSet <code>FOUNDRY_MODEL<\/code> to the deployment name.<\/p>\n<p>For local development, sign in with <code>az login<\/code> using an identity that can invoke the deployment.\nThe <a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/foundry\/concepts\/rbac-foundry#assign-foundry-user-role-to-your-user-principal\">Foundry User role<\/a> grants the required project data access.\nThe example uses <code>DefaultAzureCredential<\/code>, which can use Azure CLI credentials to authenticate.\nThe program sends model requests to Foundry and incurs usage charges.<\/p>\n<p>Save this as <code>main.go<\/code>:<\/p>\n<pre><code class=\"language-go\">package main\r\n\r\nimport (\r\n    \"context\"\r\n    \"fmt\"\r\n    \"log\"\r\n    \"os\"\r\n\r\n    \"github.com\/Azure\/azure-sdk-for-go\/sdk\/azidentity\"\r\n    \"github.com\/microsoft\/agent-framework-go\/agent\"\r\n    \"github.com\/microsoft\/agent-framework-go\/agent\/harness\"\r\n    \"github.com\/microsoft\/agent-framework-go\/provider\/foundryprovider\"\r\n)\r\n\r\nfunc main() {\r\n    endpoint := os.Getenv(\"FOUNDRY_PROJECT_ENDPOINT\")\r\n    deployment := os.Getenv(\"FOUNDRY_MODEL\")\r\n    if endpoint == \"\" || deployment == \"\" {\r\n        log.Fatal(\"FOUNDRY_PROJECT_ENDPOINT and FOUNDRY_MODEL are required\")\r\n    }\r\n\r\n    credential, err := azidentity.NewDefaultAzureCredential(nil)\r\n    if err != nil {\r\n        log.Fatalf(\"create credential: %v\", err)\r\n    }\r\n\r\n    cfg, err := harness.AgentConfig(\r\n        \/\/ This example doesn't need hosted web search\r\n        harness.Config{DisableWebSearch: true},\r\n        agent.Config{Name: \"ProjectAssistant\"},\r\n    )\r\n    if err != nil {\r\n        log.Fatalf(\"configure harness: %v\", err)\r\n    }\r\n\r\n    a := foundryprovider.NewAgent(\r\n        endpoint,\r\n        credential,\r\n        foundryprovider.ModelDeployment(deployment),\r\n        foundryprovider.AgentConfig{\r\n            Config:       cfg,\r\n            Instructions: \"Help with software engineering tasks. Use memory and to-do items when asked.\",\r\n            \/\/ Retain conversation history in agent.Session rather than at the service.\r\n            DisableStoreOutput: true,\r\n        },\r\n    )\r\n\r\n    ctx := context.Background()\r\n    session, err := a.CreateSession(ctx)\r\n    if err != nil {\r\n        log.Fatalf(\"create session: %v\", err)\r\n    }\r\n\r\n    for _, prompt := range []string{\r\n        \"Plan a health-check endpoint for a Go net\/http service. Record the tasks as to-do items and save the plan in healthcheck.md.\",\r\n        \"Read healthcheck.md and list the remaining to-do items. Explain what you would implement first, without editing the service.\",\r\n    } {\r\n        fmt.Printf(\"User: %s\\n\", prompt)\r\n        response, err := a.RunText(ctx, prompt, agent.WithSession(session)).Collect()\r\n        if err != nil {\r\n            log.Fatalf(\"run agent: %v\", err)\r\n        }\r\n        fmt.Printf(\"Assistant: %s\\n\\n\", response)\r\n    }\r\n}<\/code><\/pre>\n<p>Run the program:<\/p>\n<pre><code class=\"language-bash\">go mod tidy\r\ngo run .<\/code><\/pre>\n<p>The program prints each prompt followed by the agent&#8217;s response.\nThe agent uses the task list and saved plan from the first request to answer the second.\nTool choices and response wording vary by model.<\/p>\n<p>The example sets <code>DisableStoreOutput<\/code> to <code>true<\/code> in its <code>foundryprovider.AgentConfig<\/code> to disable Foundry response storage.\nHere, the harness&#8217;s history provider keeps the conversation in the local <code>agent.Session<\/code>, so the program does not rely on Foundry to replay stored responses.\nService-side storage is useful when you want to retrieve responses later or use Foundry-managed conversation history.<\/p>\n<h2>Where the state lives<\/h2>\n<p>The <code>session<\/code> variable points to an <code>agent.Session<\/code> object in the Go process&#8217;s memory.\nThe session stores the to-do items and memory-folder path, while FileMemory writes the plan to <code>agent-file-memory\/&lt;session-folder&gt;\/healthcheck.md<\/code> beneath the program&#8217;s working directory.<\/p>\n<p>Running the program again creates a new session and a different folder.<\/p>\n<p>To allow your application to continue after a restart, save and restore the session state and use the same memory root.\nThe <a href=\"https:\/\/learn.microsoft.com\/en-us\/agent-framework\/get-started\/memory?pivots=programming-language-go\">memory and persistence guide<\/a> shows session serialization with <code>encoding\/json<\/code>.\nRestoring the session recovers the task list and selects the previous memory folder automatically.<\/p>\n<p>If your agent needs context from more documents than fit in a prompt, see our <a href=\"https:\/\/devblogs.microsoft.com\/go\/embeddings-and-vector-search-in-agent-framework-for-go\/\">embeddings and vector-search post<\/a> for an example that retrieves passages by meaning.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Use harness.AgentConfig to configure task lists, file memory, skills, approvals, conversation history, and tracing for agents written in Go.<\/p>\n","protected":false},"author":211517,"featured_media":513,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[17,16,15,4,21],"class_list":["post-523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-go","tag-agent-framework","tag-agents","tag-ai","tag-go","tag-harness"],"acf":[],"blog_post_summary":"<p>Use harness.AgentConfig to configure task lists, file memory, skills, approvals, conversation history, and tracing for agents written in Go.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/posts\/523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/users\/211517"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/comments?post=523"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/posts\/523\/revisions"}],"predecessor-version":[{"id":526,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/posts\/523\/revisions\/526"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/media\/513"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/media?parent=523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/categories?post=523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/go\/wp-json\/wp\/v2\/tags?post=523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}