Files
AIclinicalresearch/docs/03-业务模块/IIT Manager Agent/00-系统设计/IIT Manager Agent V2.2:工具泛化与灵活性提升指南.md
HaHafeng 0c590854b5 docs(iit): Add IIT Manager Agent V2.9 development plan with multi-agent architecture
Features:
- Add V2.9 enhancements: Cron Skill, User Profiling, Feedback Loop, Multi-Intent Handling
- Create modular development plan documents (database, engines, services, memory, tasks)
- Add V2.5/V2.6/V2.8/V2.9 design documents for architecture evolution
- Add system design white papers and implementation guides

Architecture:
- Dual-Brain Architecture (SOP + ReAct engines)
- Three-layer memory system (Flow Log, Hot Memory, History Book)
- ProfilerService for personalized responses
- SchedulerService with Cron Skill support

Also includes:
- Frontend nginx config updates
- Backend test scripts for WeChat signature
- Database backup files

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-05 22:33:26 +08:00

6.5 KiB
Raw Blame History

IIT Manager Agent V2.2:工具泛化与灵活性提升指南

核心观点: 灵活性来自“工具的设计粒度”而不是“连接协议MCP”。

解决方案: 通过设计 3-5 个“瑞士军刀型”通用工具,替代 100 个“特种螺丝刀型”专用工具。

1. 直击灵魂MCP Server 真的更灵活吗?

你担心 V2.1 方案Service Class不够灵活让我们来做个对比

维度 MCP Server 方案 V2.1 Service Class 方案 真相
新增工具 在 Server 进程里写代码 -> 重启 Server -> Agent 发现新工具 在 Service 类里写代码 -> 重启 Node.js -> Agent 发现新工具 工作量完全一样。都要写代码逻辑。
工具调用 Agent 发 JSON -> 网络传输 -> MCP 执行 Agent 发 JSON -> 内存调用 -> Service 执行 V2.1 更快。没有网络开销。
Agent 自主性 LLM 看到的是 tool definitions (JSON) LLM 看到的也是 tool definitions (JSON) LLM 根本分不清你是 MCP 还是 Service。

结论:

  • MCP 的灵活性在于“解耦”:比如你可以把 REDCap 工具给别人用,或者在运行时动态加载新的 Server。
  • V2.1 的灵活性在于“敏捷”:代码都在一个工程里,改起来最快。对于 2 人团队,改代码 > 调协议

2. 你的痛点:是不是要写很多工具?

你担心:“如果有 100 个检查点,我是不是要写 check_age, check_gender, check_bmi 一百个工具?”

绝对不需要! 这就是我说的**“工具泛化”**。

错误的设计(特种螺丝刀)

写一堆具体的工具,导致 Service 类无限膨胀:

  • get_patient_age(id)
  • get_patient_history(id)
  • check_informed_consent(id)
  • ...

正确的设计(瑞士军刀)

只写 3 个 通用工具,就能覆盖 99% 的场景。Agent 会通过参数来体现灵活性。

工具 1read_clinical_data (全能查询器)

  • 功能:读取 REDCap 里的任意数据。
  • 参数record_id (患者ID), fields (想查什么字段), event (哪个访视)。
  • 灵活性
    • 查年龄Agent 传 fields: ["age"]。
    • 查病史Agent 传 fields: ["medical_history"]。
    • 你只需要写这一个函数Agent 就可以查任何东西。

工具 2eval_logic (逻辑计算器)

  • 功能:处理复杂的数值计算或逻辑判断(利用 json-logic
  • 场景Agent 算不清 BMI可以调这个工具帮它算。

工具 3manage_issue (通用反馈器)

  • 功能:包括提出质疑、发送提醒、记录日志。
  • 参数type (QUERY | NOTIFY | LOG), message (内容), severity (严重程度)。

3. 代码实现:如何实现“瑞士军刀”?

在你的 ToolsService.ts 中,只需要实现这几个通用方法。

// backend/src/modules/iit-manager/services/ToolsService.ts

export const UNIVERSAL_TOOL_DEFS = [
{
name: "read_clinical_data",
description: "通用数据查询工具。当需要检查患者的某项指标时使用。",
parameters: {
type: "object",
properties: {
record_id: { type: "string" },
// 关键:让 Agent 自己决定查什么字段
fields: {
type: "array",
items: { type: "string" },
description: "需要查询的REDCap变量名列表如 ['age', 's_cr', 'ae_desc']"
}
},
required: ["record_id", "fields"]
}
},
{
name: "manage_issue",
description: "通用问题处理工具。用于提出质疑或发送通知。",
parameters: {
type: "object",
properties: {
record_id: { type: "string" },
action_type: { type: "string", enum: ["RAISE_QUERY", "SEND_WECHAT"] },
message: { type: "string" }
},
required: ["record_id", "action_type", "message"]
}
}
];

export class ToolsService {
constructor(private redcapAdapter: RedcapAdapter) {}

async execute(name: string, args: any) {
switch (name) {
case 'read_clinical_data':
// 一个函数,通过参数变化应对无限需求
return await this.redcapAdapter.exportRecords({
recordId: args.record_id,
fields: args.fields // <--- 动态字段
});

  case 'manage\_issue':  
    if (args.action\_type \=== 'RAISE\_QUERY') {  
      return await this.saveShadowQuery(args);  
    } else {  
      return await this.sendWechat(args);  
    }  
}  

}
}

4. 场景演示Agent 的自主性如何体现?

哪怕你只提供了 2 个工具Agent 依然表现得像个专家,因为Skill (Prompt) 在指导它如何组合使用这些工具。

场景 A检查肝功能

  • Skill 配置: "instruction": "检查 ALT 和 AST 是否超过正常值 3 倍。"
  • Agent 思考: "我要查肝功能。"
  • Agent 行动: 调用 read_clinical_data(fields=['alt', 'ast'])。
  • 系统响应: {"alt": 150, "ast": 40}
  • Agent 判断: "ALT 150 > 40*3。违规。"
  • Agent 行动: 调用 manage_issue(action_type='RAISE_QUERY', message='ALT异常')。

场景 B检查入组年龄

  • Skill 配置: "instruction": "确保患者年龄 > 18。"
  • Agent 思考: "我要查年龄。"
  • Agent 行动: 调用 read_clinical_data(fields=['age'])。
  • 系统响应: {"age": 16}
  • Agent 行动: 调用 manage_issue(action_type='RAISE_QUERY', message='年龄不合规')。

看到没有?

没有写 check_liver 和 check_age 两个函数。

你只写了一个 read_clinical_data。

Agent 的大脑Prompt + 通用工具Tool 实现了无限的灵活性。

5. 总结

  1. MCP Server 不是灵活性的来源:它只是一个连接标准。如果你的工具设计得烂(粒度太细),用 MCP 也一样累。
  2. 通用参数是王道:不要写“查年龄”的工具,要写“查字段”的工具。让 Agent 填参数,这就是最大的灵活性。
  3. V2.1 极简版足够强:只要你的 ToolsService 按照“瑞士军刀”的思路去设计2 个开发人员维护 100 个项目的逻辑完全没有压力。

行动建议:

按照本文档的 第 3 节,把你的 ToolsService 重构一下,只保留 3-5 个通用方法。然后去测试一下 Agent 是否能聪明地自己填参数。