Microsoft Agent Framework 入门:实用指南

devops入门11 分钟阅读2026/7/11

上个月,我正在开发一款客服自动化工具,结果碰了壁。我搞定了能回答问题的 LLM 调用,但想把它变成一个真正的 agent——能记住上下文、调用工具、处理多步骤任务的那种——意味着我得写堆积如山的胶水代码。我得手动管理对话历史、解析函数调用,还得把各种工作流拼凑起来。这套做法不仅脆弱、繁琐,而且说实话,我实在不想把时间耗在这上面。

就在这时,我偶然发现了 Microsoft Agent Framework(MAF)。一开始我挺怀疑的——又来一个框架,又得多学一层抽象——但它那种循序渐进的教程结构吸引了我的眼球。它承诺每次只教一个概念来帮你搭建 agent,而这恰好是我最喜欢的学习方式。于是我腾出一个下午,一头扎了进去。以下就是我的发现、踩过的坑,以及真正管用的经验。

环境配置:打好基础

MAF 支持 Python、C# 和 Go。我选了 Python,毕竟这是我日常的主力语言。Go 版本目前还在公测阶段,缺少一些功能,比如声明式 agent 和 RAG,所以如果你是 Go 迷,这点得留意一下。

首先,我创建了一个全新的虚拟环境,并安装了核心包:

python -m venv maf-env
source maf-env/bin/activate
pip install microsoft-agent-framework

你还需要一个 Azure OpenAI 终端节点或 OpenAI API 密钥。我是把它们设置成了环境变量:

export AZURE_OPENAI_ENDPOINT="https://your-endpoint.openai.azure.com/"
export AZURE_OPENAI_API_KEY="your-key-here"

其实我一开始试过不带 Azure 前缀的标准 OpenAI 密钥,结果框架报了个让人摸不着头脑的认证错误。后来才发现,默认配置是默认你用 Azure OpenAI 的。如果你用的是标准 OpenAI,就得显式配置客户端。这是我踩的第一个“坑”——最好一开始就心里有数。

第 1 步:你的第一个 Agent(“Hello World”)

第一步出乎意料地简单:创建一个 agent,调用它,然后流式输出响应。没有工具,没有记忆,就是纯粹的对话。

from agent_framework import Agent

agent = Agent(
    name="my-first-agent",
    instructions="You are a helpful assistant that explains technical concepts simply."
)

response = await agent.invoke("What is a vector database?")
print(response)

这就完事了。区区几行代码,你就能拿到流式响应。我很欣赏教程从这个起步,而不是在第一页就甩给我一个功能齐全的 agent。这让我能在情况变复杂之前,先验证我的环境是跑得通的。

有个让人意外的地方:invoke 方法是异步的。如果你是在普通的 Python 脚本里跑,而不是在 Jupyter notebook 里,你需要用 asyncio.run() 包一下。文档里确实提了这茬,但我第一遍看的时候给漏了,结果盯着毫无输出的卡死脚本纳闷了十分钟。

第 2 步:添加工具(开始有意思了)

只会聊天的聊天机器人算不上真正的 agent。下一步教你如何给 agent 配上它可以调用的函数工具。这也是 MAF 真正开始给我省时间的地方。

from agent_framework import Agent, tool

@tool
def get_order_status(order_id: str) -> str:
    """Look up the status of a customer order by its ID."""
    # 实际开发中,这里会去查数据库或调 API
    return f"Order {order_id} is currently shipping and arrives in 2 days."

agent = Agent(
    name="support-agent",
    instructions="You are a customer support agent. Help customers with their orders.",
    tools=[get_order_status]
)

response = await agent.invoke("Where is my order #12345?")

跑这段代码的时候,agent 自动识别出它需要调用工具,执行了 get_order_status,并把结果融入了它的回复中。完全不用手动解析函数调用的 JSON,也不用写什么路由逻辑。整个工具调用循环都由框架搞定了。

我在这里犯了个错,白白浪费了一小时:我忘了给工具函数加 docstring(文档字符串)。没有 docstring,agent 根本不知道什么时候该调用这个函数,于是它只能瞎猜或者干脆无视。这个 docstring 是 MAF 用来给 LLM 生成工具描述的。你得把它当成 API 文档来写——必须清晰且具体。

第 3 步:多轮对话

我的 agent 会用工具了,接下来我需要它能处理有来有回的对话。第 3 步引入了 session(会话)来维护对话状态。

from agent_framework import Agent, Session

agent = Agent(
    name="support-agent",
    instructions="You are a customer support agent.",
    tools=[get_order_status]
)

session = Session(agent)

# 第一条消息
await session.invoke("Check on order #12345")

# 追问——agent 能记住上下文
response = await session.invoke("When will it arrive?")
print(response)  # 正确关联了 order #12345,不用我再重复一遍

在用 MAF 之前,我得手动把消息追加到一个列表里,然后在每次调用时把整个历史记录传回给 LLM。Session 把这些脏活累活全抽象掉了。框架在后台默默管理着消息历史、工具调用结果和助手回复。

一个关键点:Session 对象是有状态的,所以如果你在构建 Web 服务,每个用户的对话都需要对应一个独立的 session。千万别在多个用户间共享同一个 session——我测试的时候这么干过,收到的回复简直是驴唇不对马嘴。

第 4 步:记忆与持久化

Session 负责处理短期的对话记忆,但那些需要跨 session 访问的持久化上下文该怎么办?第 4 步讲的是 context provider(上下文提供者)。

from agent_framework import Agent, ContextProvider

class UserProfileProvider(ContextProvider):
    async def get_context(self, user_id: str) -> str:
        # 生产环境中从数据库获取
        return f"User is a premium member since 2022. Preferred language: English."

agent = Agent(
    name="support-agent",
    instructions="You are a customer support agent. Personalize responses based on user context.",
    context_providers=[UserProfileProvider()]
)

Context provider 会在调用时将信息注入到 agent 的系统提示词中。这非常适合用来处理用户画像、账户详情,或者任何你希望 agent 随时“知道”的当前用户数据。

一开始,我试着把所有东西都硬塞进 instructions 参数里,结果很快就乱成了一锅粥。Context provider 能保持基础指令的整洁,同时动态注入相关数据。这种关注点分离的做法,让你写出的 agent 可维护性高得多。

第 5 & 6 步:工作流与 Agent Harness

这才是 MAF 真正亮出杀手锏的地方。第 5 步引入了确定性工作流,用于编排多步骤流程;第 6 步则加入了能够规划和追踪复杂任务的“harness” agent。

工作流让你可以按定义好的顺序把 agent 串联起来——Agent A 处理输入,把结果传给 Agent B,依此类推。而 harness agent 则更进一步,它充当一个调度器,可以拆分复杂请求、委派给专门的 agent,并追踪进度。

我还没用 harness 搭建过生产级的东西,但我试玩了一个简单的研究工作流:一个 agent 负责查找信息,另一个负责总结,第三个负责格式化输出。工作流的语法非常清爽:

from agent_framework import Workflow, Step

workflow = Workflow(
    steps=[
        Step(agent=research_agent, name="research"),
        Step(agent=summary_agent, name="summarize"),
        Step(agent=format_agent, name="format")
    ]
)

result = await workflow.invoke("Explain quantum computing for a blog post")

每一步的输出会自动作为下一步的输入。你也可以加入条件逻辑和分支,不过我目前还用不上这个。

第 7 步:托管你的 Agent

最后一步讲的是如何通过托管基础设施将你的 agent 暴露出去。到了这一步,你的 agent 就从一个本地脚本变成了用户真正能交互的东西。该框架提供了与 Azure 托管选项的集成,让你能轻松把 agent 部署为一个 API 端点。

我跟着教程,大概花了 20 分钟就把一个测试 agent 部署到了 Azure Container Apps 上。托管设置的整个过程比我预想的要顺利,不过你还是需要对 Azure 基础设施有点了解。

真实评价与实用建议

花了一个周末折腾 MAF 之后,以下是我的看法:

我喜欢的点:

  • 循序渐进的教程结构真的很棒。每一步都建立在上一步的基础上,不会让你感到信息过载。
  • 只要配置正确,工具调用就能“直接跑通”。自动循环处理帮我省掉了大量代码。
  • Session 和 context provider 非常优雅地解决了实际问题。

需要注意的局限:

  • 框架还在不断演进。我碰到了一些粗糙的边缘,特别是有些报错信息让人一头雾水。
  • 相比 Python 和 C#,Go 版本缺失了不少重要功能。
  • 核心教程之外的文档比较匮乏。当我想自定义工具调用行为时,最后只能去啃源码。
  • 如果你不用 Azure,配置起来就需要额外折腾。它的默认设定是面向 Azure 的。

我的踩坑经验总结:

  1. 务必给工具函数加上详细的 docstring。这是硬性要求,没得商量。
  2. 如果你不在 Jupyter 里跑代码,记得用 asyncio.run()
  3. 每个用户对话对应一个 session——千万别共享状态。
  4. 从第 1 步开始,按顺序往下走。跳着看只会让你越看越懵。
  5. agent 的指令要聚焦且具体。指令含糊,行为就含糊。

MAF 并不是市面上唯一的 agent 框架,对于简单的用例来说,用它可能有点杀鸡用牛刀了。但如果你要构建的东西需要用到工具、对话记忆和多步骤工作流——尤其是如果你本身就在 Azure 生态里——那它绝对值得你认真看看。这种渐进式的设计意味着你可以一点点地引入它,而不需要一上来就投入巨大的成本。

相关 Agent

D

Docker

Docker 是一个容器化平台,允许开发者将应用及其依赖项打包成轻量级、可移植的容器。它简化了跨环境的开发、测试和部署过程。该描述强调它最适合容器化和开发环境,提供免费方案和团队方案,团队方案从每用户每月5美元起。

了解更多 →