# JinRong · 金融四 Agent 智能管家 四个 Agent(客户财富 / 代理人助手 / 数据分析 / **风控监测**)共用统一数据层与合规底座;Agent 之间**不互调 LLM**,跨 Agent 协作走 L1/L2/L3 画像与预警表。 > **当前工作分支:`merger`**(2026-09-08 已完成 AL-09 合并接线:风控模块 + 宿主 Wave 0 共存)。历史交付分支 `risk-control-agent` 已冻结;合并记录见《合并注意事项》执行记录一节。 ## 你是哪种后续人员? | 角色 | 先读 | | --- | --- | | 新 Agent / 统筹开发 | [docs/memory/MEMORY.md](docs/memory/MEMORY.md) §0 → [docs/memory/TODO.md](docs/memory/TODO.md) | | 搭公共 REST API / 前端 | [docs/项目管理/04-从需求到公共API开发方法.md](docs/项目管理/04-从需求到公共API开发方法.md) | | 查阅 AL-09 合并记录 | [docs/项目框架设计/合并注意事项-风控模块并入main.md](docs/项目框架设计/合并注意事项-风控模块并入main.md)(§执行记录) | | 了解需求 / 做方案评审 | [docs/PRD/PRD-风控监测Agent.md](docs/PRD/PRD-风控监测Agent.md)(v1.1)+ [附-风控规则表.md](docs/PRD/附-风控规则表.md) | | 起环境跑演示 | [docs/项目框架设计/演示SOP-风控模块.md](docs/项目框架设计/演示SOP-风控模块.md) + 本页「快速启动」 | ## 项目状态(截至 2026-09-08) **AL-09 合并接线完成**:JWT 统一 · 模块 chat/agent/memory 恢复 · auth_adapter 接缝 · **502 passed, 1 skipped**(`python -m pytest`)。核心接口实调此前已通过。 **下一步(统筹 P1):** Core 公共 API v0.1 · 接口契约发群 · 前端 `web/` init。 | 里程碑 tag | 内容 | | --- | --- | | Wave 0 / T-04 / T-03 / T-21 | JWT 鉴权 · 审计中间件 · chat 闭环 · LangGraph+DeepSeek · Core 只读 Tool · 输入防护 · Milvus 知识库 | | `risk-m1` | 适当性校验(已换核为 C×R 矩阵契约:match_result 五值 + JR-AST/FM 规则编号) | | `risk-m2` | 事件线全链路(RISK-001~005 规则引擎 / 预警聚合 / L3 / AML / 交易网关 / 4 个 API) | | `risk-m3` | 对话线闭环(风控四只读 Tool + StateGraph risk 分支) | | 阶段一 | 对齐 main 基准 AL-01~08(SUIT-001~008 退役 → core_ro.check_suitability 矩阵判定) | | `risk-m4` | 追加需求:FR-8 集中度预警 RISK-006 / FR-9 处置时效升级 RISK-007 / FR-10 代理人行为链 RISK-008 | **前端接入面(2026-09-08 补齐,后端侧已齐)**:方案 B 会话管理三端点(`8328c24`)+ 方案 C SSE 流式对话(`01ec5fc`)。同步端点 `POST /api/chat` 契约不变,前端可任选同步/流式。详见下文「前端接入契约」。 **架构定位(AL-09 后):** 宿主 `app/gateway/` 与模块 `app/api/deps.py` **双栈并存**;对外登录/token **统一**(`/api/auth/login` → `issue_dev_token`);模块 API 禁止 import gateway。接缝 S2 用 `auth_adapter.module_auth_from_host`。详见《[风控Agent模块边界与合并接缝标注.md](docs/项目框架设计/风控Agent模块边界与合并接缝标注.md)》。 ## 铁律(改码前必记) - Core 正式 C1~C5 不可被画像覆盖;Core 库只读(仅模拟交易网关可 INSERT core_trade) - 审计表(audit_log 等)只 INSERT - 代理人草稿不自动外发客户;风控不自动冻户 - 仅适当性 R-02 可阻断交易 - 四 Agent 不互调 LLM - 不改表结构(改表需用户确认);新增依赖须用户确认 ## 后端结构 ```text app/ ├── api/ # auth、chat(含 sessions/stream)、risk(4 API)、simulate、deps、auth_adapter、audit_middleware ├── service/ # agent_service(LangGraph StateGraph)、risk/*(rules/engine/alert/aml/L3/C4~C6)、 │ # suitability、tool_service、auth_service、input_guard、RAG 三层 ├── tool/ # core_tools(Core 只读 Tool)、kb_tools(知识库检索 Tool) ├── gateway/ # trade_gateway 模拟交易网关(唯一可写 core_trade) ├── model/ # schemas、suitability(21 列契约)、entities(29 表 ORM 参考) ├── repository/ # core_ro(Core 只读,含 check_suitability 矩阵)、risk_repository、session_repository ├── config/ # settings(双库 + risk_* 阈值 + JWT) └── utils/ # trace、authz、response(统一错误体)、db、exceptions scripts/ # core 灌库、demo 演示数据、kb 知识库入库、cron 定时扫描、dev 签发 token tests/ # 36+ 模块;502 用例 1 skipped;test_module_boundary.py 锁模块边界 data/kb/ # 6 只种子产品手册(知识库语料) ``` ## 环境要求 - **Python 3.13**(项目依赖与 pytest 装在系统 Python 3.13.14) - MySQL 8.0(双库:`jinrong_core` 模拟 Core 只读 / `jinrong_agent` 业务库)、Redis 8 - Neo4j Desktop(全图同步)、Ollama(bge-m3,1024 维,仅做 embedding) - Windows 原生部署,不使用本地 Docker(见技术选型文档) ## 快速启动 ```bash cp .env.example .env # 填 MYSQL_PASSWORD / NEO4J_PASSWORD / DEEPSEEK_API_KEY pip install -r requirements.txt # 首次灌库与同步:见 docs/memory/FLOW.md §0(权威步骤) uvicorn app.main:app --reload # → GET http://127.0.0.1:8000/health python -m pytest # 基线 502 passed, 1 skipped(系统 Python 3.13.14) ``` **演示库重灌(走查/集成测试前必做,两步缺一不可)**: `scripts/core/reset.ps1`(交互式输密码)→ `scripts/demo/prepare_risk_demo.sql`。 ⚠️ 只跑第一步不跑第二步 → 33 客户中 27 人风评过期、约 82% 适当性检查返回 risk_expired,这是种子设计不是 bug。 **调接口(JWT 通道)**: ```bash # 签发 token(dev) python scripts/dev/issue_dev_token.py --sub STAFF-90001 --roles risk_officer # 调用须同时带两个头 curl -X POST http://127.0.0.1:8000/api/risk/suitability/check \ -H "Authorization: Bearer " -H "X-Agent-Type: risk" \ -H "Content-Type: application/json" \ -d '{"customer_id":"CUST-1001","product_id":"PROD-005827"}' ``` dev 环境无 Bearer 时可用 `X-Debug-Role` / `X-Debug-Actor` 头兜底(仅 development + 未配 RS256 公钥时生效)。 ## 核心接口一览 | 接口 | 说明 | 权限 | | --- | --- | --- | | `GET /api/risk/alerts` | 预警台账分页(FR-4) | risk_officer / risk_manager(只读)/ compliance(仅 aml) | | `POST /api/risk/alerts/{id}/handle` | 人工处置(状态机 + 审计) | risk_officer | | `POST /api/risk/suitability/check` | 适当性校验(C×R 矩阵,G-01 归属) | customer 本人 / advisor 名下 / risk_officer | | `POST /api/risk/aml/scan` | 手动全量 AML 扫描(FR-5) | risk_officer | | `POST /api/simulate/trade` | 模拟交易(适当性阻断 + 规则引擎) | risk_demo 或客户本人 | | `POST /api/chat` | 对话(X-Agent-Type 分流四 Agent;风控线四只读 Tool) | 按准入矩阵 | | `GET /api/chat/sessions` | 会话列表(本人 + 本 Agent 线,分页) | 按准入矩阵 | | `GET /api/chat/sessions/{id}/messages` | 会话历史消息(seq_no 升序分页) | 仅本人会话 | | `POST /api/chat/sessions/{id}/close` | 关闭会话(active→closed) | 仅本人会话 | | `POST /api/chat/stream` | **SSE 流式对话**(OpenAI 兼容 chunk) | 按准入矩阵 | > 对话线(含上述全部 `/api/chat*`)**仅 risk_officer**:`risk_manager` 放行 HTTP 台账只读(`GET /api/risk/alerts`),进对话线一律 403(PRD 4A.1 冻结口径)。 ## 前端接入契约 **1)会话管理(方案 B)** ```bash curl "http://127.0.0.1:8000/api/chat/sessions?limit=20&offset=0" \ -H "Authorization: Bearer " -H "X-Agent-Type: risk" # → {"items":[{session_id,agent_type,customer_id,title,status,created_at,...}],"total":2,"limit":20,"offset":0} curl "http://127.0.0.1:8000/api/chat/sessions//messages?limit=50&offset=0" ... # → {"session_id":"...","items":[{seq_no,role,content,has_disclaimer,created_at}],"total":4,...} ``` **2)流式对话(方案 C,OpenAI 兼容 chunk)** ``` 首帧 data: {"id":"","object":"chat.completion.chunk", "choices":[{"delta":{"role":"assistant"},"finish_reason":null}], "meta":{"session_id":"sess-…","trace_id":"…","has_disclaimer":true, "disclaimer":"以上内容由 AI 生成,仅供业务参考,不构成投资建议。"}} 中间 data: {…,"choices":[{"delta":{"content":"文本块"}}]} 结束 data: {…,"choices":[{"delta":{},"finish_reason":"stop"}],"meta":{"has_disclaimer":true}} data: [DONE] 异常 data: {"error":{"code":"STREAM_FAILED|PERSIST_FAILED","message":"…"}} → data: [DONE] ``` 前端须知: - **免责声明由首帧 `meta.disclaimer` 下发,前端需常驻渲染**(customer/risk 线合规要求);落库文本仍按原口径拼在尾部 - `401/403/404/409/429/400` 在流开始前返回**普通 JSON**,只有正常流才是 `text/event-stream` - 断连/生成异常 = 整轮消息不落库(Tool 留痕仍可审计),前端需提示重试 - 心跳帧未做:长生成空隙靠反代 `proxy_read_timeout` 兜(已知遗留) ## 文档地图 | 目录 / 文件 | 内容 | | --- | --- | | [docs/memory/](docs/memory/) | 项目记忆六件套(MEMORY/TODO/REQUIREMENTS/FRAMEWORK/FLOW/ENVIRONMENT),入口为 MEMORY.md §0 | | [docs/PRD/](docs/PRD/) | 风控 PRD v1.1(§4A = 追加需求)+ 风控规则表 | | [docs/项目框架设计/](docs/项目框架设计/) | 架构设计 · 开发计划 · 实现方案 C4~C6 · 表设计(SQL 单一事实源)· 技术选型与 JWT 手册 · Core 模拟底座 · 演示 SOP · 边界标注 · **合并注意事项** | | [docs/项目管理/](docs/项目管理/) | 项目计划 · **04 开发方法**(需求→API 主线)· 表设计字典 | | [docs/需求拆解/](docs/需求拆解/) | 业务场景优先级、数据交互矩阵、合规约束、四角色用户故事(docx) | | [docs/业务记忆管理/](docs/业务记忆管理/) | 业务记忆分层手册 | ## 前端 React 19 + Vite 7 + TypeScript strict + Ant Design 5 + HashRouter——`web/` 目录尚未 init,为下一主线。 后端接入面已就绪,前端只需三件事:① `POST /api/chat/stream` 接 SSE(首帧拿 `session_id`/`disclaimer`,逐帧拼 `delta.content`,收到 `[DONE]` 收尾);② 进页面先 `GET /api/chat/sessions` 拉会话列表、选中后 `GET .../messages` 拉历史;③ 结束会话调 `POST .../close`。所有请求带 `Authorization: Bearer` + `X-Agent-Type`。