Files
ZY-Agent/apps/README.md
1445043649 4cd2acc192 feat(apps): 新增 headless(API Key) 多租户冒烟测试,并登记进 apps/README
multi_tenant.py 的「server-to-server / 无人值守」版:每个租户先由人类 owner
(cookie 会话)建 service account 并 mint 一把 workspace-scoped key
(POST /api/v1/service-accounts → POST /api/v1/api-keys,plaintext 仅返回一次),
之后所有对话只用 Authorization: Bearer dfk_live_...(独立 Session,免 cookie/CSRF)。

除并发 / 多轮上下文 / 租户隔离(同 cookie 版)外,额外校验两条 headless 专属性质:
- scope 强制:缺 runs:create 的 key 发起 stream 返回 403
- 撤销即失效:DELETE /api/v1/api-keys/{id} 后该 key 立即 401

对 :8001 实跑(DF_TENANTS=4 DF_TURNS=10)全绿。同时更正 apps/README 中
「API Key 鉴权尚未接入」的过时说明。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 20:45:37 +08:00

7.2 KiB
Raw Permalink Blame History

apps/ — 基于 DeerFlow 的应用

这个目录用于存放消费 DeerFlow 智能体能力的上层应用。每个应用一个子文件夹。

为什么放在这里

DeerFlow 的代码有一条严格的依赖方向(见根 CLAUDE.md):

backend/packages/harness/deerflow/   ← 可发布的 Agent 框架(deerflow.*
backend/app/                         ← Gateway / IM 通道(app.*
apps/                                ← 你的应用(消费 deerflow,不反向依赖)  ← 本目录

规则:app 可以依赖 deerflowdeerflow 不能依赖 app / apps。本目录放在 backend/ 之外、与 frontend/ 平级,天然符合这条边界。

两种集成模式

模式 适用场景 怎么连 示例
HTTP GatewayREST+SSE 上层是别的服务 / 多语言 http://localhost:2026/api/* examples/http-chat/
内嵌 DeerFlowClient 上层本身是 Python,进程内直接当 SDK 调 from deerflow.client import DeerFlowClient examples/embedded-chat/

还有第三种:LangGraph SDKlanggraph_sdk.get_client(url=".../api")graph id lead_agent),用于接入 LangGraph 生态工具链。需要的话照 HTTP 示例的鉴权流程拿 cookie 即可。

运行示例(每个示例自带 run.sh

# ① HTTP 模式:需要先起 Gatewaydev-gateway 或 dev-full 都行)
#    run.sh 会自动探测网关地址:优先 :2026,回退 :8001
./apps/examples/http-chat/run.sh
DF_BASE=http://localhost:8001 ./apps/examples/http-chat/run.sh   # 也可手动指定

# ② 内嵌模式:不需要起任何服务,run.sh 自动进 backend uv 环境运行
./apps/examples/embedded-chat/run.sh

http-chat 的 run.sh 优先用 uv run --no-project --with requests(临时环境,不污染系统),没有 uv 才回退到本地 .venv + pip;可用 DF_BASE / DF_EMAIL / DF_PASSWORD 覆盖。embedded-chat 的 run.sh 自动定位 backend/、加载 .env 后用 uv run 启动,依赖 config.yaml 里有可用模型。

多租户并发验证(HTTP 模式)

examples/http-chat/multi_tenant.pyapp.py 的并发 / 多租户版:用 /api/v1/auth/register 并发创建多个租户(每个注册用户自带独立 workspace),各自一个 requests.Session(独立 cookie)同时跑 N 轮链式对话,并校验:① 真并发(对话时间窗重叠);② 多轮上下文按 thread_id 各自保持(第 2 轮起每轮都依赖上一轮结果);③ 租户隔离(POST /api/threads/search 仅见己有线程,跨租户 GET /api/threads/{id} 返回 404)。

# 前提:已起 Gatewaydev-gateway 或 dev-full
DF_BASE=http://localhost:8001 DF_TENANTS=4 DF_TURNS=10 \
  uv run --no-project --with requests python apps/examples/http-chat/multi_tenant.py

环境变量:DF_BASE(网关地址,默认 :8001)、DF_TENANTS(并发租户数,默认 3)、DF_TURNS(每租户轮数,默认 10)。每次运行用唯一邮箱新建租户,可重复跑,不撞 email、也不触发登录限流(/register 不限流;setup-status 全程只调一次以避开 60s/IP 限流)。

多租户验证(Headless / API Key 模式)

examples/http-chat/multi_tenant_headless.py 是上面那个测试的 server-to-server(无人值守) 版,验证 Stage 1 的 API Key 鉴权:每个租户先由一个人类 owner(cookie 会话)建 service account 并 mint 一把 workspace-scoped keyPOST /api/v1/service-accountsPOST /api/v1/api-keys,plaintext 仅返回一次),之后所有对话只用 Authorization: Bearer dfk_live_...(独立 Session、不带 cookie / CSRF)。除并发 / 上下文 / 隔离(同 cookie 版)外,额外校验两条 headless 专属性质:④ scope 强制——一把缺 runs:create 的 key 发起对话返回 403;⑤ 撤销即失效——DELETE /api/v1/api-keys/{id} 后该 key 立即 401。

# 前提:已起 Gatewaydev-gateway 或 dev-full
DF_BASE=http://localhost:8001 DF_TENANTS=4 DF_TURNS=10 \
  uv run --no-project --with requests python apps/examples/http-chat/multi_tenant_headless.py

环境变量同上,外加 DF_EXTRA=0 可跳过 scope / 撤销专项检查。实测(:8001DF_TENANTS=2 DF_TURNS=3)全绿:真并发、多轮上下文保持、跨租户 GET 均 404、只读 key stream 403、撤销后 401。

前置:先把 DeerFlow 跑起来

仓库根目录

make dev          # 起 Gateway(8001) + 前端(3000) + nginx(2026),统一入口 http://localhost:2026

确保 config.yaml 里至少配了一个可用模型 + API key。

本地调试脚本(推荐)

make dev 是前台阻塞运行。日常调试更顺手的是仓库根 scripts/ 下两个生命周期脚本,子命令统一为 start / stop / restart / status / logs / run

脚本 起什么 入口 适合
scripts/dev-gateway.sh 只起 Gateway http://localhost:8001 调后端 API / 接入示例,起得快
scripts/dev-full.sh Gateway + 前端 + nginx http://localhost:2026 连前端一起调,完整体验
./scripts/dev-gateway.sh start          # 后台启动,等就绪后返回
./scripts/dev-gateway.sh status         # PID / 端口 / HTTP 健康检查
./scripts/dev-gateway.sh logs           # tail -f 跟随日志(不影响服务)
./scripts/dev-gateway.sh stop

./scripts/dev-full.sh start             # 全量栈后台启动(首次装依赖)
SKIP_INSTALL=1 ./scripts/dev-full.sh start   # 跳过依赖安装,重启更快
./scripts/dev-full.sh status            # 三服务一览
./scripts/dev-full.sh run               # 前台运行(= make devgateway 带热重载)

环境变量:PORT=(换端口)、NO_RELOAD=1(关热重载,断点更稳)、SKIP_INSTALL=1(全量栈跳过装依赖)。

鉴权(HTTP 模式必读)

Gateway 是 fail-closed 的——除少数公开路径外所有请求都要带会话 cookie:

  1. GET /api/v1/auth/setup-status → 是否还没管理员
  2. 首次 POST /api/v1/auth/initializeJSON {email,password})建第一个管理员;之后 POST /api/v1/auth/login/local表单 username=邮箱 + password
  3. 成功后 Session 里有 access_token(HttpOnly) + csrf_token 两个 cookie
  4. 所有写请求POST/PUT/DELETE/PATCH)必须带 X-CSRF-Token 头 = csrf_token

多租户:浏览器式接入走会话 cookie(每个注册用户即一个独立租户,自带 workspace),并发与隔离可用 multi_tenant.py 验证。无人值守 / 业务后端接入已支持 API KeyStage 1):owner 经 POST /api/v1/service-accounts + POST /api/v1/api-keys mint 一把 key,业务侧用 Authorization: Bearer dfk_live_... 直连(免 cookie / CSRF),端到端示例见 multi_tenant_headless.py

新建一个应用

mkdir apps/my-app
# 放你的代码;HTTP 模式参照 examples/http-chat,内嵌模式参照 examples/embedded-chat