# agent-workbench **Repository Path**: LLS312885991/agent-workbench ## Basic Information - **Project Name**: agent-workbench - **Description**: 基于 LangChain/LangGraph 的 Agent 开发工作台框架:开发者只写业务逻辑,流式对话、工具调用、计划列表、人机交互(模型反问/审批/表单/文件上传)、会话持久化、事件回放、评估与追踪开箱即用。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-13 - **Last Updated**: 2026-09-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: langchain, langgraph, agents, human-in-the-loop, workbench ## README # AgentWorkbench — LangChain/LangGraph Agent 开发工作台框架 > **开发者只写 Agent 业务逻辑,对话工作台开箱即用。** > > 📘 **文档** > - [docs/tutorial.md](docs/tutorial.md) —— 从零开发教程:报销助手实战,覆盖提问交互 / 文件产出 / 评估 / 部署 > - [docs/architecture.md](docs/architecture.md) —— 框架架构与技术文档:模块职责、运行时序、数据模型、扩展指南 > - [docs/frontend.md](docs/frontend.md) —— 前端组件与事件渲染指南:数据流、组件职责、如何扩展事件展示与卡片 基于 LangGraph + LangChain 的工作台框架:你按照业务开发 Agent(工具调用、数据库访问、审批、计划……),框架负责其余一切 —— 会话管理、SSE 流式输出、消息持久化、完整的聊天前端(计划列表、工具卡片、审批/表单交互、事件流观测、流程执行视图),无需写任何前端代码。 ## 核心特性 | 能力 | 说明 | | --- | --- | | 零前端成本 | 开发完 Agent 即可在工作台直接对话,`npm run build` 后由后端单端口托管 | | 流式对话 | token 级流式输出(LLM 与非 LLM 节点均支持) | | 工具调用展示 | 实时展示调用中/成功/失败状态,入参与结果可展开 | | 计划(Plan)列表 | Agent 状态中的 `plan` 通道自动渲染为实时计划卡片 | | 人机交互 | `human.approve / ask_text / choose / form / ask_file` 一行代码向用户提问(审批/输入/单选多选/表单/文件上传),支持默认值 + 倒计时超时自动提交;`make_ask_tools()` 让模型自主决定何时反问用户 | | 文件产出 | `emit_file("报告.md", content)` 一行产出文件,前端出现可下载的文件卡片(刷新后仍可回放下载) | | 办公文档解析 | PDF/Word 附件自动提取全文注入模型;Excel 自动注入**结构摘要**(sheet/表头/样例),`make_office_tools()` 让模型按需深查明细行 | | 知识库(RAG) | 按 Agent 隔离的知识库存储与轻量检索(2-gram 评分,零外部依赖),`make_knowledge_tools(agent)` 生成检索工具供模型开箱使用 | | 会话导出 | 聊天区一键导出完整会话为 Markdown(含思考/工具调用/附件与产出文件链接) | | 暗色主题 | 头部一键切换亮/暗,跟随系统偏好,持久化保存 | | 大会话分页 | 默认渲染最近 60 条消息,顶部「加载更早的消息」逐步加载,切换会话自动重置 | | LLM-as-judge 评估 | 评估用例支持 `judge` 要点,关键词断言通过后由模型按要点打分(未配 Key 自动跳过) | | 断线恢复 | 运行中连接中断后自动凭 run_id 轮询续读事件,无需刷新 | | 会话持久化 | LangGraph checkpointer(SQLite 默认,可切 Postgres),刷新/重启不丢会话 | | 运行中止 | 运行中输入框变为红色停止按钮,点击即取消当前运行(SSE 以 `run_finished{cancelled}` 终止,已完成节点状态保留) | | 事件流观测 | 完整协议事件落库(**连续 delta 自动合并,避免记录爆炸**),前端可回放 | | 图执行视图 | 记录节点开始/结束事件,前端点开即可看到流程节点执行到哪里 | | 多 Agent | `agents/` 下每个包一个 Agent,自动发现注册,工作台左侧切换 | ## 架构 ``` ┌────────────────────────── 你要写 ──────────────────────────┐ │ agents//agent.py 业务工具、LangGraph 图 │ │ @agent(name=...) 装饰器注册(返回未编译 StateGraph) │ └──────────────────────────┬─────────────────────────────────┘ │ 注册发现(懒构建 + 注入 checkpointer) ┌──────────────────────────▼─────────────────────────────────┐ │ agentworkbench(框架服务端) │ │ registry Agent 自动发现 / 注册 │ │ persistence LangGraph checkpointer(SQLite / Postgres) │ │ events 流转码器:LangGraph 内部流 -> UI 协议事件 │ │ eventstore 事件流落库(delta 合并 + 边界批量写) │ │ human interrupt 助手:approve/ask_text/choose/form │ │ server FastAPI:REST 会话管理 + SSE 运行流 + 静态托管 │ └──────────────────────────┬─────────────────────────────────┘ │ REST + SSE(稳定 JSON 协议,snake_case) ┌──────────────────────────▼─────────────────────────────────┐ │ web/(React 工作台,完全通用,不感知任何 Agent 代码) │ │ 会话列表 · 流式消息 · 工具卡片 · 计划卡片 · 审批/表单 · │ │ 事件流抽屉 · 图流程执行视图 │ └────────────────────────────────────────────────────────────┘ ``` ## 获取与安装 本框架以**源码仓库**方式使用:你 fork/clone 本仓库,在 `agents/` 目录里写自己的 业务 Agent,工作台随之交付。 要求:Python 3.10+(建议 3.12)、Node.js 18+(仅首次构建前端需要)。 ```bash # 1. 获取代码(GitHub 或 Gitee 镜像) git clone https://github.com//agent-framework.git cd agent-framework # git clone https://gitee.com//agent-framework.git # 2. 安装框架(仓库根目录) pip install -e . # 或使用 uv: uv venv --python 3.12 .venv && VIRTUAL_ENV=.venv uv pip install -e . # 3. 构建前端(一次性;后续也可以在 web/ 下用 npm run dev 热更新开发) cd web && npm install && npm run build && cd .. # 4. 配置模型(离线演示 Agent 无需任何 Key;可选) copy .env.example .env # 编辑 .env 填入 AWB_API_KEY 等 # 5. 启动 awb dev # 开发模式(agents 目录改动自动重载) # 或 awb start # 生产模式 ``` > 没有安装 Node?两个替代方案: > 1. 直接下载 CI 构建产物 —— GitHub 仓库的 Actions 运行结果页有 `web-dist` > 产物,下载解压为 `web/dist/` 即可,跳过本地前端构建; > 2. 使用 Docker(容器内自动构建前端):`docker compose up -d`。 打开 :首页是 Agent 卡片选择页,点击卡片进入对应 Agent 的对话界面(点头像处 Agent 名或侧栏品牌可返回首页)。 - 选择 **离线演示助手(无需模型)** 发送任意消息 —— 它会完整演示流式输出、工具调用、计划列表、审批卡片、表单卡片、事件流与流程视图,全程不需要 LLM Key。 - 配置好模型后选择 **智能演示助手**,体验真实的 ReAct Agent(计划维护、订单数据库查询、下单审批)。 ### 双平台 CI - GitHub 走 [GitHub Actions](.github/workflows/ci.yml):pytest(3.11/3.12 矩阵) + 前端类型检查/构建,构建产物以 `web-dist` artifact 上传; - Gitee 镜像走 [Gitee Go](.workflow/ci.pipeline.json)(首次需在仓库「流水线」 页启用该配置),执行同样的测试与构建。 ## 开发你的第一个 Agent 在 `agents/` 下建一个包,框架自动发现。**最小可用只需十几行:** ```python # agents/my_agent/agent.py from langchain_core.messages import AIMessage from langchain_core.tools import tool from langgraph.graph import END, START, StateGraph from agentworkbench import agent from agentworkbench.state import WorkbenchState @tool def query_order(order_id: str) -> str: """按订单号查询订单状态(工具的 docstring 会作为 LLM 的工具说明)""" return f"订单 {order_id}:已发货" def chat(state: WorkbenchState): # 这里写你的业务逻辑:调用 LLM、访问数据库、编排流程…… return {"messages": [AIMessage(content="你好,我是业务助手。")]} @agent(name="my_agent", title="业务助手", description="我的第一个业务 Agent") def _build(): graph = StateGraph(WorkbenchState) graph.add_node("chat", chat) graph.add_edge(START, "chat") graph.add_edge("chat", END) # 注意:返回未编译的 StateGraph,框架会自动注入会话持久化并编译 return graph ``` 重启 `awb dev`(或等自动重载),工作台左侧即可看到新 Agent。 ### 使用 LLM(ReAct 工具调用) ```python from langgraph.prebuilt import create_react_agent from agentworkbench import agent, get_checkpointer from agentworkbench.llm import get_chat_model # 读取 .env 的 AWB_MODEL_* 配置 def _build(): llm = get_chat_model(temperature=0) return create_react_agent( llm, tools=[query_order], state_schema=WorkbenchState, checkpointer=get_checkpointer(), # 预置图是已编译的,需显式接入持久化 ) ``` ### 计划列表 Agent 状态中的 `plan` 通道会自动渲染为前端计划卡片: ```python # 节点里直接写状态 def step(state: WorkbenchState): return {"plan": [ {"content": "查询订单", "status": "completed"}, {"content": "生成报告", "status": "in_progress"}, ]} ``` LLM Agent 可以提供一个 `update_plan` 工具,让模型自主维护计划(见 `agents/assistant_demo/tools.py`)。 ### 产出文件 在任意节点或工具内一行代码产出文件,前端聊天区会出现「产出文件」卡片,可直接下载(刷新后依然可从历史回放中下载): ```python from agentworkbench import emit_file def step(state): emit_file("演示订单报告.md", "# 报告\n...", mime="text/markdown") # 写盘 + file 协议事件 return {...} ``` 文件保存在 `/files//`,通过 `GET /api/threads/{id}/files/{name}` 下载,`GET /api/threads/{id}/files` 列出全部产出。 ### 反馈事件(notify 助手) 除文件外,还可以在节点/工具内一行代码推送常见反馈事件: ```python from agentworkbench import emit_warning, emit_progress, emit_sources, emit_task emit_warning("知识库索引较旧,结果可能滞后") # 前端黄色提示条(4s 自动消失) emit_progress(45, "已完成 45%") # 输入框上方进度条 emit_sources([{"title": "文档A", "url": "https://..."}]) # 引用来源列表 emit_task("sub-1", "生成报告", "running") # 子任务状态(流程面板/事件流可见) ``` 推理模型的深度思考(DeepSeek-R1 / Anthropic thinking 等)由框架自动识别为 `thinking_*` 事件,前端渲染为可折叠的「深度思考」区;每次运行的 token 用量 与时长由框架自动统计为 `usage` 事件,展示在消息流底部。 ### 人机交互(审批 / 输入 / 单选多选 / 表单 / 文件上传) 在**任意节点或工具内**一行代码向用户提问:节点挂起,前端弹出对应交互卡片, 用户提交后图从挂起点恢复(回答自动回显为一条用户消息,刷新后依然可见): ```python from agentworkbench import human ok = human.approve("将删除该订单,确认执行?") # -> bool city = human.ask_text("请补充收货城市") # -> str mode = human.choose("配送方式", ["标准", "次日"]) # 单选 -> str tags = human.choose("费用类型", ["交通", "餐饮", "办公"], multi=True, default=["办公"], timeout=30) # 多选 -> list[str] info = human.form("完善订单", fields=[ # -> dict {"name": "receiver", "label": "收件人", "type": "text", "required": True}, {"name": "shipping", "label": "时效", "type": "select", "options": ["标准", "次日"]}, {"name": "gift", "label": "礼品包装", "type": "confirm"}, ]) invoice = human.ask_file("请上传发票", accept="image/*,.pdf") # -> {"name","url","mime","size"} ``` **默认值与超时**:`approve / ask_text / choose` 支持 `default=` 与 `timeout=`(秒)。 配置后前端显示倒计时,超时未答或用户点「跳过」即按默认值自动提交——适合 "长时间无人处理时走兜底路径"的业务流。表单字段可用 `default` 预填, 所有必填字段均有默认值时支持整单超时提交。 ### 模型自主提问(Agent 反问用户) 除了在固定位置调用 `human.*`,还可以把 `make_ask_tools()` 生成的工具交给 ReAct Agent——**何时提问、问什么由模型自主决定**:模型发现缺少关键信息时 调用 `ask_user`,框架挂起执行并在前端弹出输入卡片,用户的回答作为工具结果 流回模型继续推理(前端零改动): ```python from agentworkbench import agent, get_checkpointer, make_ask_tools from agentworkbench.llm import get_chat_model from langgraph.prebuilt import create_react_agent def _build(): return create_react_agent( get_chat_model(), tools=[*你的业务工具, *make_ask_tools()], # ask_user + ask_user_choice state_schema=WorkbenchState, prompt="……缺少必要信息时,先用 ask_user 向用户提问,不要猜测……", checkpointer=get_checkpointer(), ) ``` 效果示例:用户说"帮我查天气"→ 模型发现缺城市 → 调用 `ask_user("请问要查询哪个城市?")` → 前端弹出输入卡片 → 用户回答"杭州" → 模型继续调用 `get_weather`。 ### Generative UI 提问卡(自定义提问形态) 内置五种提问之外的形态——比如让用户拖滑块设预算、在商品列表里勾选——用 `human.ask_card` + 前端注册组件实现(详见 [docs/frontend.md](docs/frontend.md)): ```python # Agent 侧:交互形态由前端注册的组件决定,回答以 dict 返回 budget = human.ask_card("budget_slider", {"min": 0, "max": 1000}, default={"value": 300}, timeout=30) ``` ```tsx // 前端:组件实现 display(只读)与 ask(可交互,onSubmit 提交即恢复运行)双态 defineCard({ type: "budget_slider", render: BudgetSlider, askable: true }); ``` 组件统一注册表、按 `mode` 双态渲染;`default`/`timeout` 倒计时策略与内置提问一致。 完整示例见 `offline_demo` 的数量选择滑块(`quantity_selector`)。 ### 办公文档解析(PDF / Word / Excel) 用户上传的文档附件**自动解析并注入模型消息**: - **PDF / Word(.docx)**:提取全文(含表格)内联,默认上限 20000 字符(`AWB_ATTACH_DOC_MAX` 可调) - **Excel(.xlsx)**:注入**整簿结构摘要**——每个 sheet 的名称、行列数、表头行与样例行,模型看一眼就懂布局 需要模型**按需深查** Excel 明细时,加上内置工具: ```python from agentworkbench.office_tools import make_office_tools tools=[*你的工具, *make_office_tools()] # excel_summary(file) —— 整簿结构摘要 # excel_read_rows(file, sheet?, start_row?, max_rows?) —— 按 sheet 读取明细行 # document_text(file) —— 提取 PDF/Word 全文 ``` 工具通过运行配置自动定位当前会话的文件(附件与 Agent 产出都在其中), 解析失败会以错误文本返回给模型自行处理。底层解析函数在 `agentworkbench.office`(`pdf_text` / `docx_text` / `excel_summary` / `excel_sheet_rows`),业务 Agent 可直接复用。 ### 知识库(RAG,按 Agent 隔离) 每个 Agent 拥有独立知识库(`/knowledge//`),上传的文档 自动提取文本、切片建索引;Agent 通过内置检索工具获取相关片段: ```python from agentworkbench.knowledge_tools import make_knowledge_tools tools=[*你的工具, *make_knowledge_tools("my_agent")] # 绑定本 Agent 的知识库 ``` 管理接口: | 方法 | 路径 | 说明 | | --- | --- | --- | | POST | `/api/agents/{agent}/knowledge` | 上传文档(multipart,txt/md/csv/json/pdf/docx/xlsx) | | GET | `/api/agents/{agent}/knowledge` | 列出已索引文档 | | DELETE | `/api/agents/{agent}/knowledge/{name}` | 移除文档 | 检索基于字符 2-gram 重叠评分(中文友好、零外部依赖);数据量增大后可替换 为向量后端,工具接口保持不变。 ### 用户上传附件(模型可感知内容) 用户随消息上传的附件**不再只是文件名**——框架会把文件内容组装进模型消息: - **文本类**(代码/配置/文档,如 py/ts/json/csv/md…):内容内联注入消息 (默认上限 6000 字符,超出截断并注明); - **图片**:构建多模态视觉块(base64 data URL),支持视觉的模型可直接"看图"; - **二进制**(pdf/zip 等):保留文件名占位,不注入内容。 相关配置: | 环境变量 | 默认 | 说明 | | --- | --- | --- | | `AWB_ATTACH_IMAGES` | `auto` | 图片视觉块注入:`auto`(deepseek 系纯文本模型跳过)/ `on` / `off` | | `AWB_ATTACH_TEXT_MAX` | `6000` | 单个文本附件注入的最大字符数 | | `AWB_ATTACH_IMAGE_MAX_BYTES` | `3500000` | 图片注入的最大字节数 | 注入内容仅进入模型上下文;前端气泡展示与历史回放自动剥离注入块, 附件仍以缩略图/类型卡片呈现。`ask_file` 上传的文件不自动注入, Agent 代码内用 `artifacts.load_text(thread_id, meta["name"])` 读取。 ### 流式输出 LLM 的 token 天然流式。非 LLM 节点也可以用自定义流输出进度文本: ```python from langgraph.config import get_stream_writer def step(state): writer = get_stream_writer() writer("正在扫描数据库...") # 前端按流式文本渲染 return {...} ``` ### 运行中止 运行中输入框会变为红色停止按钮,点击即取消当前运行(SSE 以 `run_finished{cancelled:true}` 终止;已完成的节点状态保留在检查点中, 会话可以继续对话)。 ### 断线恢复 运行中若网络中断(非主动中止),前端自动凭 `run_id` 轮询 `GET /threads/{id}/events/poll?run_id=…&after_seq=…` 续读已落库事件, 恢复实时渲染直至运行结束;期间界面提示「连接中断,正在恢复运行状态…」。 ## 事件流与流程观测 - **事件流抽屉**(聊天区右上角「事件流」):打开会话即加载持久化事件,实时事件持续追加;点击单行展开完整 JSON。 - **存储策略**:`message_delta` / `tool_args_delta` 按消息/调用合并为单条记录(带 `merged` 计数),并在边界事件(工具结束、计划更新、节点结束等)处批量落库 —— 存储量是 **O(消息+工具+节点)** 而不是 O(token)。已测试:7 条逐字增量 → 1 条存储记录。 - **执行流程弹窗**(「执行流程」按钮):React Flow + dagre 自动布局渲染图拓扑,结合 `node_started/node_finished` 事件标注每个节点的 等待/运行中/已完成/失败/等待输入 状态与执行次数。节点因 interrupt 挂起时会标记为「等待输入」。 ### 深度追踪(Langfuse / LangSmith) 产品内的事件流面向使用者;面向开发者的 prompt 级追踪用纯环境变量接入,零代码: ```env # Langfuse(开源可私有部署;需 pip install langfuse) AWB_LANGFUSE_PUBLIC_KEY=pk-xxx AWB_LANGFUSE_SECRET_KEY=sk-xxx # LangSmith(LangChain 原生识别,零依赖) LANGSMITH_TRACING=true LANGSMITH_API_KEY=lsv2_xxx ``` 每次运行的完整 prompt、模型返回、工具调用、token 与耗时自动上报到对应平台,适合调试回答质量、定位慢环节与统计成本。 ## CLI 命令 | 命令 | 说明 | | --- | --- | | `awb dev` | 开发模式(agents 目录改动自动重载) | | `awb start` | 生产模式(可加 `--host` / `--port`) | | `awb new ` | 脚手架:生成最小可跑的 Agent 包(agents//) | | `awb eval ` | 运行评估数据集(失败退出码非 0,可接 CI) | | `awb schema` | 导出协议 JSON Schema(`-o` 写文件),前后端契约的单一事实源 | ## REST / SSE 协议 前端与服务端之间是稳定协议(字段全部 snake_case),你完全可以替换/复用前端。 ### REST | 方法 | 路径 | 说明 | | --- | --- | --- | | GET | `/api/agents` | Agent 列表 | | GET | `/api/agents/{name}/graph` | 图拓扑(节点/边) | | POST | `/api/threads` | 创建会话 `{agent}` | | GET | `/api/threads?agent=` | 会话列表 | | PATCH | `/api/threads/{id}` | 改名 `{title}` | | DELETE | `/api/threads/{id}` | 删除会话(含检查点与事件流) | | GET | `/api/threads/{id}/messages` | 历史消息(工具结果折叠进 `tool_calls`)+ 当前计划 + 挂起的交互 | | GET | `/api/threads/{id}/files` | 会话产出文件列表 | | GET | `/api/threads/{id}/files/{name}` | 下载产出的文件 | | POST | `/api/threads/{id}/runs` | 运行:`{message}` 新消息 / `{resume}` 恢复交互 → **SSE 事件流** | | POST | `/api/threads/{id}/cancel` | 取消运行 | | GET | `/api/threads/{id}/events?run_id=` | 持久化事件流(合并后) | ### SSE 事件(`POST /runs` 响应流,每帧 `data: {json}`) | type | 载荷 | 说明 | | --- | --- | --- | | `run_started` | `run_id, input{kind, preview?}` | 运行开始 | | `message_started` | `id, role` | 消息开始 | | `message_delta` | `id, delta` | 文本增量 | | `message_finished` | `id` | 消息结束 | | `tool_started` | `call_id, name, args` | 工具调用开始 | | `tool_args_delta` | `call_id, args_delta` | 工具入参流式增量 | | `tool_finished` | `call_id, status, result, duration_ms` | 工具结果与执行耗时 | | `plan_updated` | `items[{content,status}]` | 计划更新 | | `thinking_started / thinking_delta / thinking_finished` | `id, delta` | 推理模型的深度思考过程(前端折叠区展示) | | `file` | `file{name,size,mime,url}` | Agent 产出文件(可下载) | | `message_images` | `id, images[url]` | 消息携带的图片 | | `usage` | `input/output/total_tokens, models, duration_ms` | 运行用量与时长统计 | | `warning` | `message` | 警告提示(黄灯,不中断运行) | | `progress` | `value(0-100), text?` | 任务进度条 | | `sources` | `sources[{title,url}]` | 引用/来源列表 | | `task_update` | `task_id, name, status, parent_id?` | 子任务/子代理状态 | | `node_started` / `node_finished` | `name, (task_id / status)` | 图节点执行进度 | | `interrupt` | `id, payload{kind, default?, timeout?, ...}` | 人机交互请求(kind: approve/text/choose/form/file) | | `custom` | `data` | 开发者自定义透传 | | `error` | `message` | 运行出错(流内报错,不断流) | | `run_finished` | `cancelled?` | 运行结束(终止事件) | 存储版事件额外带 `run_id / seq / created_at`,且连续增量合并为一条(含 `merged` 计数)。 ## 目录结构 ``` agent-framework/ ├── agentworkbench/ # 框架包(pip install -e . 后 import agentworkbench) │ ├── config.py # 环境变量配置 │ ├── registry.py # Agent 注册与自动发现 │ ├── state.py # WorkbenchState(messages + plan) │ ├── persistence.py # checkpointer 生命周期(SQLite/Postgres) │ ├── protocol.py # UI 事件协议定义 │ ├── events.py # LangGraph 流 -> 协议事件 转码器 + 历史序列化 │ ├── eventstore.py # 事件流存储(delta 合并、批量落库) │ ├── human.py # interrupt 助手(approve/ask_text/choose/form/ask_file + make_ask_tools) │ ├── office.py / office_tools.py # PDF/Word/Excel 解析与内置 office 工具 │ ├── llm.py # 按环境变量构建聊天模型 │ ├── cli.py # awb dev / awb start │ └── server/ # FastAPI 应用与路由 ├── agents/ # ← 你的 Agent 业务代码都在这里 │ ├── offline_demo/ # 离线演示(无需模型 Key,覆盖全部工作台能力) │ ├── expense_demo/ # 报销助手(教程配套:文件/表单/多选/审批 + 默认值倒计时) │ └── assistant_demo/ # LLM 演示(ReAct + 计划工具 + 下单审批) ├── docs/ │ ├── tutorial.md # 从零开发教程(报销助手实战) │ ├── architecture.md # 框架架构与技术文档 │ └── frontend.md # 前端组件与事件渲染指南 ├── web/ # 通用前端工作台(React + Vite + TS,流程图用 React Flow + dagre 自动布局) ├── tests/ # pytest:注册/会话/流式协议/恢复/事件存储/图拓扑 └── .env.example ``` ## 配置 | 环境变量 | 默认 | 说明 | | --- | --- | --- | | `AWB_MODEL_PROVIDER` | `openai` | 模型提供商(openai / anthropic / openai 兼容端点…) | | `AWB_MODEL` | `gpt-4o-mini` | 模型名 | | `AWB_API_KEY` / `OPENAI_API_KEY` | - | API Key | | `AWB_API_BASE` | - | OpenAI 兼容自定义端点(如 DeepSeek) | | `AWB_HOST` / `AWB_PORT` | `127.0.0.1` / `8000` | 服务监听 | | `AWB_AGENTS_DIR` | `./agents` | Agent 扫描目录 | | `AWB_HOME` | `./.workbench` | 运行数据目录(meta/事件/演示库) | | `AWB_DATABASE_URI` | - | 切换 Postgres 持久化(需 `pip install -e ".[postgres]"`) | | `AWB_AUTH_TOKENS` | - | API 访问令牌(逗号分隔多个)。配置后 `/api/*` 要求 `Authorization: Bearer `(或 `?token=`),前端自动弹出令牌输入门;静态页面不受限 | | `AWB_ATTACH_IMAGES` | `auto` | 消息附件图片注入为视觉块:`auto`/`on`/`off` | | `AWB_ATTACH_TEXT_MAX` | `6000` | 单个文本附件注入模型的最大字符数 | | `AWB_ATTACH_DOC_MAX` | `20000` | PDF/Word 附件全文注入的最大字符数 | | `AWB_ATTACH_IMAGE_MAX_BYTES` | `3500000` | 单个图片附件注入的最大字节数 | ## 评估(awb eval) 评估数据集见 `evals/*.json` 与教程第 9 节。支持三类断言:关键词 `contains/not_contains`、交互回答序列 `auto_resumes`、以及 **LLM-as-judge** 要点打分(`"judge": ["要点"]`,需配置模型 Key,未配置自动跳过)。 任意用例失败退出码非 0,可直接接入 CI 作为回归门槛。 ## 测试 ```bash pip install -e ".[dev]" pytest tests -q ``` 23 个用例覆盖:Agent 发现注册、会话 CRUD、SSE 协议事件(消息/工具/计划/中断)、interrupt 恢复、提问增强(多选/默认值/文件回答)、模型自主提问工具链路、流式工具入参聚合(分片回归)、访问认证、事件落库与 delta 合并、事件查询过滤、图拓扑、运行取消。 ## Roadmap - 多租户与用户体系(当前为共享令牌的简单认证) - 提问增强后续:多问题并行挂起、服务端超时(当前超时由前端倒计时驱动) - 运行队列与异步任务后端(当前单会话单运行,进程内取消) - 前端自动化测试(当前以后端 pytest + 手工验收为主)