feat(agent): complete EvoAgent integration for all 6 agent roles

Migrate all agent roles from Legacy to EvoAgent architecture:
- fundamentals_analyst, technical_analyst, sentiment_analyst, valuation_analyst
- risk_manager, portfolio_manager

Key changes:
- EvoAgent now supports Portfolio Manager compatibility methods (_make_decision,
  get_decisions, get_portfolio_state, load_portfolio_state, update_portfolio)
- Add UnifiedAgentFactory for centralized agent creation
- ToolGuard with batch approval API and WebSocket broadcast
- Legacy agents marked deprecated (AnalystAgent, RiskAgent, PMAgent)
- Remove backend/agents/compat.py migration shim
- Add run_id alongside workspace_id for semantic clarity
- Complete integration test coverage (13 tests)
- All smoke tests passing for 6 agent roles

Constraint: Must maintain backward compatibility with existing run configs
Constraint: Memory support must work with EvoAgent (no fallback to Legacy)
Rejected: Separate PM implementation for EvoAgent | unified approach cleaner
Confidence: high
Scope-risk: broad
Directive: EVO_AGENT_IDS env var still respected but defaults to all roles
Not-tested: Kubernetes sandbox mode for skill execution
This commit is contained in:
2026-04-02 00:55:08 +08:00
parent 0fa413380c
commit 16b54d5ccc
73 changed files with 9454 additions and 904 deletions

View File

@@ -37,22 +37,41 @@
## 当前架构
仓库目前处于“模块化单体 -> 拆分服务”的迁移阶段,本地开发默认走 split-service 路径。
仓库目前使用 **split-service 运行时模型** 进行本地开发,这是默认支持的运行路径。
当前 app surface
### 运行时 vs 设计时
- `backend.apps.agent_service`,端口 `8000`:控制面,负责 workspaces、agents、skills、审批接口
- `backend.apps.trading_service`,端口 `8001`:只读交易数据接口
- `backend.apps.news_service`,端口 `8002`:只读 explain/news 接口
- `backend.apps.runtime_service`,端口 `8003`:运行时生命周期接口
- `backend.apps.openclaw_service`,端口 `8004`:只读 OpenClaw facade
- WebSocket gateway端口 `8765`:前端实时事件和 feed 通道
- **runtime** — 活跃的执行层scheduler、gateway、pipeline、实盘运行期间的审批
- **run** — 一次具体的执行实例(`runs/<run_id>/`
- **design-time** — 启动特定 runtime 之前的配置和控制面概念
- **workspace** — `agent_service` 暴露的设计时注册表(`workspaces/`
当前最关键的主链路是:
### 服务表面
`frontend -> runtime_service/control APIs -> gateway/runtime manager -> market service + pipeline + storage`
| 服务 | 端口 | 职责 |
|------|------|------|
| `backend.apps.agent_service` | `:8000` | workspaces、agents、skills 和 guard/approval API 的控制面 |
| `backend.apps.trading_service` | `:8001` | 只读交易数据 API |
| `backend.apps.news_service` | `:8002` | 只读 explain/news API |
| `backend.apps.runtime_service` | `:8003` | 运行时生命周期 API |
| `backend.apps.openclaw_service` | `:8004` | 只读 OpenClaw facade |
| WebSocket gateway | `:8765` | 前端实时事件/feed 通道 |
迁移背景可参考 [services/README.md](./services/README.md)。
### 活跃运行时路径
```
frontend -> runtime_service/control APIs -> gateway/runtime manager -> market service + pipeline + storage
```
运行时状态存储在 `runs/<run_id>/` — 这是 **运行时唯一真相源**`workspaces/` 目录是 **设计时注册表**,不是运行时执行路径。
### 文档
- [docs/current-architecture.md](./docs/current-architecture.md) — 权威架构事实
- [services/README.md](./services/README.md) — 服务边界和迁移详情
- [docs/current-architecture.excalidraw](./docs/current-architecture.excalidraw) — 架构图
- [docs/development-roadmap.md](./docs/development-roadmap.md) — 下一步执行计划
- [docs/terminology.md](./docs/terminology.md) — 术语规范指南
---
@@ -112,6 +131,9 @@ MODEL_NAME=qwen3-max-preview
# 长期记忆(只有启用 --enable-memory 才需要)
MEMORY_API_KEY=
# 实验性:将选定的 analyst / risk 角色切换到 EvoAgent
EVO_AGENT_IDS=
```
说明:
@@ -119,6 +141,23 @@ MEMORY_API_KEY=
- live 模式必须配置 `FINNHUB_API_KEY`
- `POLYGON_API_KEY` 用于长期 market store 的补数和刷新
- `MEMORY_API_KEY` 仅在启用长期记忆时需要
- `EVO_AGENT_IDS` 目前支持 analyst 角色以及 `risk_manager``portfolio_manager`,用于分阶段灰度发布
特定 EvoAgent 灰度目标的冒烟测试:
```bash
python3 scripts/smoke_evo_runtime.py --agent-id fundamentals_analyst
```
该脚本启动临时运行时,验证 gateway 日志包含选定的 `EvoAgent`,检查 `runtime_state.json`,验证审批唤醒路径,然后停止运行时。
你也可以将其包含在本地发布检查中:
```bash
./scripts/check-prod-env.sh --smoke-evo
```
未设置 `EVO_AGENT_IDS` 时,此发布检查默认运行 `fundamentals_analyst``risk_manager``portfolio_manager` 的冒烟路径。
如果要用更接近生产的本地启动方式,也可以直接执行:
@@ -157,9 +196,13 @@ python -m uvicorn backend.apps.agent_service:app --host 0.0.0.0 --port 8000 --re
python -m uvicorn backend.apps.trading_service:app --host 0.0.0.0 --port 8001 --reload
python -m uvicorn backend.apps.news_service:app --host 0.0.0.0 --port 8002 --reload
python -m uvicorn backend.apps.runtime_service:app --host 0.0.0.0 --port 8003 --reload
# 兼容性 gateway 路径,不是推荐的主要开发入口
python -m backend.main --mode live --host 0.0.0.0 --port 8765
```
仓库里部署脚本使用的 `production` 只是一个示例 run label不应再把它理解成
系统规定的根目录运行目录名。
### 4. 使用 CLI 运行回测或实盘
回测:
@@ -205,7 +248,10 @@ unzip ret_data.zip -d backend/data
- 每次 run 的状态写入 `runs/<run_id>/`
- `runs/<run_id>/BOOTSTRAP.md` 保存该 run 的 bootstrap 值和 prompt body
- `runs/<run_id>/state/runtime_state.json` 保存运行时快照
- `runs/<run_id>/team_dashboard/*.json` 主要是给 dashboard 用的兼容导出层,不是唯一真相源
- `runs/<run_id>/team_dashboard/*.json` 主要是给 dashboard 用的兼容导出层,不是运行时唯一真相源
- 在受控环境里可通过 `ENABLE_DASHBOARD_COMPAT_EXPORTS=false` 关闭这层兼容 JSON 导出,而不影响 runtime state 持久化
遗留的根级目录如 `live/``production/``backtest/` 应被视为历史兼容性产物,不是新工作的默认运行时位置。
可选保留策略:
@@ -231,7 +277,7 @@ VITE_TRADING_SERVICE_URL=http://localhost:8001
VITE_WS_URL=ws://localhost:8765
```
如果不配置,前端会本地默认值和兼容回退逻辑运行
如果未设置这些变量,前端会回退到本地默认值和兼容性路径
---
@@ -302,7 +348,7 @@ trigger_time: "09:30"
enable_memory: false
```
初始化一个 run 工作区
初始化一个 run 运行资产目录
```bash
evotraders init-workspace --config-name my_run
@@ -324,7 +370,7 @@ evotraders/
│ └── cli.py # Typer CLI 入口
├── frontend/ # React + Vite 前端
├── shared/ # 拆分服务共用 client 和 schema
├── runs/ # run 状态和 dashboard 导出
├── runs/ # run-scoped 状态和 dashboards
├── data/ # 长期研究数据
└── services/README.md
```