多代理

  |   0 评论   |   0 浏览

你将学会: 先判断该不该拆;用 Skills(不换执行者)解决「领域知识太多」。
前置: 阶段 1~2。不要一上来就上多代理。

四种模式

先问: 单代理是不是工具太多选错、是不是两块知识不该同时进上下文、是不是要并行?都不是就别拆。

模式换执行者先学
Skills否,按需加载提示词本课
Subagents是,当工具调,上下文隔离仓库加深
Handoffs是,改状态切换阶段仓库加深
Router分类后分发仓库加深

完整代码:Skills

from dotenv import load_dotenv

load_dotenv()

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.tools import tool

model = init_chat_model(
    "deepseek:deepseek-chat",
    temperature=0.5,
    max_tokens=2500,
    timeout=300,
    max_retries=6,
)

SKILLS = {
    "write_sql": "你是 SQL 专家。先写表假设,再给 SELECT,默认 LIMIT 10,并解释。",
    "review_contract": "你是合同审查。列出金额/期限/违约,标风险,最后一句建议。",
}


@tool
def load_skill(skill_name: str) -> str:
    """加载技能正文。可用:write_sql、review_contract。"""
    skill = SKILLS.get(skill_name)
    print(f"  [load_skill] {skill_name}", flush=True)
    return skill or f"没有技能 {skill_name}"


agent = create_agent(
    model=model,
    tools=[load_skill],
    system_prompt=(
        "专业任务必须先 load_skill 再作答。"
        "可用:write_sql、review_contract。"
    ),
)
r = agent.invoke({
    "messages": [{"role": "user", "content": "写个查询:每个用户的订单数。"}]
})
print("调用 =>", [tc["name"] for m in r["messages"] if m.type == "ai" for tc in m.tool_calls])
print("回答 =>", r["messages"][-1].text[:300])

应看到 [load_skill] write_sql。这还是一个 agent,只是提示词按需灌入。

真的换执行者:子代理当工具

Skills 不够用时(两块知识不该同时进上下文、要隔离失败),把另一个 agent 包成工具。子代理每次都是全新上下文,主代理只拿到返回文本。

from dotenv import load_dotenv

load_dotenv()

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.tools import tool

model = init_chat_model(
    "deepseek:deepseek-chat",
    temperature=0.5,
    max_tokens=2500,
    timeout=300,
    max_retries=6,
)


def search_docs(query: str) -> str:
    """搜索内部文档。"""
    return f"关于「{query}」的文档结论:用 create_agent 即可,不必先画 LangGraph。"


research_agent = create_agent(
    model=model,
    tools=[search_docs],
    system_prompt="你是调研专家。必须调用 search_docs,只用一句话给结论。",
)


@tool("research", description="调研一个主题并返回结论")
def call_research_agent(query: str) -> str:
    result = research_agent.invoke({"messages": [{"role": "user", "content": query}]})
    return result["messages"][-1].text


main_agent = create_agent(
    model=model,
    tools=[call_research_agent],
    system_prompt="调研类问题必须调用 research 工具,不要自己编资料。",
)
result = main_agent.invoke({
    "messages": [{"role": "user", "content": "调研:LangChain 里多代理怎么编排?"}]
})
print("主代理调用 =>", [
    tc["name"] for m in result["messages"] if m.type == "ai" for tc in m.tool_calls
])
print("最终回复 =>", result["messages"][-1].text[:200])

应看到主代理调用 research。Handoffs(改状态切换阶段)和 Router(先分类再分发)见仓库,本课不要求手写。

练习

  1. 再问一句合同条款,确认加载的是 review_contract
  2. 跑通上面的子代理脚本,口述:Skills 和 Subagents 谁换了执行者、谁隔离了上下文。

本章验收

  •  能说出三种「值得拆」的信号
  •  能独立写出 load_skill 并跑通
  •  能解释:子代理为什么「当工具调用」而不是再开一个聊天窗口

对照仓库:04-多代理/ 下 Handoffs / Router / Subagents 与四篇 Build 教程。

下一课:LangGraph


标题:多代理
作者:llp
地址:https://llinp.cn/articles/2026/08/23/1787493452898.html