首页 / 文章 / 面向未来工程师的AI智能体:记忆、工具与控制循环

面向未来工程师的AI智能体:记忆、工具与控制循环

一张实用的智能体构建模块地图——涵盖规划、工具、记忆与评估功能——摒弃了那些用以替代设计的华而不实的术语。

2466 词

本指南旨在为《AI工程师未来需要了解的关于AI智能体的所有知识》重建一条可操作的路径。重点在于合约、校验机制,以及那些无需猜测意图即可直接放入代码库的代码。在修改代码之前,应先明确输入参数、该步骤的负责人以及终止标准。操作人员应当能够从已知的检查点重新运行该步骤,而无需猜测其中的隐藏状态。相比庞大的脚本,更应优先使用小型且可测试的单元。当某个步骤失败时,故障原因应当指向单一责任模块,而非复杂的流程链。

智能体如何执行动作

在修改代码之前,需先明确“代理如何执行操作”,包括输入参数、该步骤的负责人以及终止条件。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 应将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功标准,杜绝默许的半完成状态。 严格限制工具的结构规范。过宽的自由文本参数容易引发注入攻击,还会增加审计成本。

import requests

def search_web(query: str) -> list[dict]:
    response = requests.get(
        "https://serpapi.com/search",
        params={"q": query, "api_key": "YOUR_API_KEY", "num": 5},
    )
    results = response.json()["organic_results"]
    return [
        {"title": r["title"], "url": r["link"], "snippet": r["snippet"]}
        for r in results
    ]

results = search_web("best sourdough recipe")
for r in results:
    print(r["title"], "-", r["url"])
import anthropic

client = anthropic.Anthropic()

# The menu of tools the model can choose from
tools = [
    {
        "name": "web_search",
        "description": "Search the web for current information.",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {"type": "string", "description": "The search query"}
            },
            "required": ["query"],
        },
    }
]

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "What's the weather in Seattle right now?"}],
)

print(response.content)
# [ToolUseBlock(name='web_search', input={'query': 'Seattle weather today'})]
# 1. Parse the LLM response to find the tools it wants to run
tool_calls = [block for block in response.content if block.type == "tool_use"]

# 2. Run the functions directly, OUTSIDE of the LLM
#    (this is our search_web function from earlier -- plain Python,
#     the model never sees this code)
tool_results = []
for call in tool_calls:
    if call.name == "web_search":
        output = search_web(call.input["query"])
        tool_results.append(
            {
                "type": "tool_result",
                "tool_use_id": call.id,
                "content": str(output),
            }
        )

# 3. Hand the results back -- from the model's perspective,
#    the answer just shows up in the chat
final = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[
        {"role": "user", "content": "What's the weather in Seattle right now?"},
        {"role": "assistant", "content": response.content},
        {"role": "user", "content": tool_results},
    ],
)

print(final.content[0].text)
# "It's 62 and cloudy in Seattle."

多步骤任务

对于多步骤任务,在修改代码之前需明确输入内容、各步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新执行相应步骤,而无需猜测隐藏状态。应在功能结果旁记录执行时间和成本。提前了解这些信息可以避免在任务从演示环境过渡到共享环境时出现意外费用。需严格限制工具的架构,过宽的自由文本参数容易引发注入攻击,并增加审计成本。

# The ReAct loop
while True:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        tools=tools,
        messages=messages,
    )
    messages.append({"role": "assistant", "content": response.content})

    # If the model didn't ask for any tools, it's done -- that's its final answer
    if response.stop_reason != "tool_use":
        break

    # Otherwise: run the tools, append the results, and go around again
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            output = run_tool(block.name, block.input)
            tool_results.append(
                {"type": "tool_result", "tool_use_id": block.id, "content": str(output)}
            )
    messages.append({"role": "user", "content": tool_results})

print(response.content[0].text)
# "Booked it into your calendar -- cheapest flight was the 9:15am Alaska
#  departure Friday at $138. Event added from 9:15am to 11:30am."

可靠的输出

为确保输出可靠,在修改代码之前需明确输入参数、该步骤的负责人以及终止条件。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 配置信息应置于应用程序代码之外。环境文件、密钥存储和功能标志应集中存放于一个位置,以便操作人员无需查看整个流程即可进行审计。 严格限制工具的架构。过宽的自由文本参数容易引发注入攻击,且会增加审计成本。 为确保输出可靠,在修改代码之前需明确输入参数、该步骤的负责人以及终止条件。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 相较于庞大的脚本,应优先使用小型且可测试的单元。当某个步骤失败时,故障原因应能明确指向某个具体责任模块,而非整个复杂的流程。

system_prompt = """You have access to a web_search tool.
To use it, respond with JSON in this format:
{"name": "web_search", "input": {"query": "..."}}

CRITICAL: You MUST respond with ONLY valid JSON. NO other text.
NO markdown. NO code fences. NO explanations before or after.
Your ENTIRE response must be parseable by json.loads().
DO NOT FORGET THE COMMAS. CHECK YOUR BRACKETS.
If you output anything that is not valid JSON, the system WILL CRASH.
THIS IS EXTREMELY IMPORTANT. VALID JSON ONLY.
"""

高质量输入

对于高质量输入,在修改代码之前需明确输入内容、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的半完成状态。 在耗时的模型调用之后设置检查点,以避免重复处理相同任务时再次产生费用。

tools = [
    {
        "name": "web_search",
        "description": "Search the web for current information.",
        "input_schema": {
            "type": "object",
            "properties": {"query": {"type": "string"}},
            "required": ["query"],
        },
    },
    {
        "name": "add_calendar_event",
        "description": "Add an event to the user's calendar.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start_time": {"type": "string"},
            },
            "required": ["title", "start_time"],
        },
    },
    # ...plus read_email, send_email, get_flights, book_flight,
    # read_file, write_file, run_code, and 20 more
]

信任你的智能体

在修改代码之前,为“信任您的代理”模式明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。应在功能结果旁记录执行时间和成本。提前明确这些信息,可避免在流程从演示环境切换到共享环境时出现意外费用。

操作检查清单

对于操作检查清单,同样需要在修改代码之前明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理方式都是产品的一部分,而非后续需要补充的内容。

在耗资较高的模型调用之后设置检查点,这样重试时就不会再次为相同的工作收费。

在预算允许的情况下,通过固定装置在持续集成中添加用于测试关键路径的烟雾测试。

应优先选择小型、可测试的单元,而非庞大的脚本。当某个步骤失败时,故障应能指向单一责任模块,而非复杂的流程链。

在耗资较高的模型调用之后设置检查点,这样重试时就不会再次为相同的工作收费。

在升级技术栈之前,应冻结版本、为关键路径记录标准操作流程,并确认回滚步骤。共享环境需要设置速率限制、租户验证机制,以及明确的密钥轮换负责人。与其追求花哨的一次性演示,不如注重扎实的可靠性。

针对强化措施注意事项0,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

在功能结果旁记录执行时间和成本。提前明确这些信息可避免在流程从演示环境转向共享环境时出现意外费用。

严格限制工具架构的灵活性。过宽的自由文本参数容易引发注入攻击,还会增加审计成本。

针对强化措施注意事项1,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

需同时记录正常流程和故障恢复流程。重试机制、人工审核环节以及错误处理方式都是产品的一部分,而非后续需要补充的内容。

在耗资较高的模型调用之后设置检查点,这样重新尝试时就不会重复计算相同的工作。

关于强化措施第2点,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

将此阶段视为输入与验证后输出之间的契约。为相关成果命名,定义成功判定标准,并拒绝默许的半完成状态。

将规划与工具执行分开。规划者负责提出方案,执行者负责进行操作,验证者则根据目标检查结果。

关于强化措施第3点,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

将配置置于应用程序代码之外。环境文件、密钥存储和功能开关应集中存放,以便操作员无需查看整个系统结构即可进行审计。

严格限制工具的架构。过长的自由文本参数容易引发注入攻击,且会增加审计成本。

针对强化措施第4点,在修改代码之前需明确输入参数、该步骤的负责人以及完成标准。操作员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

优先选择小型、可测试的单元,而非庞大的脚本。当某个步骤失败时,故障应指向单一责任模块,而非复杂的流程链。

在耗时的模型调用之后设置检查点,这样重试时就不会重复处理相同的工作。

针对强化建议5,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

在功能结果旁记录执行时间和成本。提前明确这些信息可避免在流程从演示环境转向共享环境时出现意外费用。

将规划与工具执行分开。规划者负责提出方案,执行者负责进行修改,验证者则根据目标检查最终结果。

针对强化建议6,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

需同时记录正常流程和故障恢复流程。重试机制、人工审核环节以及错误处理方式都是产品的一部分,而非后续需要补充的内容。

严格限制工具架构的灵活性。过长的自由文本参数容易引发注入攻击,且会增加审计成本。

关于强化措施7,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功检测标准,并拒绝默许的半完成状态。

在耗时的模型调用之后设置检查点,以避免重复执行相同任务时再次产生费用。

关于强化措施8,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

将配置置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一处,以便操作员无需查看整个系统结构即可进行审计。

将规划与工具执行分开。规划器负责提出方案,执行器负责实施变更,验证器则根据目标检查结果。

针对强化措施第9点,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

优先选择小型且可测试的单元,而非庞大的脚本。当某个步骤失败时,故障应能指向单一责任主体,而非复杂的流程链。

严格限制工具的架构。过宽的自由文本参数容易引发注入攻击,也会增加审计成本。

针对强化措施注意事项10,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

在功能测试结果旁记录执行时间和成本。提前明确这些信息可避免在流程从演示环境转向共享环境时出现意外费用。

在耗时的模型调用之后设置检查点,这样重新尝试时就不会重复计算相同的工作量。

针对强化措施注意事项11,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理方式都是产品的一部分,而非后续需要补充的内容。

将规划与工具执行分开。规划者提出方案,执行者进行修改,验证者则根据目标检查结果。

针对强化措施备注12,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

将此阶段视为输入与已验证输出之间的契约。为相关成果命名,明确成功判定标准,杜绝默许的半完成状态。

严格限制工具的结构规范。过宽的自由文本参数容易引发注入攻击,还会增加审计成本。

针对强化措施备注13,在修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

将配置信息置于应用程序代码之外。环境文件、密钥存储以及功能开关应集中存放于一处,以便操作员无需查看整个系统结构即可进行审计。

在执行成本较高的模型调用后设置检查点,这样重试时就不会重复处理相同的工作。

针对强化安全性的第14条建议,应在修改代码之前明确输入参数、该步骤的负责人以及终止标准。操作员应能够基于已知的检查点重新运行该步骤,而无需猜测其中的隐藏状态。

优先选择小型且可测试的单元,而非结构复杂的脚本。当某个步骤失败时,故障应能指向具体的责任模块,而非整个混乱的流程。

将规划与工具执行分开。规划者负责提出方案,执行者负责实际操作,验证者则根据目标检查结果。

针对强化安全建议15,在修改代码之前需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。

应在功能结果旁记录执行时间和成本。提前了解这些信息可避免在系统从演示环境过渡到共享环境时出现意外费用。

需严格限制工具架构。过宽的自由文本参数容易引发注入攻击,还会增加审计成本。