313 lines
11 KiB
Markdown
313 lines
11 KiB
Markdown
# Agent 组员统一接入说明书
|
||
|
||
> 版本:v1.0
|
||
> 适用对象:客服、投顾、风控及其他业务 Agent 开发人员
|
||
> 阅读要求:组员开发 Agent 前必须完整阅读本文。
|
||
|
||
本文是业务组员接入底座的统一入口,整合了底座启动、Agent 注册、公共执行链、模型、意图、工具、
|
||
适当性、基金行情和提交验收要求。接口字段以《05-接口文档.md》为准,数据库以《00-新数据库基线设计.md》
|
||
和《02-数据库建表设计.md》为准。
|
||
|
||
## 1. 你负责什么,底座负责什么
|
||
|
||
业务 Agent 属于 MVC+S 架构的 Service 层。组员只负责业务意图、业务编排和业务输出,不负责重建公共底座。
|
||
|
||
组员负责:
|
||
|
||
- `AgentDefinition`;
|
||
- 继承 `BaseAgent` 的业务类;
|
||
- `handle()` 内的业务判断和编排;
|
||
- 业务只读工具声明及测试;
|
||
- 注册表登记;
|
||
- 业务边界和权限测试。
|
||
|
||
底座负责:
|
||
|
||
- JWT、RBAC、入口和客户范围校验;
|
||
- 配置快照和记忆召回;
|
||
- 意图分类和低置信处理;
|
||
- 模型路由、密钥引用和 fallback;
|
||
- 工具权限、超时、审计和来源引用;
|
||
- 适当性校验;
|
||
- 合规审查、敏感信息脱敏;
|
||
- 运行持久化、Outbox、SSE 和恢复。
|
||
|
||
业务范围只包括场内基金模拟交易。场外运营必须独立建表、独立接口,不得写入场内交易表。
|
||
|
||
## 2. 接入前提
|
||
|
||
项目使用项目自带虚拟环境(Python 3.13,实测 3.13.5):
|
||
|
||
```powershell
|
||
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
|
||
```
|
||
|
||
复制配置模板并填写本机环境:
|
||
|
||
```powershell
|
||
Copy-Item .env.example .env
|
||
```
|
||
|
||
启动 HTTP 服务和 Worker:
|
||
|
||
```powershell
|
||
.\.venv\Scripts\python.exe -m uvicorn app.main:app --host 127.0.0.1 --port 8099
|
||
.\.venv\Scripts\python.exe -m app.worker
|
||
```
|
||
|
||
数据库迁移只能通过 Alembic:
|
||
|
||
```powershell
|
||
.\.venv\Scripts\python.exe -m alembic upgrade head
|
||
.\.venv\Scripts\python.exe tools\audit_schema.py
|
||
```
|
||
|
||
`.env`、JWT 私钥、模型 API Key 不得提交到 Git。
|
||
|
||
## 3. 定义 Agent
|
||
|
||
`agent_type` 必须使用小写蛇形命名,例如 `customer_service`、`advisor`、`risk`。
|
||
`supported_intents` 列出该 Agent 支持的全部意图;配置中心不能扩大代码中声明的工具上限。
|
||
|
||
```python
|
||
from app.core.contracts import AgentDefinition, AgentRequest, CoreResult, RequestContext
|
||
from app.service.agent.base import BaseAgent
|
||
|
||
|
||
class AdvisorAgent(BaseAgent):
|
||
definition = AgentDefinition(
|
||
agent_type="advisor",
|
||
version="1.0.0",
|
||
allowed_roles=("customer", "advisor", "operator", "admin"),
|
||
allowed_portals=("api",),
|
||
allowed_tools=("query_fund_quote",),
|
||
supported_intents=("fund_quote", "general"),
|
||
)
|
||
|
||
async def handle(self, request: AgentRequest, context: RequestContext) -> CoreResult:
|
||
return CoreResult(text="业务处理结果")
|
||
```
|
||
|
||
业务类只实现 `handle()`。不要覆盖 `execute()`、鉴权、配置、记忆、意图分类、模型、工具或合规方法。
|
||
|
||
## 4. 注册 Agent
|
||
|
||
在 `app/service/agent/bootstrap.py` 的统一注册入口登记:
|
||
|
||
```python
|
||
factory.register(
|
||
AdvisorAgent.definition,
|
||
lambda _context: AdvisorAgent(AdvisorAgent.definition),
|
||
)
|
||
```
|
||
|
||
HTTP 服务和 Worker 使用同一个工厂,不能各自维护注册表。构造器必须返回 `BaseAgent`,且实例的
|
||
`AgentDefinition` 必须与注册定义完全一致。
|
||
|
||
注册完成后必须通过:
|
||
|
||
```powershell
|
||
python -m pytest tests/contract/test_agent_factory_contract.py -q -p no:cacheprovider
|
||
```
|
||
|
||
未注册的 Agent 类型会返回 `404 AGENT_TYPE_NOT_FOUND`。
|
||
|
||
## 5. 公共执行顺序
|
||
|
||
每次运行固定经过:
|
||
|
||
```text
|
||
输入校验
|
||
→ JWT/RBAC/入口/客户范围校验
|
||
→ 读取发布配置
|
||
→ 召回授权记忆
|
||
→ 自动意图分类
|
||
→ 执行 handle()
|
||
→ 模型、工具和适当性治理
|
||
→ 引用、禁止表达和敏感信息审查
|
||
→ complete_run 同事务持久化、审计和 Outbox
|
||
→ 查询/SSE 返回结果
|
||
```
|
||
|
||
组员只能读取 `self.config`、`self.memories`、`request` 和服务端生成的 `context`。客户身份以 `context`
|
||
为准,不信任客户端自行传入的身份字段。
|
||
|
||
## 6. 意图分类
|
||
|
||
组员不需要创建 `IntentClassifier`、调用 `ModelRouterService` 或传 `endpoints`。底座会在 `handle()`
|
||
前从当前激活的模型端点自动分类,并把结果写入 `CoreResult.intent`。
|
||
|
||
模型输出必须是严格 JSON:
|
||
|
||
```json
|
||
{"intent":"fund_quote","confidence":0.92}
|
||
```
|
||
|
||
底座会校验:
|
||
|
||
- 意图必须属于 `supported_intents`;
|
||
- `confidence` 必须在 0 到 1;
|
||
- 低于配置阈值时 `needs_clarification=true`;
|
||
- 非法 JSON、未声明意图和空输入失败关闭。
|
||
|
||
低置信结果不能当作确定意图继续执行高风险业务。
|
||
|
||
## 7. 模型调用
|
||
|
||
模型链路固定为:
|
||
|
||
```text
|
||
ConfigRelease → ModelRouterService → ModelGateway → 主端点/受控 fallback
|
||
```
|
||
|
||
业务 Agent 只能调用底座注入的方法:
|
||
|
||
```python
|
||
result = await self.generate_with_model(endpoints, prompt)
|
||
```
|
||
|
||
禁止:
|
||
|
||
- 导入 `httpx` 或供应商 SDK;
|
||
- 自己读取模型密钥;
|
||
- 自己选择未批准端点;
|
||
- 把模型原始异常返回给用户。
|
||
|
||
模型密钥只能使用 `secret_ref`,不能写入代码、数据库明文、日志或接口响应。
|
||
|
||
## 8. 公共工具调用
|
||
|
||
工具必须通过工厂注入的 `ToolExecutor` 调用:
|
||
|
||
```python
|
||
value = await self.call_tool(
|
||
"工具名",
|
||
{"参数": "值"},
|
||
intent="当前意图",
|
||
context=context,
|
||
)
|
||
```
|
||
|
||
每个工具必须声明 Pydantic 输入模型、权限码、允许角色、只读属性和超时。底座统一执行参数校验、
|
||
意图白名单、角色权限、超时、脱敏摘要、审计和来源引用。
|
||
|
||
底座已注册 **4 个公共只读工具**(`app/service/agent/bootstrap.py` 的 `ToolRegistry`,约 L155-192):
|
||
|
||
| 工具名 | 必需权限 | 允许角色 | 只读 | 越权与失败行为 |
|
||
|---|---|---|---|---|
|
||
| `check_suitability` | `suitability:read` | customer、advisor、operator、admin | 是 | C1-C5/R1-R5 匹配;测评过期/缺失一律拒绝(失败关闭);通过和拒绝都写 `interaction_audit` |
|
||
| `query_fund_quote` | `fund:quote:read` | customer、advisor、operator、risk_operator、admin | 是 | 只读行情,不得改写为成交、委托或持仓语义;超时 15s |
|
||
| `query_knowledge` | `knowledge:query` | customer、operator、advisor、risk_operator、admin | 是 | 集合名由服务端按意图映射,调用方不得指定;维度不符失败关闭;超时 8s |
|
||
| `query_customer_profile` | `memory:read:self`(查他人为 `memory:read:customer`) | customer、advisor、operator、risk_operator、admin | 是 | 越范围按"不存在"处理且不泄露存在性;无当前画像**抛错**而不返回空画像 |
|
||
|
||
**工具白名单是两段式**:代码里的 `AgentDefinition.allowed_tools` 是**上限**,实际可用范围还要与
|
||
当前 `active` 的 `config_release` 中 `namespace=agent_tools`、`config_key=<agent_type>:<intent>`
|
||
发布的工具白名单**取交集**;**缺发布配置时交集为空、工具失败关闭**。4 个工具的接口面登记口径
|
||
见《05-接口文档.md》§8.4。
|
||
|
||
## 9. 基金行情工具
|
||
|
||
底座已提供公共只读工具(全部 4 个工具的清单见 §8;本节只展开行情工具):
|
||
|
||
```text
|
||
工具名:query_fund_quote
|
||
权限码:fund:quote:read
|
||
允许角色:customer、advisor、operator、risk_operator、admin
|
||
```
|
||
|
||
### 9.1 代码和配置声明
|
||
|
||
在 AgentDefinition 中声明:
|
||
|
||
```python
|
||
allowed_tools=("query_fund_quote",)
|
||
supported_intents=("fund_quote", "general")
|
||
```
|
||
|
||
在已发布配置中声明:
|
||
|
||
```text
|
||
namespace: agent_tools
|
||
config_key: <agent_type>:fund_quote
|
||
value_json: {"allowed_tools": ["query_fund_quote"]}
|
||
```
|
||
|
||
### 9.2 调用方式
|
||
|
||
```python
|
||
quote = await self.call_tool(
|
||
"query_fund_quote",
|
||
{"fund_codes": ["159511"], "limit": 20},
|
||
intent="fund_quote",
|
||
context=context,
|
||
)
|
||
```
|
||
|
||
返回结果重点关注:
|
||
|
||
- `quote_source`:`eastmoney`、`cache` 或 `degraded`;
|
||
- `is_intraday`:是否盘中行情;
|
||
- `degraded`:是否降级;
|
||
- `nav_date`:净值对应日期。
|
||
|
||
降级行情只能用于说明和分析,不能表述为成交、委托、持仓或实时保证。
|
||
|
||
禁止直接导入 `hq.py`、调用东方财富 URL、使用 `httpx` 或自行读取行情缓存。
|
||
|
||
## 10. 适当性校验
|
||
|
||
投顾相关流程必须调用公共 `SuitabilityService` 或 `check_suitability` 工具,不得复制 C1-C5/R1-R5
|
||
规则。客户风险等级低于产品风险等级、测评过期时必须拒绝;专业投资者也不能绕过审计。
|
||
|
||
通过和拒绝决定都会写入 `interaction_audit`,服务只读,不修改交易、产品或客户风险资料。
|
||
|
||
## 11. 记忆、关系和转人工
|
||
|
||
- 记忆提取由 `complete_run()` 在同一事务写入 Outbox,组员不直接调用提取服务;
|
||
- 记忆只能读取当前客户授权范围;
|
||
- Neo4j 查询必须经过 `RelationshipService` 和关系白名单;
|
||
- Agent 只能提出转人工请求,不能分配、接单、解决或关闭工单;
|
||
- 不能伪造 `SourceReference`,只能引用本次授权召回或工具真实返回的数据。
|
||
|
||
## 12. 禁止事项
|
||
|
||
- 禁止绕过 `AgentFactory`、`BaseAgent`、统一鉴权、记忆、模型、工具、合规、审计和事件流程;
|
||
- 禁止直接创建 SQLAlchemy Session、访问 MySQL、Redis、Milvus 或 Neo4j Driver;
|
||
- 禁止代客下单、确认成交、修改持仓、审核方案、处置或关闭风险预警;
|
||
- 禁止把场外运营数据写入场内交易表;
|
||
- 禁止重命名、删除或修改已有数据库表和字段;数据库需求只能新增表或字段并先对照基线。
|
||
|
||
## 13. 提交前测试
|
||
|
||
业务 Agent 至少覆盖:
|
||
|
||
- 正常意图、低置信意图和模型格式错误;
|
||
- 未授权角色、入口、权限和客户范围;
|
||
- 工具白名单、参数错误、超时和失败关闭;
|
||
- 适当性通过、风险不匹配和测评过期;
|
||
- 行情正常、缓存、降级和非交易时段;
|
||
- 禁止表达、敏感信息脱敏、来源引用和最终持久化。
|
||
|
||
统一验收命令:
|
||
|
||
```powershell
|
||
python -m pytest -q -p no:cacheprovider
|
||
python -m ruff check app tests tools alembic
|
||
python -m mypy app
|
||
python tools/check_authoritative_docs.py
|
||
python tools/audit_schema.py
|
||
```
|
||
|
||
## 14. 当前状态
|
||
|
||
`app/service/agent/bootstrap.py` 的 `register_business_agents()`(约 L218-225)已注册两个业务 Agent:
|
||
|
||
- `FundQueryDemoAgent`(`agent_type="fund_query_demo"`):示例 Agent,一个 `fund_quote` 意图 + `query_fund_quote` 工具;
|
||
- `CustomerServiceAgent`(`agent_type="customer_service"`):客服 Agent,五类意图(`faq` / `product_inquiry` / `policy_explain` / `chitchat` / `transfer_human`),使用 `query_knowledge`。
|
||
|
||
上表 4 个公共只读工具均已注册并可供业务 Agent 使用,但业务 Agent 必须完成自己的代码声明、
|
||
意图白名单配置和注册后才能调用。新增的业务 Agent 若未注册,提交其 `agent_type` 会返回
|
||
`404 AGENT_TYPE_NOT_FOUND`。
|
||
|
||
推荐阅读顺序:本文 → 《05-接口文档.md》→ 对应业务域流程文档。本文不替代接口文档和数据库基线。
|