Skip to main content

dev-guide

lc-agent 框架 和 lc-agent-bfzs 演示项目的开发指南。 编写、修改、运行这两个项目代码时必须遵循此 Skill。

Source facts

Repository
ydf0509/lc-agent
Last source activity
September 14, 2026 at 08:26
Detected SKILL.md language
Chinese
Stars
6
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
dev-guide
description
lc-agent 框架 和 lc-agent-bfzs 演示项目的开发指南。 编写、修改、运行这两个项目代码时必须遵循此 Skill。
# 注意: 严格禁止ai自动修改此文件添加临时不重要的一次性细节。 未获用户明确要求,AI 不得修改本文件及 .agents/skills/ 下的任何 skill。 # lc-agent 开发指南 ## 1. 项目关系 | 项目 | 路径 | 角色 | PyPI 包名 | |------|------|------|-----------| | **lc-agent** | `D:\codes\lc-agent` | 框架(被导入使用) | `lc-agent-app` | | **lc-agent-bfzs** | `D:\codes\lc-agent-bfzs` | 基于框架的演示应用 | `lc-agent-bfzs` | - lc-agent 提供:Web UI、Agent 引擎、MCP 管理、Skills 加载、工具注册、持久化、WebSocket 流式输出 - bfzs 只写业务逻辑:自定义工具、自定义 Agent Graph、Skills、配置 ## 2. 环境 ``` Python 解释器: D:\ProgramData\Miniconda3\envs\py312\python.exe Node.js: 系统 PATH 中的 node/npm Frontend: D:\codes\lc-agent\frontend (Vue 3 + Vite) bfzs 端口: 8001 lc-agent 默认: 8000 ``` 安装方式: ```powershell # 框架需要可编辑安装 cd D:\codes\lc-agent && pip install -e ".[dev,desktop]" # bfzs 是应用项目,不需要 pip install,直接 python 运行 # 入口: D:\codes\lc-agent-bfzs\bfzs\main.py ``` ## 3. 目录结构 ### lc-agent 框架 ``` lc_agent/ ├── __init__.py # 公开 API: LcAgentApp, set_config_path, get_config, tool, ToolRegistry ├── app.py # LcAgentApp 主编排器 ├── main.py # CLI 入口 (lc-agent 命令) ├── desktop.py # pywebview 桌面客户端(独立启动) ├── config/ │ ├── loader.py # JSONC 配置加载 + {env:VAR} 替换 │ ├── runtime.py # 全局配置单例: set_config_path / get_config / get_app_name / get_database_url │ ├── utils.py # get_config_value 点路径读取 + 默认值常量 │ └── schema.py # Pydantic 配置 schema ├── core/ │ ├── engine.py # AgentEngine — create_agent + 预设 + 流式 │ ├── chat_model.py # ChatOpenAIReasoning (提取 reasoning_content) │ ├── models.py # AgentPreset, ModelInfo 数据模型 │ └── http_trace*.py # HTTP 请求追踪 ├── tools/ │ ├── registry.py # ToolRegistry 单例 + @tool 装饰器 │ └── builtin.py # 内置工具(如有) ├── mcp/ │ ├── manager.py # McpManager — 连接/管理 MCP 服务器 │ └── tool_adapter.py # MCP schema → LangChain StructuredTool ├── skills/ │ ├── filtered_loader.py # Skills 运行时开关(enable/disable) │ └── scanner.py # Skills 目录扫描 ├── server/ │ ├── app.py # FastAPI 工厂 + 静态文件挂载 │ ├── websocket.py # ChatWebSocketHandler │ ├── dependencies.py # FastAPI DI │ └── routes/ # REST API: health, models, tools, agents, sessions, skills, mcp ├── db/ │ ├── engine.py # async SQLite + Alembic 自动迁移 │ ├── models.py # SQLModel 表定义 │ ├── repository.py # 数据访问层 │ └── migrations/ # Alembic 版本 └── web/dist/ # 前端构建产物(npm run build 输出) frontend/ # Vue 3 前端源码 ├── src/ │ ├── App.vue │ ├── views/ChatView.vue # 主聊天界面 │ ├── stores/ # Pinia: chat, sessions, agents, tools │ ├── api/ # http.ts (REST), websocket.ts (WS) │ ├── components/ │ │ ├── chat/ # ToolCallCard, TokenUsage, HttpTrace, ChatBubble... │ │ ├── layout/ # AppHeader, LeftSidebar, RightPanel │ │ ├── panels/ # ToolGroupPanel, ModelSelector, TodoList │ │ └── dialogs/ # AgentEditorDialog │ └── router/index.ts ├── package.json └── vite.config.ts # 代理 /api → :8000, /ws → ws://:8000 (开发bfzs需改8001) ``` ### lc-agent-bfzs 演示应用 ``` D:\codes\lc-agent-bfzs/ ├── config.jsonc # LLM、DB、MCP、Skills 配置 ├── pyproject.toml # 依赖: lc-agent ├── bfzs/ │ ├── main.py # 入口: 加载配置→导入工具→创建App→注册Agent→run │ ├── tools/ │ │ ├── file_tools.py # [file_mgmt] 文件管理 │ │ └── data_tools.py # [data_analysis] 数据分析 │ └── agents/ │ └── research_agent.py # 自定义 LangGraph 研究助手 ├── myskills/ # 自定义 SKILL.md 文件 ├── bfzs_data.db # SQLite 数据 (运行时生成) └── bfzs_checkpoints.db # LangGraph checkpoint (运行时生成) ``` ## config.jsonc 中 model_id 和 raw_model_id区别 - `model_id` 是 给供应商+原始模型名字起的唯一别名名字,前端使用这个。 - `raw_model_id` 是 实际请求模型供应商http接口的模型ID,实际请求服务时候用的raw_model_id。 ## 4. 开发模式和常用操作 ### 4.1 新增工具 (在 bfzs 项目) ```python # bfzs/tools/my_new_tools.py from lc_agent import tool @tool(group="my_group", group_description="我的工具组显示名") def my_function(param1: str, param2: int = 10) -> str: """工具的描述 — 会展示给 LLM 看,要写清楚用途和参数含义。 Args: param1: 参数1说明 param2: 参数2说明 """ # 业务逻辑 return "结果字符串" ``` 然后在 `bfzs/main.py` 中添加 import: ```python import bfzs.tools.my_new_tools # noqa: F401 ``` **规则:** - `group` 必须是 ASCII `^[a-zA-Z0-9_-]+$` - `group_description` 写中文显示名 - 函数 docstring 是 LLM 看到的工具描述,务必清晰 - 工具名最终为 `{group}__{func_name}` ### 4.2 新增自定义 Agent (在 bfzs 项目) ```python # bfzs/agents/my_agent.py from typing import Annotated, TypedDict from langchain_core.messages import AIMessage from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages class MyState(TypedDict): messages: Annotated[list, add_messages] # ... 其他状态字段 def build_my_agent(): """构建自定义 Agent Graph:直接写代码,不读配置。""" from langchain_openai import ChatOpenAI # 按需换自己的模型类 llm = ChatOpenAI(model="...", api_key="...") # 写死或读环境变量 async def node_a(state: MyState) -> dict: resp = await llm.ainvoke(state["messages"]) return {"messages": [AIMessage(content=resp.content)]} graph = StateGraph(MyState) graph.add_node("node_a", node_a) graph.add_edge(START, "node_a") graph.add_edge("node_a", END) return graph.compile() ``` 在 `bfzs/main.py` 注册: ```python from bfzs.agents.my_agent import build_my_agent app.add_agent(name="my_agent", graph=build_my_agent(), description="描述") ``` 想复用 `config.jsonc` 里配好的模型时,用 `resolve_model(model_id)` 一行拿连接参数 (`raw_model_id` / `base_url` / `api_key` / `provider`),不用自己翻配置: ```python from lc_agent import resolve_model info = resolve_model("my-model-id") # config 省略时自动用全局配置 llm = ChatOpenAI(model=info.raw_model_id, base_url=info.base_url, api_key=info.api_key) ``` (框架内部约定:`model_id` 只是前端别名,请求一律发 `raw_model_id`。) ### 4.3 修改框架核心 (在 lc-agent 项目) 常见修改点: | 目标 | 文件 | |------|------| | 新增 REST API | `lc_agent/server/routes/` 新建文件定义 `router = APIRouter()`,然后在 `server/app.py` 中 import 并 `include_router` | | 修改 WebSocket 协议 | `lc_agent/server/websocket.py` | | 修改 Agent 构建逻辑 | `lc_agent/core/engine.py` | | 新增数据库表 | `lc_agent/db/models.py` (启动时自动 Alembic 迁移) | | 修改配置解析 | `lc_agent/config/loader.py` + `runtime.py` + `schema.py` | | 修改 MCP 集成 | `lc_agent/mcp/manager.py` | ### 4.5 新增前端组件 ``` frontend/src/components/ ├── chat/ # 聊天相关 (消息气泡内的元素) ├── layout/ # 布局 (Header, Sidebar) ├── panels/ # 面板 (工具列表, 模型选择) └── dialogs/ # 对话框 ``` ## 5. 运行项目 ### 启动 bfzs (常规方式) ```powershell cd D:\codes\lc-agent-bfzs D:\ProgramData\Miniconda3\envs\py312\python.exe -u -m bfzs.main --port 8001 ``` ### 使用 restart-bfzs skill (推荐) 当修改了前端或后端代码后,使用 `restart-bfzs` skill 来重建前端并重启服务。 ### 仅编译前端 (不重启 Python) ```powershell cd D:\codes\lc-agent\frontend && npm run build ``` ### 运行测试 ```powershell cd D:\codes\lc-agent D:\ProgramData\Miniconda3\envs\py312\python.exe -m pytest tests/ -v ``` - "测试通过"必须看到 `N passed` 汇总行才算数,exit 0 不算(曾有仓库根遗留 `pytest.py` 劫持 `python -m pytest`,只打印 5 行依赖检查就 exit 0) - 仓库根严禁放与常用工具同名的 .py(pytest.py / conftest.py 等,会因 cwd 优先被当模块加载) - 若 pytest 输出异常为空,先确认没有同名劫持文件;结果可 `--junitxml` 或落盘再读 ### 6.3 三值权限过滤 Agent Preset 的 `allowed_tool_groups` / `allowed_mcp_servers` / `allowed_skills`: - `None` = 全部允许 - `[]` = 全部禁止 - `["a", "b"]` = 只允许指定的 ### 6.4 Agent 的三种创建方式 | 方式 | 来源 | 存储 | 构建逻辑 | Middleware | |------|------|------|----------|-----------| | **内置预设** | 框架代码 | 无需存储 | `engine.build_agent()` | 框架自动添加 | | **用户网页创建** | Web UI 编辑 | SQLite `agent_presets` 表 | `engine.build_agent()` | 框架自动添加 | | **用户代码创建** | Python 代码 | 无(内存) | 用户自己构建 graph | **用户完全控制** | #### 内置预设(硬编码在框架中) | ID | display_name | 行为 | |----|--------------|------| | `chat` | 普通对话 | 纯聊天,无工具 | | `empty` | 空模板 | 默认不启用工具 | | `power` | 全功能 | 默认启用所有工具 | #### 用户网页创建的预设 用户在 Web UI 中创建/编辑的 Agent Preset,存入 SQLite 数据库。 启动时从 DB 加载,走 `build_agent()` 创建,享有框架自动添加的 middleware。 #### 用户代码创建的 Agent 通过 `app.add_agent(name, graph, description)` 注册自定义 LangGraph: ```python app.add_agent(name="my_agent", graph=my_compiled_graph, description="描述") ``` - graph 可以来自 `create_agent`、`create_deep_agent`、或手动 `StateGraph().compile()` - 框架**不会**往用户 graph 里添加任何 middleware - 用户需要自行管理上下文裁剪、工具、权限等 ## 7. LangChain/LangGraph 代码规范 **重要:** 写 LangChain 相关代码时: 1. 禁止使用 AI 预训练的过时语法,要使用2026年最新的语法。 2. 必须用 `docs-langchain` 和 `reference-langchain` MCP 查询最新用法 3. 如有必要,用 `nbrag` MCP 搜索 `langchain_ai_codes_and_docs` 知识库 4. 可以直接读 `D:\ProgramData\miniconda3\envs\py312\Lib\site-packages\` 下的源码 ### 当前版本关键 API ```python # Agent 创建 (langchain >= 1.0) from langchain.agents import create_agent from langchain.agents.middleware import TodoListMiddleware from langchain.agents.middleware.summarization import SummarizationMiddleware # LangGraph (>= 0.4) from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver # Chat Model from lc_agent.core.chat_model import ChatOpenAIReasoning # Skills from langchain_agentskills import SkillsToolkit from langchain_agentskills.loaders import DirectorySkillLoader, CompositeSkillLoader ``` ## 8. 数据库 | 用途 | bfzs 路径 | 引擎 | |------|-----------|------| | 应用数据 (sessions, presets, messages) | `D:\codes\lc-agent-bfzs\bfzs_data.db` | async SQLite via SQLModel | | LangGraph checkpoint | `D:\codes\lc-agent-bfzs\bfzs_checkpoints.db` | AsyncSqliteSaver | - 无需手动迁移,启动时 Alembic 自动处理 - 项目可以破坏性修改 schema,无需兼容旧数据 - 如 schema 改动大,可以删除 .db 文件重新启动。**但必须先询问用户确认!** 数据库中存有用户配置的 Agent preset,删库意味着丢失所有配置,重建很麻烦 ### 8.2 数据库旧表加字段时候的注意事项 给已有表新增字段时,**必须写正式 Alembic revision**,同时改 SQLModel 表定义,两者缺一不可: 1. `lc_agent/db/models.py` — 修改表模型加字段(Python 侧) 2. `lc_agent/db/migrations/versions/` — 新建 revision 文件,`down_revision` 指向当前 head 3. NOT NULL 新列必须带 `server_default`;模型侧空串默认值写 `server_default=text("''")`(纯 `""` 会被兜底补列逻辑拼出非法 DDL) 4. 验证:跑覆盖该表的测试即可(fixture 在全新库上执行完整迁移链) `_add_missing_columns` 只是启动时的幂等兜底,不能替代正式 revision。 ## 9. 常见陷阱 1. **别在框架里写业务逻辑** — 工具、Agent、Skills 都应该在 bfzs 项目中 2. **前端修改后要 build** — `npm run build` 输出到 `lc_agent/web/dist/`,否则后端静态文件还是旧的 3. **Python 解释器** — 必须用 `D:\ProgramData\Miniconda3\envs\py312\python.exe` 4. **bfzs 工作目录** — 启动 bfzs 时 cwd 必须是 `D:\codes\lc-agent-bfzs`(因为 config.jsonc 中的相对路径基于此) 5. **MCP 服务器** — 类型分 `local`(subprocess)、`sse`、`http`(streamable HTTP) 6. **LiteLLM** — bfzs 通过 LiteLLM 代理访问各家 LLM,默认 `http://localhost:4000/v1` 7. **新增功能前先查生态** — 见下方"架构原则" 8. **禁止在 Python 文件顶部写 `from __future__ import annotations`** — 此语句会把当前模块所有函数注解变为惰性字符串,LangChain 的 `@tool` / `@lc_tool` 装饰器在构建 Pydantic schema 时调用 `get_type_hints()`,会在全局作用域解析注解字符串,导致函数内局部变量(如动态生成的 `Field(description=...)` 引用)报 `NameError`。Python 3.12 无需此语句,项目内已有该语句的文件可以直接删除。 ## 10. 架构原则:优先复用 LangChain 生态 **新增功能时,必须优先检查 langchain/langgraph/deepagents 生态是否已有现成实现,而不是手动从零造轮子。** 已有的成功案例: | 功能 | 来源(非自研) | 包 | |------|---------------|-----| | Agent 创建 | `create_agent` | `langchain` | | TodoList | `TodoListMiddleware` | `langchain.agents.middleware` |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub