Files
group_fqcd_jr/docs/16-Agent组员入门易懂版说明.md
T

11 KiB
Raw Blame History

Agent 组员入门易懂版说明

📌 接入请以 docs/14-Agent组员统一接入说明书.md 为准(唯一推荐入口,含完整工具清单与权限口径)。 本文是同一套教学序列的入门易懂版(与 11 / 15 内容高度重合),保留用于新人快速上手; 两者冲突时以 14 为准。

适用对象:第一次接入本项目的客服、投顾、风控和运营开发人员,以及协助编码的 AI。
阅读目标:看完后,能够在不破坏底座的前提下写出一个业务 Agent。

1. 先用一句话理解这个项目

你们要做的是“业务 Agent”,底座已经负责公共工作。

可以把系统想成一个机场:

Controller = 机场入口和检票口
AgentFactory = 登机调度台
BaseAgent = 统一登机流程
你的 Agent = 具体航班
ToolExecutor = 受控的机场服务柜台
Worker = 真正执行飞行任务的工作人员

你只需要设计“这个航班要去哪里、提供什么业务服务”,不需要重新建机场、重新做安检或自己买飞机。

2. 你真正需要写的代码

一个业务 Agent 通常只需要三部分:

  1. 定义 Agent 的名字、角色和意图;
  2. 写一个继承 BaseAgent 的类;
  3. 在公共工厂注册一行代码。

最小结构如下:

app/service/agent/implementations/your_agent.py   # 业务 Agent
tests/unit/service/test_your_agent.py             # 业务测试
app/service/agent/bootstrap.py                    # 注册一行

不要复制 BaseAgent,不要复制模型调用,不要复制工具权限代码。

3. 第一步:定义 Agent

from app.core.contracts import AgentDefinition


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"),
    )

每一项是什么意思

字段 简单理解 示例
agent_type Agent 的唯一名字 advisor
version 业务 Agent 版本 1.0.0
allowed_roles 哪些角色可以使用 customer、advisor
allowed_portals 从哪里进入 api
allowed_tools 代码允许使用哪些工具 query_fund_quote
supported_intents 这个 Agent 能处理哪些问题类型 fund_quote、general

注意:allowed_tools 是最大权限。配置中心只能减少工具,不能增加工具。

4. 第二步:写 handle()

from app.core.contracts import 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=f"你刚才说的是:{request.message}")

request 和 context 的区别

request 是用户说的话,例如:

请查询基金 159511 的行情

context 是系统验证后的身份信息,例如:

user_id、roles、permissions、trace_id、customer_ids

身份、客户范围和权限必须相信 context,不要相信用户自己在消息里写的客户编号。

5. 第三步:注册 Agent

在 app/service/agent/bootstrap.py 中添加:

factory.register(
    AdvisorAgent.definition,
    lambda _context: AdvisorAgent(AdvisorAgent.definition),
)

这行代码的意思是:

当系统收到 agent_type=advisor 时,
请使用 AdvisorAgent.definition 检查权限,
然后创建一个 AdvisorAgent 实例。

为什么必须在这里注册?因为 HTTP 服务和 Worker 都从这里拿 AgentFactory。如果你在别的地方注册, 可能出现“接口能找到,Worker 找不到”的问题。

6. 系统会自动做什么

你写完 handle() 后,系统会自动完成:

检查请求
→ 检查 JWT、角色和权限
→ 读取配置
→ 读取客户记忆
→ 判断用户意图
→ 执行你的 handle()
→ 检查违规内容和敏感信息
→ 保存结果、审计和事件

所以你不需要在 handle() 里重复写:

  • JWT 验证;
  • 角色判断;
  • 数据库 Session;
  • 记忆读取;
  • 模型密钥读取;
  • 工具权限判断;
  • 审计日志;
  • SSE 推送。

7. 如何使用基金行情工具

底座已经提供:

工具名:query_fund_quote
权限码:fund:quote:read

7.1 先在 AgentDefinition 声明

allowed_tools=("query_fund_quote",)
supported_intents=("fund_quote", "general")

7.2 在 handle() 中调用

async def handle(
    self,
    request: AgentRequest,
    context: RequestContext,
) -> CoreResult:
    quotes = await self.call_tool(
        "query_fund_quote",
        {
            "fund_codes": ["159511"],
            "limit": 20,
        },
        intent="fund_quote",
        context=context,
    )
    return CoreResult(text=f"行情查询结果:{quotes}")

7.3 为什么必须用 call_tool()

因为 call_tool() 会自动检查:

工具是否存在
→ 当前意图是否允许用它
→ 当前角色是否允许用它
→ 当前用户是否有权限
→ 参数是否正确
→ 是否超时
→ 是否写入审计

不要这样写:

import httpx
response = httpx.get("https://api.fund.eastmoney.com/...")

也不要这样写:

from hq import get_southern_fund_market

外部行情必须由底座统一处理。

7.4 如何理解行情结果

重点字段:

nav             基金净值
nav_date        净值日期
daily_change    日涨幅
quote_source    eastmoney / cache / degraded
is_intraday     是否盘中
degraded        是否降级

当 degraded=true 时,应该说“当前数据可能不是最新行情”,不能说“已经成交”或“保证收益”。

8. 如何使用适当性校验

投顾 Agent 不要自己写风险等级比较:

if customer_level >= product_level:
    allowed = True

必须使用公共工具:

decision = await self.call_tool(
    "check_suitability",
    {
        "customer_risk_level": 3,
        "product_risk_level": 3,
        "product_requires_disclosure": True,
    },
    intent="risk_check",
    context=context,
)

返回结果主要看:

allowed                 是否允许
reason_code             原因
required_disclosure     是否需要风险揭示
requires_confirmation   是否需要二次确认
requires_recording      是否需要双录

风险不匹配或测评过期时,必须停止高风险流程并给出安全提示。

9. 如何调用模型

大多数 Agent 不需要自己调用模型,因为底座已经自动完成意图分类。

只有业务确实需要生成一段说明文字时,才使用:

result = await self.generate_with_model(
    approved_endpoints,
    "请根据以下行情生成简短风险说明:...",
)

这里的 approved_endpoints 必须来自底座路由结果,不能自己写模型地址。

禁止:

  • 自己读取 API Key;
  • 自己创建 OpenAI 或其他供应商客户端;
  • 把模型原始回答直接返回;
  • 让模型决定是否下单或修改持仓。

10. 配置中心怎么配

工具白名单的配置格式:

namespace: agent_tools
config_key: advisor:fund_quote
value_json: {"allowed_tools": ["query_fund_quote"]}

配置只能小于等于代码中的 allowed_tools。例如代码没有声明 query_fund_quote,仅靠数据库配置 不能让 Agent 获得它。

行情运行配置使用:

namespace: fund_market
config_key: default

配置缺失或格式错误时,底座会使用安全默认值,不要在业务代码里直接读取配置表。

11. 常见错误和解决办法

错误一:AGENT_TYPE_NOT_FOUND

原因:没有在 bootstrap.py 注册 Agent。

解决:补充 factory.register(...),再运行注册表契约测试。

错误二:FORBIDDEN

原因可能是:角色不在 allowed_roles、入口不在 allowed_portals、缺少权限或工具没有配置到当前意图。

解决:检查代码声明和已发布配置,不要在 Agent 中绕过检查。

错误三:RECOVERABLE_ERROR

常见原因:模型、行情、Redis 等外部依赖暂时不可用。让 Worker 按策略重试,不要把供应商异常原文展示给用户。

错误四:工具找不到

确认三件事:

AgentDefinition.allowed_tools 是否声明
当前 supported_intents 是否包含调用意图
agent_tools/<agent_type>:<intent> 是否发布了工具白名单

错误五:引用校验失败

不要手写 SourceReference。只引用 self.memories 或本次 call_tool() 返回的数据。

12. 测试怎么写

最少要测试:

正常请求
未授权角色
未授权入口
低置信意图
模型输出错误
工具参数错误
工具超时
行情降级
适当性不通过
禁止表达和敏感信息

提交前执行:

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

13. 哪些事情绝对不能做

  • 不要覆盖 BaseAgent.execute();
  • 不要自己实现鉴权、意图分类、工具权限或审计;
  • 不要直接访问 MySQL、Redis、Milvus、Neo4j;
  • 不要直接调用东方财富接口;
  • 不要代客下单、确认成交或修改持仓;
  • 不要把场外运营数据写进场内交易表;
  • 不要修改已有表名、字段名、类型和既有含义;
  • 不要提交 .env、私钥、Token 或 API Key。

14. 开发完成后的交接模板

Agent 名称:
支持意图:
新增工具:
修改文件:
配置项:
测试命令:
测试结果:
数据库是否变化:
是否涉及场外流程:
已知限制:

如果数据库有需求,必须额外说明:新增了哪些表/字段、如何证明没有修改旧表和旧字段,以及迁移回滚方式。

15. 最后记住

你的业务 Agent 越简单越好:

声明能力
→ 接收 request/context
→ 调用公共工具
→ 组织业务结果
→ 返回 CoreResult

安全、权限、模型、记忆、审计、恢复和外部依赖由底座负责。不要为了“方便”绕过底座,否则代码无法通过 契约测试,也会给其他组员和生产运行带来不一致行为。