15 KiB
ZK Data Agent
ZK Data Agent 是基于 claw-code-agent 改造的团队通用 Agent 工作台。
它不是一个单点数据工具,也不是只会聊天的 Web UI。这个项目的核心目标是把“通用 Agent 能力”稳定下来:让 Agent 能理解任务、选择 Skill、调用 Tools、读写文件、执行 Python、保留会话、展示工具链路,并把团队反复使用的工作经验沉淀成可维护的能力包。
数据开发、线上挖掘、ELK 查询、数据工场 SQL 查询,都是已经通过 Skill 和 Tools 落地的子能力。
这个项目解决什么
团队日常有很多任务不只是“问模型一句话”:
- 要读文件、查日志、跑 SQL、分析线上数据。
- 要生成中间结果、落盘文件、继续追问和修正。
- 要把某类任务的经验固化下来,下一次让 Agent 按同样的方法做。
- 要让用户看到 Agent 做了什么、调用了什么工具、文件生成在哪里。
- 要让多人共用一套平台,而不是每个人本地各跑一份零散脚本。
ZK Data Agent 做的是这层通用底座。业务能力通过 Skill 和 Tools 逐步沉淀。
核心设计
Agent Loop
Agent 每轮对话不是一次性生成文本,而是一个循环:
用户输入
-> 组装系统提示词、Skill 提示词、会话上下文、工具定义
-> 模型决定直接回复或返回 tool_calls
-> 后端执行对应 tool handler
-> 工具结果写入会话
-> 下一轮模型继续判断
-> 直到输出最终回复、等待用户 review 或被取消
这个循环让 Agent 可以边观察、边执行、边修正,而不是只能一次性回答。
Skill
Skill 是“经验层”。它用 SKILL.md 描述某类任务应该怎样做、什么时候需要用户确认、可以调用哪些工具、产物应该放在哪里。
项目级 Skill 统一放在:
skills/<skill-name>/SKILL.md
Skill 适合承载:
- 工作流程
- 业务边界
- review 门禁
- 工具调用经验
- 输入输出格式约定
- 常见错误和注意事项
Skill 不应该写成大段不可执行代码。稳定、强格式、可复用的能力应该下沉到 Tool。
Tools
Tools 是“执行层”。工具负责稳定地做事情,例如读写文件、执行 Python、查询 parquet、转换 records、导出 JSONL。
主要位置:
src/agent_tools.py
src/agent_tool_specs/
src/data_agent_records.py
src/data_agent_inputs.py
src/data_agent_router_sessions.py
工具适合承载:
- 强格式转换
- 数据校验
- 路径归一
- 线上数据读取
- 账号级 Python 执行环境
- 需要审计和约束的外部调用
原则是:不要长期让 Agent 手写易错脚本来完成稳定流程。能工具化的,尽量工具化。
会话工作区
每个用户、每个会话都有独立目录:
.port_sessions/accounts/<account_id>/sessions/<session_id>/
input/ 用户输入文件
scratchpad/ 临时脚本、中间分析、草稿
output/ 最终产物
session.json 会话历史
会话工作区是这个项目和普通聊天机器人很不一样的地方。Agent 的产物不是散落在项目根目录,而是跟随当前会话保存,方便回看、下载和继续追问。
Review 门禁
一些任务不能让 Agent 一步到位,例如:
- 数据生成目标还不清楚。
- 标签边界存在歧义。
- 线上候选需要人工抽样确认。
- 输出格式会影响训练、评测或对外交付。
这类流程要通过 Skill 和 Tool 实现 review 门禁。目标、计划、候选样本、最终导出都应该分阶段展示给用户确认。
可观测性
Web UI 会展示:
- 当前模型和上下文状态
- Skill 列表和启用状态
- 工具调用过程
- 总结版思考阶段
- 历史会话
- 当前会话输入/输出文件
- 后台运行和刷新恢复状态
目标是让用户知道 Agent 正在做什么,而不是只看到一个黑盒回复。
和 Claude Code 的区别
这个项目继承了 Claude Code 类工具的基本思路:Agent 可以读写文件、执行工具、维护上下文,并围绕一个工作区完成任务。
但当前项目的定位更偏团队内部 Agent 平台:
| 维度 | Claude Code 类工具 | ZK Data Agent |
|---|---|---|
| 使用形态 | 个人本地 CLI/IDE 工作流为主 | 团队共享 Web 服务 |
| 任务范围 | 代码开发为核心 | 通用任务底座,数据开发只是能力之一 |
| 能力沉淀 | 个人 prompt、命令、脚本较多 | 项目级 Skill + Tools 统一管理 |
| 文件空间 | 通常围绕当前代码仓库 | 每个用户/会话独立 input/scratchpad/output |
| 可观测性 | 终端输出为主 | Web UI 展示工具链路、活动、文件、历史 |
| Python 执行 | 常用 shell 自行管理 | 优先 python_exec,走账号级环境和工具约束 |
| 人工确认 | 通常是权限批准或终端交互 | 更强调业务 review:目标、计划、样本、导出 |
| 内部系统 | 需要用户自行接脚本 | 可以通过 Skill/Tools 接 ELK、SQL、线上数据 |
因此,它不是要替代 Claude Code 的个人编码体验,而是把 Agent 变成团队可共享、可扩展、可治理的工作台。
能力目录
通用 Agent 能力
当前底座已经支持:
- OpenAI 兼容模型调用
- Web UI 多会话管理
- 模型选择
- Skill 发现和会话级启用
- 工具调用展示
- 文件输入和会话产物管理
- 后台 run 状态和刷新恢复
- 总结版思考过程展示
- Python 执行和包安装工具
- 用户级 systemd 部署
数据开发能力
Skill:product-data
适用于从产品定义、标签规则、手写边界或示例 query 生成数据集。
典型流程:
输入定义/规则/样例
-> 抽取 generation goal
-> 用户 review
-> 生成 generation plan
-> 用户确认数量、标签、边界、路径
-> 生成 dataset draft text
-> 转换为 canonical records
-> 校验
-> 导出 records.jsonl
默认最终产物:
当前会话/output/records.jsonl
线上挖掘能力
Skill:online-mining
适用于从线上 router session 中按 query 特征、domain、设备、日期等条件挖掘候选样本。
典型流程:
需求/badcase/标签定义
-> 构造挖掘策略
-> profile 数据
-> search 候选
-> sample 抽样 review
-> 策略调整
-> 候选转换为 canonical records
-> 导出 records.jsonl
默认线上数据路径:
/data/online_data/router_session_parquet/date=YYYYMMDD/
重要分支:
- 如果用户要“直接把线上候选作为样本”,只做转换,不生成新 query。
- 如果用户明确要“补充生成/扩写类似 case”,才切换到数据生成链路。
评测修复能力
Skill:eval-repair
用于评测错误分析、错误类型归纳和后续补数流程。目前主要是流程占位和约定沉淀,工具还会继续补齐。
日志查询能力
Skill:elk-fetch
用于按 request id 查询小米内网 ELK 日志,覆盖 NLP 主链路、拒识、免唤醒、小米汽车 OneTrack 等场景。
原则:
- 通过
python_exec执行 skill 内脚本。 - 不让 Agent 直接用
bash python ...绕过工具链路。
数据工场 SQL 能力
Skill:data-factory-sql
用于通过 Kyuubi HTTP API 执行 SQL、轮询状态并下载 CSV 结果。
适用于:
- 用户直接给 SQL。
- 用户要求“跑个 SQL”“数据工场查一下”。
- Agent 基于表结构和字段说明生成 SQL 草稿,再请求用户确认后执行。
团队公约
空间公约
业务任务默认在当前会话空间内工作:
input/ 用户上传或指定的输入材料
scratchpad/ 临时脚本、中间文件、抽样缓存
output/ 最终交付文件
约定:
- 最终产物优先写入当前会话
output/。 - 临时脚本和中间文件写入当前会话
scratchpad/。 - 数据 records 默认导出到逻辑路径
output/records.jsonl,工具会自动路由到当前会话 output。 - 不要把业务任务产物写到项目根目录的
output/、tasks/、src/、skills/。 - 读取外部数据可以用明确路径,但写入外部路径前需要用户明确确认。
- 平台源码目录默认只读。只有用户明确要求开发平台功能时,才修改
src/、frontend/、skills/、scripts/等项目文件。
Skill 公约
项目级 Skill 统一放在:
skills/<skill-name>/SKILL.md
SKILL.md frontmatter 至少包含:
---
name: product-data
description: 简短说明这个 skill 做什么。
when_to_use: 说明什么场景应该触发。
aliases: optional-alias
allowed_tools: read_file, write_file, python_exec
---
维护规则:
- 用中文写主要流程说明,方便团队后续维护。
- Skill 写“怎么做”和“什么时候停下来问用户”。
- 不要把稳定格式转换、校验、复杂查询长期写在 Skill 里,应沉淀为 Tool。
- Skill 如果依赖脚本,脚本放在该 Skill 目录下,并通过
python_exec调用。 - 新增业务 Skill 后,可以在 Web UI Skill 列表中按会话启用或关闭。
Tool 公约
工具是稳定执行边界。
约定:
- 强格式输出必须工具化,例如 canonical records、JSONL 导出、数据校验。
- 需要持久化状态的 review 流程应由工具记录 pending/confirmed 状态。
- Python 分析优先用
python_exec。 - 缺 Python 包时用
python_package。 - 除非没有专用工具,否则不要让 Agent 通过
bash绕过已有工具。
Python 公约
Agent 执行 Python 优先使用:
python_exec
python_package
原因:
- 可以进入账号级 Python 环境。
- 可以把临时脚本和输出放在当前会话 scratchpad。
- Web UI 能看到工具调用过程。
- 后续更容易加超时、取消、审计和资源限制。
Git 公约
不要提交:
.env.deploy.venv/.port_sessions/router_session_parquet/- 用户数据、模型输出、临时任务产物
可以提交:
skills/下经过确认的项目级 Skillsrc/下稳定工具和运行时代码frontend/app/下 Web UI 代码scripts/和deploy/下部署维护脚本- README 中面向团队维护的约定
系统组成
frontend/app/ Next.js Web UI
backend/ FastAPI Web 后端
src/ Agent runtime、提示词、工具实现、会话持久化
skills/ 项目级 Skill,使用 SKILL.md 定义
scripts/ 本地启动、服务器部署、systemd 启动脚本
deploy/systemd/ 用户级 systemd service 模板
.port_sessions/ 本地/服务端运行数据,禁止提交
.env.deploy 本机私有部署配置,禁止提交
前端负责账号、会话列表、模型选择、对话流式展示、活动面板和会话文件面板。
后端负责 Agent loop、OpenAI 兼容模型调用、工具执行、run 状态、会话持久化和数据开发工具。
本地开发启动
首次准备 Python 依赖:
pyenv install 3.10.14
pyenv local 3.10.14
python -m venv .venv
.venv/bin/python -m pip install --upgrade pip setuptools wheel
.venv/bin/python -m pip install -e .
准备前端依赖:
cd frontend/app
npm install
本地启动 Web UI:
bash scripts/start-webui.sh
默认地址:
前端:http://127.0.0.1:3000
后端:http://127.0.0.1:8765
scripts/start-webui.sh 会优先读取 .env.deploy,也可以直接使用当前 shell 里的环境变量:
export OPENAI_API_KEY="..."
export OPENAI_BASE_URL="http://model.mify.ai.srv/v1"
export OPENAI_MODEL="xiaomi/mimo-v2-flash"
停止本地 Web UI:
kill $(cat .port_sessions/webui-frontend.pid) $(cat .port_sessions/webui-backend.pid)
部署和更新
首次部署
推荐把应用部署在用户目录,不需要把代码放到 /opt:
git clone git@git.n.xiaomi.com:wuyang6/zk-data-agent.git "$HOME/zk-data-agent" || true
bash "$HOME/zk-data-agent/scripts/install-from-git.sh"
首次部署会:
- 拉取
main分支。 - 交互式生成
.env.deploy。 - 必要时请求 sudo 安装 Ubuntu 系统依赖。
- 用 pyenv 准备 Python
3.10.14。 - 创建项目
.venv。 - 安装前端依赖并构建。
- 安装并启动用户级 systemd 服务。
.env.deploy 会保存:
OPENAI_API_KEY
OPENAI_BASE_URL
OPENAI_MODEL
CLAW_BACKEND_HOST
CLAW_BACKEND_PORT
CLAW_FRONTEND_HOST
CLAW_FRONTEND_PORT
CLAW_API_URL
该文件包含敏感信息,只保存在部署机器本地,权限设置为 600,并已被 .gitignore 忽略。
日常更新
已经完成首次部署后,普通代码更新使用:
cd "$HOME/zk-data-agent"
bash scripts/update-server-fast.sh
如果改动包含依赖、systemd 模板或部署脚本,使用完整部署脚本:
bash scripts/deploy-ubuntu.sh
部署指定分支:
bash scripts/deploy-ubuntu.sh main
强制覆盖服务器工作区:
bash scripts/deploy-ubuntu.sh main --force
服务管理
部署脚本会安装两个用户级 systemd 服务:
zk-data-agent-backend
zk-data-agent-frontend
查看状态:
systemctl --user status zk-data-agent-backend
systemctl --user status zk-data-agent-frontend
查看日志:
journalctl --user -u zk-data-agent-backend -f
journalctl --user -u zk-data-agent-frontend -f
重启服务:
systemctl --user restart zk-data-agent-backend zk-data-agent-frontend
停止服务:
systemctl --user stop zk-data-agent-backend zk-data-agent-frontend
如果机器要求用户退出 SSH 后服务仍保持运行,可由管理员执行:
loginctl enable-linger <username>
环境要求
Ubuntu 部署建议:
gitbashcurlsystemdpyenv- Python
3.10.14 - Node.js
20或22 npm
首次安装如果缺 Python 编译依赖,可以执行:
bash scripts/deploy-ubuntu.sh --bootstrap-system
--bootstrap-system 会使用 sudo apt-get 安装系统依赖;应用代码、虚拟环境、前端依赖、运行数据和 systemd 用户服务仍然位于当前用户目录。
开发验证
后端基础校验:
.venv/bin/python -m compileall src backend
前端校验:
cd frontend/app
npm run lint
npx tsc --noEmit
npm run build
提交前建议确认:
git status --short
git diff --check
常见问题
Web UI 能打开,但模型调用失败
先检查 .env.deploy:
cat .env.deploy
重点确认:
OPENAI_API_KEYOPENAI_BASE_URLOPENAI_MODEL
然后看后端日志:
journalctl --user -u zk-data-agent-backend -f
systemd 服务找不到 npm
重新执行完整部署脚本:
bash scripts/deploy-ubuntu.sh
脚本会把当前可用的 npm 路径写入 .env.deploy,避免用户级 systemd 读取不到 zsh/nvm 环境。
新增 Skill 后前端看不到
项目级 Skill 放在:
skills/<skill-name>/SKILL.md
确保 frontmatter 至少包含 name、description、when_to_use。Web UI 会通过 /api/claw/skills 读取 Skill 列表。
Agent 产物没有出现在“聊天中的文件”
最终产物必须写入当前会话 output/。数据 records 推荐使用数据工具导出到逻辑路径:
output/records.jsonl
工具会自动路由到当前会话 output 目录。