大模型实战:把自定义 Agent 封装成一个 HTTP 服务

前面几篇一直在拆 Agent 的"脑袋":

  • 它内部是一个循环:思考 → 行动 → 观察 → 记录;
  • 它会用工具、会记忆、还能自我反思;
  • 多个 Agent 可以组成一个"家族",通过调度器协作。

但在工程实践里,很多人做到这里会卡住:

这些 Agent 只能在一份 Python 脚本里跑,

其它项目想用,又要复制粘贴一大堆代码。

这篇就从工程落地的角度做一件事:

把一个 Agent 封装成一个简单的 HTTP 服务

让它对外暴露一个统一接口:

POST /agent/infer → 返回结构化结果。

整个过程只围绕技术实现,不讨论任何组织场景,方便你直接集成到自己的项目里。


一、目标长什么样?

先想清楚最终想要的使用方式。理想状态下,别的项目只需要:

复制代码
curl -X POST http://localhost:8000/agent/infer \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "rag_qa",
    "query": "请用3点概括这个系统的核心功能",
    "context": {
      "user_id": "u123",
      "lang": "zh"
    }
  }'

然后拿到一个结构清晰的响应:

复制代码
{
  "agent": "rag_qa",
  "ok": true,
  "answer": "......",
  "meta": {
    "used_docs": [/* 文档id列表或片段 */],
    "latency_ms": 853,
    "trace_id": "20260208-abc123"
  }
}

用一句话概括:

无论里面是多复杂的多智能体协作、RAG、工具调用,
对外就一个接口 + 一种统一返回格式


二、抽象一个最小的 Agent 接口

先把内部实现统一成一个简单的 Python 接口,方便我们后面挂到 HTTP 层。

2.1 抽象基类

python 复制代码
from abc import ABC, abstractmethod
from typing import Dict, Any

class BaseAgent(ABC):
    def __init__(self, name: str):
        self.name = name

    @abstractmethod
    def handle(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
        """
        :param query: 用户这次请求的自然语言或结构化指令
        :param context: 额外上下文,比如 user_id / locale / 历史状态键等
        :return: {
            "answer": str,
            "meta": {...}  # 可选:调试信息、trace、引用内容等
        }
        """
        pass

之后你所有具体 Agent(RAG 问答、代码解释、报告生成等)都实现同一个 handle 签名,HTTP 层就可以做到**"不关心里面是谁,只要会 handle"**。

2.2 一个示例实现:RAG 问答 Agent

python 复制代码
class RAGQAgent(BaseAgent):
    def __init__(self, name, llm, retriever):
        super().__init__(name)
        self.llm = llm
        self.retriever = retriever

    def handle(self, query: str, context: Dict[str, Any]) -> Dict[str, Any]:
        docs = self.retriever.retrieve(query, k=4)
        ctx_text = "\n\n".join(docs)

        prompt = (
            "你是一个基于文档的问答助手,请严格参考给定内容回答问题。\n"
            "如果文档中没有相关信息,请说明"资料中未提及"。\n\n"
            f"【文档片段】\n{ctx_text}\n\n"
            f"【问题】\n{query}\n"
        )

        answer = self.llm(prompt)

        return {
            "answer": answer,
            "meta": {
                "doc_count": len(docs),
                "docs_preview": [d[:100] for d in docs]
            }
        }

此时,对 HTTP 层来说,它只看到一个:

python 复制代码
agent = RAGQAgent("rag_qa", llm, retriever)
result = agent.handle(query, context)

三、构建一个简单的 Agent 注册表

为了避免在 HTTP 代码里写一堆 if agent_name == "xxx",建议搞一个注册表(Registry)​,按名字管理 Agent 实例。

python 复制代码
class AgentRegistry:
    def __init__(self):
        self._agents = {}

    def register(self, agent: BaseAgent):
        self._agents[agent.name] = agent

    def get(self, name: str) -> BaseAgent:
        if name not in self._agents:
            raise KeyError(f"未知 Agent: {name}")
        return self._agents[name]

    def list_agents(self):
        return list(self._agents.keys())

在应用启动时集中注册:

python 复制代码
registry = AgentRegistry()

# 假设已经初始化好了 llm、retriever 等
rag_qa_agent = RAGQAgent("rag_qa", llm, retriever)
summary_agent = SummaryAgent("summary", llm)  # 自己实现

registry.register(rag_qa_agent)
registry.register(summary_agent)

这样,无论将来增加多少种 Agent,只需要在启动时 register 一下即可。


四、用一个轻量框架把 Agent 暴露成 HTTP 接口

这里用 FastAPI 举例(你也可以换成 Flask、Django 等),逻辑都类似:解析请求 → 找到对应 Agent → 调用 handle → 包装响应

4.1 定义请求与响应模型

python 复制代码
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Dict, Any

app = FastAPI()

class AgentRequest(BaseModel):
    agent: str
    query: str
    context: Dict[str, Any] = {}

class AgentResponse(BaseModel):
    agent: str
    ok: bool
    answer: str
    meta: Dict[str, Any] = {}

4.2 实现统一推理接口

python 复制代码
import time

@app.post("/agent/infer", response_model=AgentResponse)
def infer(req: AgentRequest):
    start = time.time()
    try:
        agent = registry.get(req.agent)
    except KeyError:
        raise HTTPException(status_code=404, detail=f"Agent '{req.agent}' 未注册")

    try:
        result = agent.handle(req.query, req.context or {})
        latency_ms = (time.time() - start) * 1000
        meta = result.get("meta", {})
        meta["latency_ms"] = latency_ms

        return AgentResponse(
            agent=agent.name,
            ok=True,
            answer=result.get("answer", ""),
            meta=meta
        )
    except Exception as e:
        # 这里可以加日志
        raise HTTPException(status_code=500, detail=str(e))

启动服务后,就得到了一个通用的 Agent 服务入口。


五、为 Agent 服务加上最小可用的"健康度"接口

为了方便排查问题,建议顺手加两个简单的辅助接口:

5.1 查看已注册的 Agent 列表

python 复制代码
@app.get("/agent/list")
def list_agents():
    return {"agents": registry.list_agents()}

5.2 健康检查

python 复制代码
@app.get("/health")
def health():
    return {"status": "ok"}

这样在部署后,用浏览器或命令行测试就很方便:

python 复制代码
curl http://localhost:8000/agent/list
curl http://localhost:8000/health

六、在调用侧怎么接入这个 Agent 服务?

一旦把 Agent 封装成 HTTP 服务,其他项目就可以无需关心内部细节,通过 HTTP 客户端直接调用。

以 Python 为例:

python 复制代码
import requests

def call_agent(server_url: str, agent: str, query: str, context=None):
    payload = {
        "agent": agent,
        "query": query,
        "context": context or {}
    }
    resp = requests.post(f"{server_url}/agent/infer", json=payload, timeout=30)
    resp.raise_for_status()
    data = resp.json()
    if not data.get("ok"):
        raise RuntimeError("Agent 调用失败")
    return data["answer"], data.get("meta", {})

其它语言(Java、Go、JavaScript 等)也只需要写一个类似的 HTTP 客户端封装即可。


七、如何渐进式把你现有的多智能体系统"服务化"?

结合你前面已经实现的多智能体、自我反思、RAG 体系,可以按以下顺序慢慢迁移,不用"一次性大改":

  1. 先挑一个最核心的 Agent 做试点

    比如 rag_qapolicy_explain 这种最常用的问答 Agent:

    • 抽取成实现了 BaseAgent.handle 的类;
    • 用上文的 FastAPI 逻辑包一层 HTTP。
  2. 逐步把其它 Agent 接进注册表

    • ReportAgent、SummaryAgent、CodeAgent 等;
    • 每个都保持统一签名:handle(query, context)
  3. 在旧系统中先改"调用方式",不改逻辑

    • 先把原来直接调用 Python 类的地方,换成 HTTP 客户端调用;
    • 确认行为一致后,再考虑进一步拆分、迁移。
  4. 最后再考虑拆分进不同进程、不同机器

    • 一个服务里可以先挂多个 Agent;
    • 请求量大了,再按 Agent 维度拆服务也比较自然。

做到这里,你的 Agent 体系就从:

只能在一个进程里本地调用的"类"

升级为:

任何语言、任何项目都可以通过 HTTP 复用的"服务"。


八、小结

这篇不再深挖 Agent 的内部算法,而是回到一个非常工程化的问题:

怎么让已经写好的 Agent,更容易被复用?​

我做了几件事:

  1. 用一个统一的 BaseAgent.handle(query, context) 抽象所有 Agent;
  2. AgentRegistry 统一管理并按名字查找实例;
  3. 用一个轻量 HTTP 框架包一层 /agent/infer 的接口;
  4. 为服务加上简单的 /agent/list/health 辅助接口;
  5. 示范了调用方如何用 HTTP 客户端直接接 Agent。
相关推荐
不懒不懒1 小时前
【从零开始:PyTorch实现MNIST手写数字识别全流程解析】
人工智能·pytorch·python
zhangshuang-peta1 小时前
从REST到MCP:为何及如何为AI代理升级API
人工智能·ai agent·mcp·peta
helloworld也报错?1 小时前
基于CrewAI创建一个简单的智能体
人工智能·python·vllm
EdisonZhou2 小时前
MAF快速入门(15)Agent调试利器:DevUI
llm·aigc·agent·.net core
wukangjupingbb2 小时前
Gemini 3和GPT-5.1在多模态处理上的对比
人工智能·gpt·机器学习
明月照山海-2 小时前
机器学习周报三十四
人工智能·机器学习
啥都生2 小时前
Claude和GPT新模型撞车发布。。。
人工智能
Katecat996632 小时前
蚊子幼虫与蛹的自动检测与分类-VFNet_R101_FPN_MS-2x_COCO实现详解
人工智能·数据挖掘
云空2 小时前
日常高频英语口语实用表达播客
人工智能·机器人