Skip to content

xtolly/superbox-agent-server

Repository files navigation

Agent Server

基于 LangGraphFastAPI 构建的智能 Agent 服务器,采用 JSON-RPC 2.0 协议通过 WebSocket 实现与客户端的实时双向通信。支持多 Agent 动态切换、混合工具系统(内置工具 + 客户端远程工具 + MCP 工具)、以及 RESTful API 扩展。

🌟 核心特性

  • JSON-RPC 2.0 协议: 标准化的请求/响应/通知格式,支持批量请求
  • WebSocket 实时通信: 基于 FastAPI WebSocket 的双向通信
  • 多 Agent 架构: 支持多个 Agent 并存,按需切换,自动发现注册
  • 混合工具系统:
    • 内置工具 — 服务端直接执行(如 get_current_timecalculator
    • 客户端工具 — 通过 JSON-RPC 远程调用客户端执行
    • MCP 工具 — 通过 Model Context Protocol 连接外部服务
  • Graph-based 执行: LangGraph 状态图驱动,内置 interrupt / resume 机制
  • RESTful API: 独立的 HTTP 端点,支持批量元件型号替换等功能
  • 可配置 LLM: 支持 OpenAI 兼容 API(DeepSeek、Qwen 等)
  • 会话管理: 多会话并发,每个会话独立状态、独立工具集
  • 日志系统: 按天轮转的控制台 + 文件双通道日志

📋 系统架构

┌──────────────┐        WebSocket         ┌───────────────────────────────────┐
│    Client    │ ◄──────────────────────► │           Agent Server            │
│  (C# .NET)  │     JSON-RPC 2.0         │            (Python)               │
└──────┬───────┘                          │                                   │
       │                                  │  ┌─────────────┐  ┌───────────┐  │
       │ 1. agent.register               │  │  LangGraph   │  │ MCP       │  │
       ├─────────────────────────────────►│  │  Agent       │  │ Manager   │  │
       │                                  │  │  ┌─────────┐ │  │           │  │
       │ 2. agent.chat                    │  │  │CAD Agent│ │  │  dx2-mcp  │  │
       ├─────────────────────────────────►│  │  ├─────────┤ │  └───────────┘  │
       │                                  │  │  │Component│ │                  │
       │ 3. agent.toolCall (notification) │  │  │Replace  │ │  ┌───────────┐  │
       │◄─────────────────────────────────┤  │  │Agent    │ │  │ Builtin   │  │
       │                                  │  │  └─────────┘ │  │ Tools     │  │
  ┌────┴─────┐                            │  └─────────────┘  └───────────┘  │
  │ Execute  │                            │                                   │
  │  Tool    │                            │  ┌────────────────────────────┐   │
  └────┬─────┘                            │  │    REST API                │   │
       │                                  │  │  POST /api/batch-replace   │   │
       │ 4. agent.submitToolResult        │  └────────────────────────────┘   │
       ├─────────────────────────────────►│                                   │
       │                                  └───────────────────────────────────┘
       │ 5. agent.response (notification)
       │◄─────────────────────────────────┤

通信时序

Client                                          Server
  │                                               │
  │  ── agent.register (tools=[...]) ──────────►  │  注册客户端 & 工具
  │  ◄── result: {status, tools_synced} ────────  │
  │                                               │
  │  ── agent.chat (message) ──────────────────►  │  发送用户消息
  │  ◄── agent.status {thinking} ───────────────  │  状态通知
  │                                               │
  │          ┌─── LangGraph 执行 ───┐             │
  │          │ call_llm → 工具调用   │             │
  │          │ 内置工具 → 立即执行   │             │
  │          │ 客户端工具 → interrupt │             │
  │          └──────────────────────┘             │
  │                                               │
  │  ◄── agent.toolCall {call_id, args} ────────  │  请求执行客户端工具
  │  ── agent.submitToolResult {result} ────────► │  返回工具结果
  │                                               │
  │          ┌─── resume 继续执行 ───┐             │
  │          └──────────────────────┘             │
  │                                               │
  │  ◄── agent.response {content} ──────────────  │  最终响应

🚀 快速开始

环境要求

  • Python >= 3.11
  • uv (Python 包管理器)

安装

# 克隆项目
git clone <repository-url>
cd agent-server

# 安装依赖
uv sync

配置环境变量

创建 .env 文件:

# LLM API 配置(OpenAI 兼容接口)
OPENAI_API_KEY=your-api-key
OPENAI_API_BASE=https://api.openai.com/v1
MODEL_NAME=gpt-4
TEMPERATURE=0.01

# 服务器配置
HOST=0.0.0.0
PORT=8999

# Agent 配置
AGENT_TIMEOUT=600.0

# 其他
MAX_MESSAGE_SIZE=1048576
LOG_BACKUP_COUNT=30

启动服务器

python app.py

服务器将在 http://0.0.0.0:8999 启动。可通过 /health/ready 检查服务状态。

📁 项目结构

agent-server/
├── app.py                     # FastAPI 应用入口 & WebSocket/HTTP 端点
├── pyproject.toml             # 项目配置和依赖
├── mcp_servers.json           # MCP 服务器配置
├── .env                       # 环境变量配置
│
├── agent/                     # Agent 核心
│   ├── base.py                # BaseAgent 基类(LangGraph 图构建、interrupt/resume)
│   ├── state.py               # AgentState / PendingToolCall 状态定义
│   ├── registry.py            # AgentRegistry 注册表(自动发现、单例管理)
│   └── agents/                # 具体 Agent 实现
│       ├── cad_agent.py       # CADAgent — CAD 绘图/建模助手
│       └── component_replacement_agent.py
│                              # ComponentReplacementAgent — 电气元件替换工作流
│
├── jsonrpc/                   # JSON-RPC 2.0 协议层
│   ├── models.py              # 请求/响应/通知/错误码 Pydantic 模型
│   ├── methods.py             # MethodRouter 方法路由器(装饰器注册 + 分发)
│   └── handler.py             # JsonRpcHandler 消息解析 & 处理
│
├── services/                  # 业务服务层
│   ├── websocket_handler.py   # JSON-RPC 方法实现(register/chat/toolResult 等)
│   ├── connection_manager.py  # WebSocket 连接 & 会话管理(SessionData)
│   └── agent_handler.py       # Agent 执行器(execute / resume + 超时控制)
│
├── tools/                     # 工具系统
│   ├── base.py                # ToolRegistry 注册表 + MCP→OpenAI 格式转换
│   └── builtin.py             # 内置工具(get_current_time / calculator)
│
├── api/                       # RESTful API
│   └── routers/
│       └── batch_replace.py   # POST /api/batch-replace — 批量元件型号替换
│
├── core/                      # 核心基础设施
│   ├── config.py              # Settings 配置类(Pydantic Settings + .env)
│   ├── logging.py             # 日志配置(控制台 + 按天轮转文件)
│   ├── mcp_manager.py         # MCPManager — MCP 服务器生命周期管理
│   └── exceptions.py          # 自定义异常体系
│
├── utils/                     # 工具库
│   └── dx2_accessor.py        # Dx2 数据访问(厂家/系列查询 + 模糊搜索)
│
├── client/                    # C# 客户端代码
│   └── Leadsoft.Common.Agent/ # C# .NET Agent 客户端库
│
├── scripts/                   # 辅助脚本
│   ├── debug_component_replacement_agent.py
│   └── generate_bomset.py
│
└── assets/                    # 静态数据资源
    └── dx2/                   # Dx2 厂家/系列数据文件

📡 JSON-RPC 2.0 协议

连接

ws://localhost:8999/v1/ws?session_id={your-session-id}

也支持旧版端点 ws://localhost:8999/ws?session_id={your-session-id}

客户端 → 服务端

1. agent.register — 注册客户端与工具

{
  "jsonrpc": "2.0",
  "method": "agent.register",
  "params": {
    "client_id": "cad-client-001",
    "agent_id": "component_replacement",
    "tools": [
      {
        "name": "fetch_bom_tool",
        "description": "获取BOM明细列表",
        "inputSchema": {
          "type": "object",
          "properties": {},
          "required": []
        }
      }
    ]
  },
  "id": 1
}

响应:

{
  "jsonrpc": "2.0",
  "result": {
    "status": "registered",
    "agent_id": "component_replacement",
    "tools_count": 1,
    "tools_synced": ["fetch_bom_tool", "ask_user_tool"]
  },
  "id": 1
}

2. agent.chat — 发送消息

{
  "jsonrpc": "2.0",
  "method": "agent.chat",
  "params": { "message": "把所有NDM2断路器替换为正泰NXM系列" },
  "id": 2
}

3. agent.submitToolResult — 提交工具执行结果

{
  "jsonrpc": "2.0",
  "method": "agent.submitToolResult",
  "params": {
    "call_id": "call_abc123",
    "tool_name": "fetch_bom_tool",
    "success": true,
    "result": "[{\"id\":1, \"type\":\"NDM2-63\", ...}]"
  },
  "id": 3
}

4. agent.clearHistory — 清除会话历史

{
  "jsonrpc": "2.0",
  "method": "agent.clearHistory",
  "params": { "agent_id": "component_replacement" },
  "id": 4
}

5. system.ping — 心跳检测

{ "jsonrpc": "2.0", "method": "system.ping", "id": 5 }

6. system.listAgents — 列出可用 Agent

{ "jsonrpc": "2.0", "method": "system.listAgents", "id": 6 }

服务端 → 客户端(通知)

agent.status — 状态更新

{
  "jsonrpc": "2.0",
  "method": "agent.status",
  "params": { "status": "thinking", "message": "正在分析替换需求..." }
}

状态值包括:thinkingexecutingtools_synced 等。

agent.toolCall — 工具调用请求

{
  "jsonrpc": "2.0",
  "method": "agent.toolCall",
  "params": {
    "call_id": "call_abc123",
    "tool_name": "fetch_bom_tool",
    "arguments": {}
  }
}

agent.response — 最终响应

{
  "jsonrpc": "2.0",
  "method": "agent.response",
  "params": { "content": "已完成所有NDM2断路器到NXM系列的替换。" }
}

错误码

代码 常量 含义
-32700 PARSE_ERROR 无效的 JSON
-32600 INVALID_REQUEST 无效的请求对象
-32601 METHOD_NOT_FOUND 方法不存在
-32602 INVALID_PARAMS 无效的参数
-32603 INTERNAL_ERROR 内部错误
-32000 SERVER_ERROR 通用服务器错误
-32001 AGENT_ERROR Agent 执行错误
-32002 TOOL_ERROR 工具执行错误
-32003 TIMEOUT_ERROR 执行超时
-32004 NOT_REGISTERED 客户端未注册

🤖 Agent 系统

Agent 自动发现

服务器启动时自动扫描 agent/agents/ 目录,发现所有 BaseAgent 子类并注册:

# agent/registry.py
registry.auto_discover()  # 自动发现并实例化所有 Agent

已实现的 Agent

Agent ID 类名 说明
cad CADAgent CAD 绘图/建模/标注助手,使用通用 BaseAgent 图
component_replacement ComponentReplacementAgent 电气元件替换工作流,自定义多步骤状态图

BaseAgent 图结构

通用 Agent 使用的 LangGraph 图:

START → call_llm → (检查是否有工具调用)
           │                    │
           ▼                    ▼
          END          process_tools → (interrupt 客户端工具)
                                │
                                ▼ (resume)
                          call_llm → ...

ComponentReplacementAgent 工作流

电气元件替换的多步骤有状态工作流:

START → 步骤1: 确认替换明细
          │
          ▼
        步骤2: 确认目标厂家 → (搜索厂家数据库)
          │
          ▼
        步骤3: 确认目标系列 → (搜索系列数据库)
          │
          ▼
        自动执行替换 → END

每个步骤循环执行 LLM调用 → 工具处理 → 状态更新,直到满足步骤完成条件后自动推进。

自定义 Agent

继承 BaseAgent 并实现必要方法:

from agent.base import BaseAgent

class MyAgent(BaseAgent):
    def get_agent_id(self) -> str:
        return "my_agent"

    def get_system_prompt(self) -> str:
        return "你是一个专业的助手..."

    def get_tools(self) -> list:
        # 返回内置工具列表(可选)
        return []

    # 可选:覆盖 create_graph() 实现自定义工作流
    # 可选:覆盖 get_llm_config() 使用不同的 LLM

将文件放入 agent/agents/ 目录即可自动注册。

🔧 工具系统

内置工具(服务端执行)

工具名 说明
get_current_time 获取当前服务器时间
calculator 执行基本数学运算
search_manufacturer_tool 模糊搜索电气元件厂商
search_series_tool 模糊搜索元件系列
batch_search_series_tool 批量搜索元件系列

客户端工具(远程执行)

客户端在 agent.register 时注册的工具,LLM 调用时通过 agent.toolCall 通知客户端执行。 工具定义遵循 MCP 协议格式(name / description / inputSchema),服务端自动转换为 OpenAI 格式。

MCP 工具

通过 mcp_servers.json 配置外部 MCP 服务器,启动时自动连接并加载工具:

{
  "mcpServers": {
    "dx2-mcp": {
      "command": "python",
      "args": ["path/to/dx2-mcp/main.py"],
      "env": {},
      "agents": ["component_replacement"]
    }
  }
}

agents 字段指定哪些 Agent 可以使用该 MCP 服务的工具。

🌐 REST API

POST /api/batch-replace — 批量元件型号替换

根据一组替换示例(old → new),利用 LLM 推导规律并批量替换:

请求:

{
  "old": "NDM2-63/3200 ln=32A",
  "new": "NXM-63H/3200 32A",
  "tasks": ["NDM2-100/3200 ln=25A", "NDM2-100M/3340 ln=63A"]
}

响应:

{
  "results": [
    { "original": "NDM2-100/3200 ln=25A", "replaced": "NXM-100H/3200 25A" },
    { "original": "NDM2-100M/3340 ln=63A", "replaced": "NXM-100H/3340 63A" }
  ]
}

其他 HTTP 端点

方法 路径 说明
GET / API 信息和可用 Agent
GET /health 健康检查
GET /ready 就绪检查(验证 Agent 已加载)

🛠️ 配置说明

所有配置通过环境变量或 .env 文件设置,由 Pydantic Settings 管理:

配置项 默认值 说明
OPENAI_API_KEY OpenAI 兼容 API 密钥
OPENAI_API_BASE https://api.openai.com/v1 API 基础 URL
MODEL_NAME gpt-4 使用的模型名称
TEMPERATURE 0.01 LLM 温度参数
HOST 127.0.0.1 服务器监听地址
PORT 8999 服务器端口
AGENT_TIMEOUT 60.0 Agent 单次执行超时(秒)
LOG_LEVEL INFO 日志级别
LOG_DIR logs 日志文件目录
LOG_BACKUP_COUNT 30 日志保留天数
MAX_MESSAGE_SIZE 1048576 最大消息大小(字节)

� 主要依赖

依赖包 用途
fastapi Web 框架 & WebSocket
uvicorn ASGI 服务器
langgraph Agent 状态图引擎
langchain-openai OpenAI 兼容 LLM 调用
langchain-core LangChain 核心抽象(Tool / Message)
langchain-mcp-adapters MCP 工具适配器
mcp Model Context Protocol 客户端
pydantic 数据验证和序列化
pydantic-settings 配置管理
websockets WebSocket 支持

🔍 使用示例

Python 客户端

import asyncio
import websockets
import json

async def test_agent():
    uri = "ws://localhost:8999/v1/ws?session_id=test-001"

    async with websockets.connect(uri) as ws:
        # 1. 注册
        await ws.send(json.dumps({
            "jsonrpc": "2.0",
            "method": "agent.register",
            "params": {"client_id": "python-client", "agent_id": "cad", "tools": []},
            "id": 1
        }))
        print("注册响应:", await ws.recv())

        # 2. 发送消息
        await ws.send(json.dumps({
            "jsonrpc": "2.0",
            "method": "agent.chat",
            "params": {"message": "现在几点了?"},
            "id": 2
        }))

        # 3. 接收消息循环
        while True:
            msg = json.loads(await ws.recv())
            print("收到:", msg)

            if msg.get("method") == "agent.toolCall":
                # 处理工具调用...
                pass
            elif msg.get("method") == "agent.response":
                print("最终响应:", msg["params"]["content"])
                break

asyncio.run(test_agent())

🔐 安全建议

  1. API 密钥安全: 使用 .env 或环境变量,不要提交到版本控制
  2. WebSocket 认证: 生产环境添加 Token 验证机制
  3. HTTPS / WSS: 生产环境使用加密连接
  4. CORS 配置: 生产环境应限制 allow_origins 为具体域名
  5. 速率限制: 添加请求频率限制
  6. 输入验证: JSON-RPC 层已内置 Pydantic 参数验证

📄 许可证

MIT License

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors