cc 1 周之前
父節點
當前提交
4d11baf3e2

+ 5 - 11
ai-server/src/main/java/com/zsjz/ai/module/agent/tools/AgentToolRegistry.java

@@ -185,15 +185,12 @@ public class AgentToolRegistry {
 
     private static final List<String> PERSON_TOOLS = List.of(
             "get_person_call_profile", "stat_person_call_station", "stat_person_call_top10",
-            "stat_call_record_summary", "get_person_oper_phone_info",
+            "stat_call_record_summary",
             "get_person_trans_profile", "stat_person_trans_top10", "stat_trans_record_summary",
-            "get_trans_other_names", "get_trans_bank_card_info",
+             "get_trans_bank_card_info",
             "stat_trans_amount_trend_month", "stat_trans_amount_trend_year",
-            "stat_intimacy_summary", "stat_intimacy_big_trans", "stat_intimacy_special_day_trans",
-            "stat_intimacy_same_phone_binding", "stat_intimacy_keep_call",
-            "stat_intimacy_special_day_call", "stat_intimacy_keep_trans",
-            "stat_intimacy_travel_together", "stat_intimacy_night_call",
-            "list_persons", "list_person_names", "list_person_groups");
+            "stat_intimacy_summary",
+            "list_persons");
 
     private static final List<String> FILE_TOOLS = List.of(
             "list_file_profiles", "stat_file_profiles_by_category", "get_file_sample");
@@ -230,7 +227,6 @@ public class AgentToolRegistry {
     private final DataProfileService dataProfileService;
     private final IntimacyService intimacyService;
     private final PersonBasicInfoService personBasicInfoService;
-    private final PersonGroupService personGroupService;
 
     private final FileAiProfileService fileAiProfileService;
 
@@ -260,7 +256,6 @@ public class AgentToolRegistry {
                              DataProfileService dataProfileService,
                              IntimacyService intimacyService,
                              PersonBasicInfoService personBasicInfoService,
-                             PersonGroupService personGroupService,
                              FileAiProfileService fileAiProfileService) {
         this.sqlResultStore = sqlResultStore;
         this.callRecordService = callRecordService;
@@ -288,7 +283,6 @@ public class AgentToolRegistry {
         this.dataProfileService = dataProfileService;
         this.intimacyService = intimacyService;
         this.personBasicInfoService = personBasicInfoService;
-        this.personGroupService = personGroupService;
         this.fileAiProfileService = fileAiProfileService;
     }
 
@@ -333,7 +327,7 @@ public class AgentToolRegistry {
                 trackTogetherTravelService, sqlResultStore));
         toolkit.registerTool(new GraphAnalysisTool(graphService));
         toolkit.registerTool(new PersonAnalysisTool(dataProfileService, intimacyService,
-                personBasicInfoService, personGroupService, sqlResultStore));
+                personBasicInfoService, sqlResultStore));
         toolkit.registerTool(new FileAnalysisTool(fileAiProfileService, sqlResultStore));
 
         // ---- 建组并分配工具 ----

+ 6 - 247
ai-server/src/main/java/com/zsjz/ai/module/agent/tools/PersonAnalysisTool.java

@@ -3,7 +3,6 @@ package com.zsjz.ai.module.agent.tools;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zsjz.ai.common.base.Query;
 import com.zsjz.ai.common.enums.SymbolEnum;
-import com.zsjz.ai.common.model.call.entity.CallOpenInfo;
 import com.zsjz.ai.common.model.person.dto.CallDataProfileStatDTO;
 import com.zsjz.ai.common.model.person.dto.CallOftenTop10DTO;
 import com.zsjz.ai.common.model.person.dto.CallRecordSummaryDTO;
@@ -13,9 +12,7 @@ import com.zsjz.ai.common.model.person.dto.TransDataProfileStatDTO;
 import com.zsjz.ai.common.model.person.dto.TransOftenTop10DTO;
 import com.zsjz.ai.common.model.person.dto.TransTrendDTO;
 import com.zsjz.ai.common.model.person.entity.PersonBasicInfo;
-import com.zsjz.ai.common.model.person.entity.PersonGroup;
 import com.zsjz.ai.common.model.person.query.CallOftenTop10Query;
-import com.zsjz.ai.common.model.person.query.CallOperPhoneInfoQuery;
 import com.zsjz.ai.common.model.person.query.CallRecordSummaryQuery;
 import com.zsjz.ai.common.model.person.query.CallStatStationQuery;
 import com.zsjz.ai.common.model.person.query.TransOftenTop10Query;
@@ -38,11 +35,9 @@ import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Objects;
 import java.util.function.Function;
 
@@ -98,18 +93,15 @@ public class PersonAnalysisTool {
     private final DataProfileService dataProfileService;
     private final IntimacyService intimacyService;
     private final PersonBasicInfoService personBasicInfoService;
-    private final PersonGroupService personGroupService;
     private final SqlResultStore sqlResultStore;
 
     public PersonAnalysisTool(DataProfileService dataProfileService,
                               IntimacyService intimacyService,
                               PersonBasicInfoService personBasicInfoService,
-                              PersonGroupService personGroupService,
                               SqlResultStore sqlResultStore) {
         this.dataProfileService = dataProfileService;
         this.intimacyService = intimacyService;
         this.personBasicInfoService = personBasicInfoService;
-        this.personGroupService = personGroupService;
         this.sqlResultStore = sqlResultStore;
     }
 
@@ -241,38 +233,6 @@ public class PersonAnalysisTool {
         }
     }
 
-    /**
-     * 号码运营商归属查询(补齐未匹配到的号码)
-     */
-    @Tool(name = "get_person_oper_phone_info",
-          description = "查询一批本方号码在运营商开户信息表(call_opening_info)中的归属记录(开户人、证件号、地址、"
-                  + "运营商等原始字段);表里查不到的号码也会补一行(只带号码、姓名、operatorId),便于模型知道哪些号没匹配上。"
-                  + "★ 问「某人名下号码的运营商/开户信息」「哪些号码在运营商侧没有记录」时用本工具,不要用 execute_sql 手写 SQL。"
-                  + "phoneList 必传(至少一个号码);personName 建议一起传,用于过滤开户人并回填未匹配行。"
-                  + "本接口无分页条件,一次最多返回 10000 行。",
-          readOnly = true)
-    public ToolResultBlock getPersonOperPhoneInfo(
-            @ToolParam(name = "query", description = "运营商号码归属查询条件,phoneList 必传")
-            PersonToolSpecs.OperPhoneInfoSpec query) {
-        PersonToolSpecs.OperPhoneInfoSpec spec = query == null ? new PersonToolSpecs.OperPhoneInfoSpec() : query;
-        try {
-            List<String> phones = cleanList(spec.phoneList);
-            if (phones == null) {
-                return ToolResults.error("phoneList 不能为空,请至少传一个本方号码");
-            }
-            CallOperPhoneInfoQuery q = new CallOperPhoneInfoQuery();
-            q.setPersonName(trimToNull(spec.personName));
-            q.setOperatorId(trimToNull(spec.operatorId));
-            q.setPhoneList(phones);
-            applyFetchWindow(q);
-
-            List<CallOpenInfo> list = dataProfileService.getCallOperPhoneInfo(q);
-            return renderList(list, spec.pageSize);
-        } catch (Exception e) {
-            return fail("运营商号码归属查询", e);
-        }
-    }
-
     // ==================== 交易画像(DataProfileService) ====================
 
     /**
@@ -331,7 +291,7 @@ public class PersonAnalysisTool {
             q.setStartDate(parseDate(spec.startDate, "startDate"));
             q.setEndDate(parseDate(spec.endDate, "endDate"));
             if (spec.transCount != null) {
-                q.setTransCount(spec.transCount.intValue());
+                q.setTransCount(spec.transCount);
             }
             if (spec.transAmount != null) {
                 q.setTransAmount(toBigDecimal(spec.transAmount, "transAmount"));
@@ -373,7 +333,7 @@ public class PersonAnalysisTool {
             q.setStartDate(parseDate(spec.startDate, "startDate"));
             q.setEndDate(parseDate(spec.endDate, "endDate"));
             if (spec.transCount != null) {
-                q.setTransCount(spec.transCount.intValue());
+                q.setTransCount(spec.transCount);
             }
             if (spec.transAmount != null) {
                 q.setTransAmount(toBigDecimal(spec.transAmount, "transAmount"));
@@ -381,7 +341,7 @@ public class PersonAnalysisTool {
             q.setTransCountSymbol(parseSymbol(spec.transCountSymbol, "transCountSymbol"));
             q.setTransAmountSymbol(parseSymbol(spec.transAmountSymbol, "transAmountSymbol"));
             if (spec.source != null) {
-                q.setSource(spec.source.intValue());
+                q.setSource(spec.source);
             }
             // 排序硬编码(不暴露给模型),否则 XML 的 <if> 不成立会导致结果完全无序
             q.setOrderKey(DEFAULT_TRANS_SUMMARY_ORDER_KEY);
@@ -395,46 +355,6 @@ public class PersonAnalysisTool {
         }
     }
 
-    /**
-     * 交易对方名称清单(用于下拉/枚举,去重)
-     */
-    @Tool(name = "get_trans_other_names",
-          description = "列出某个对象在交易数据中出现过的全部交易对方名称(去重,对方信息缺失归入「未知对手」)。"
-                  + "★ 用于「某人都有哪些交易对手」「把交易对手名称列出来做筛选」这类枚举型问题,"
-                  + "或作为调用 stat_trans_record_summary / stat_trans_amount_trend_* 前的取值参考。"
-                  + "只返回名称字符串,没有金额次数;要带统计数字请用 stat_person_trans_top10 或 stat_trans_record_summary。"
-                  + "personName 必传。",
-          readOnly = true)
-    public ToolResultBlock getTransOtherNames(
-            @ToolParam(name = "query", description = "交易对方名称查询条件,personName 必传")
-            PersonToolSpecs.TransOtherNameSpec query) {
-        PersonToolSpecs.TransOtherNameSpec spec = query == null ? new PersonToolSpecs.TransOtherNameSpec() : query;
-        try {
-            String personName = trimToNull(spec.personName);
-            if (personName == null) {
-                return ToolResults.error("personName 不能为空");
-            }
-            Query q = new Query();
-            q.setPersonName(personName);
-            applyFetchWindow(q);
-
-            Page<String> page = dataProfileService.getTransOtherNamePage(q);
-            if (page.getTotal() > FETCH_LIMIT) {
-                return overLimit(page.getTotal());
-            }
-            // 元素是纯字符串,直接丢给 ToolResultTable 无法推导列,包成 [{"otherName": 值}] 再走统一出口
-            List<Map<String, Object>> rows = new ArrayList<>();
-            for (String otherName : page.getRecords()) {
-                Map<String, Object> row = new LinkedHashMap<>();
-                row.put("otherName", otherName);
-                rows.add(row);
-            }
-            return ToolResultTable.store(sqlResultStore, null, rows, 1,
-                    ToolResultTable.normalizePageSize(spec.pageSize));
-        } catch (Exception e) {
-            return fail("交易对方名称查询", e);
-        }
-    }
 
     /**
      * 银行卡交易汇总(含账户状态、余额、开卡/销卡时间)
@@ -528,126 +448,10 @@ public class PersonAnalysisTool {
           readOnly = true)
     public ToolResultBlock statIntimacySummary(
             @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("亲密度总览统计", personName, intimacyService::intimacySummary);
+        return runIntimacy(personName, intimacyService::intimacySummary);
     }
 
-    /**
-     * 亲密度 - 大额转账
-     */
-    @Tool(name = "stat_intimacy_big_trans",
-          description = "统计某个对象的大额转账行为:按交易对手聚合 1 万元以上(其中 5 万元以上为一档)的转账,"
-                  + "返回对手姓名、命中分值、行为标签与「大额交易次数」明细。"
-                  + "★ 问「某人给谁大额转账」「大额资金往来对象」「单笔或累计大额交易」时用本工具,"
-                  + "不要用 execute_sql 手写 SQL —— 大额阈值(1 万 / 5 万)与计分档位来自案件亲密度配置。"
-                  + "personName 必传。要看含金额的原始交易,用 execute_sql 或 stat_trans_record_summary。",
-          readOnly = true)
-    public ToolResultBlock statIntimacyBigTrans(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("大额转账分析", personName, intimacyService::bigTrans);
-    }
 
-    /**
-     * 亲密度 - 特殊日期特殊转账
-     */
-    @Tool(name = "stat_intimacy_special_day_trans",
-          description = "统计某个对象在敏感日期(案件配置的特殊日期/节假日)内的特殊转账行为:按交易对手聚合,"
-                  + "返回对手姓名、命中分值、行为标签与「特殊日期特殊转账」次数明细,按次数分档计分。"
-                  + "★ 问「敏感日期期间谁给谁转过账」「节假日/特殊日期的资金往来」时用本工具,不要用 execute_sql 手写 SQL。"
-                  + "personName 必传。要看敏感日期内的原始话单式明细请用 stat_call_sensitive_detail(通话)或 execute_sql(交易)。",
-          readOnly = true)
-    public ToolResultBlock statIntimacySpecialDayTrans(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("特殊日期特殊转账分析", personName, intimacyService::specialDayTrans);
-    }
-
-    /**
-     * 亲密度 - 异卡同号
-     */
-    @Tool(name = "stat_intimacy_same_phone_binding",
-          description = "统计某个对象的「异卡同号」行为:在本方所属人员组中,找出把银行卡预留手机号登记成本方号码的其他人,"
-                  + "按人返回命中分值、行为标签与「异卡同号」关联卡数明细。"
-                  + "★ 问「谁的银行卡用了某人的手机号」「异卡同号关联了哪些人」时用本工具,不要用 execute_sql 手写 SQL —— "
-                  + "该行为依赖人员组的「主体」标识,只有主体人员调用才会返回结果,非主体一律返回空。"
-                  + "personName 必传。",
-          readOnly = true)
-    public ToolResultBlock statIntimacySamePhoneBinding(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("异卡同号分析", personName, intimacyService::samePhoneBinding);
-    }
-
-    /**
-     * 亲密度 - 频繁联系(通话次数 TOP)
-     */
-    @Tool(name = "stat_intimacy_keep_call",
-          description = "统计某个对象的频繁联系行为:按通话次数对联系对象排名,取前 20 名并按档位(前 5 / 6~10 / 11~20)计分,"
-                  + "返回对手姓名、命中分值、行为标签与「联系次数」明细。已过滤 12/95/96/106 开头的服务号与短号。"
-                  + "★ 问「谁和某人联系最频繁」「通话次数最多的联系人」时用本工具,不要用 execute_sql 手写 SQL —— "
-                  + "档位分值与短号过滤口径已固化。personName 必传。"
-                  + "若关心的是「跨月持续联系」,请用 stat_call_continuous_summary。",
-          readOnly = true)
-    public ToolResultBlock statIntimacyKeepCall(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("频繁联系分析", personName, intimacyService::keepCall);
-    }
-
-    /**
-     * 亲密度 - 特殊日期联系(通话)
-     */
-    @Tool(name = "stat_intimacy_special_day_call",
-          description = "统计某个对象在敏感日期(案件配置的特殊日期/节假日)内的通话联系:按通话次数对联系对象排名,"
-                  + "取前 20 名并按档位计分,返回对手姓名、命中分值、行为标签与「特殊日期通话次数」明细。"
-                  + "★ 问「敏感日期期间和谁联系过」「节假日/特殊日期的通话对象」时用本工具,不要用 execute_sql 手写 SQL。"
-                  + "personName 必传。要看敏感日期内的原始话单请用 stat_call_sensitive_detail。",
-          readOnly = true)
-    public ToolResultBlock statIntimacySpecialDayCall(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("特殊日期联系分析", personName, intimacyService::specialDayCall);
-    }
-
-    /**
-     * 亲密度 - 频繁交易
-     */
-    @Tool(name = "stat_intimacy_keep_trans",
-          description = "统计某个对象的频繁交易行为:按交易笔数对交易对手排名,取前 20 名并按档位(前 5 / 6~10 / 11~20 / 20 以后)计分,"
-                  + "返回对手姓名、命中分值、行为标签与「交易次数」明细。"
-                  + "★ 问「谁和某人交易最频繁」「交易笔数最多的对手」时用本工具,不要用 execute_sql 手写 SQL —— "
-                  + "档位分值来自案件亲密度配置,缺失时有内置兜底值。personName 必传。"
-                  + "若要看交易金额维度,请用 stat_person_trans_top10。",
-          readOnly = true)
-    public ToolResultBlock statIntimacyKeepTrans(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("频繁交易分析", personName, intimacyService::keepTrans);
-    }
-
-    /**
-     * 亲密度 - 同交通工具出行
-     */
-    @Tool(name = "stat_intimacy_travel_together",
-          description = "统计某个对象的同交通工具出行行为:把火车/航班记录与同行轨迹按「出行时间 + 车次/航班号」配对,"
-                  + "找出与其同行的其他人,按同行次数分档计分,返回同行人姓名、命中分值、行为标签与「同行次数」明细。"
-                  + "★ 问「某人和谁一起坐过车/飞机」「同行人」「一起出行的次数」时用本工具,不要用 execute_sql 手写 SQL —— "
-                  + "配对口径(时间+班次)与分档规则已固化。personName 必传。"
-                  + "注意:本行为需要遍历全案人员做轨迹匹配,返回较慢且结果可能为空(没有同行记录时)。",
-          readOnly = true)
-    public ToolResultBlock statIntimacyTravelTogether(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("同交通工具出行分析", personName, intimacyService::travelTogether);
-    }
-
-    /**
-     * 亲密度 - 夜间通话
-     */
-    @Tool(name = "stat_intimacy_night_call",
-          description = "统计某个对象的夜间通话行为:按对方号码聚合夜间通话次数,只保留有夜间通话的月份数 ≥ 2 的号码,"
-                  + "取次数前 20 名并按档位计分,返回对方号码、命中分值、行为标签与「夜间通话次数」明细。"
-                  + "★ 问「某人深夜常联系谁」「夜间通话对象」时用本工具,不要用 execute_sql 手写 SQL —— "
-                  + "夜间时段、跨月阈值与档位分值已固化。personName 必传。"
-                  + "需要按小时段下钻或自定义夜间时段,请用 stat_call_night_summary / stat_call_night_detail。",
-          readOnly = true)
-    public ToolResultBlock statIntimacyNightCall(
-            @ToolParam(name = "personName", description = "本方(机主)姓名,精确匹配,必传,如「张三」") String personName) {
-        return runIntimacy("夜间通话分析", personName, intimacyService::nightCall);
-    }
 
     // ==================== 人员与人员组(只读列表) ====================
 
@@ -670,52 +474,7 @@ public class PersonAnalysisTool {
         }
     }
 
-    /**
-     * 全案对象人员姓名清单
-     */
-    @Tool(name = "list_person_names",
-          description = "列出当前案件全部对象人员的姓名(仅姓名,最省 token)。"
-                  + "★ 问「本案有哪些人」「都有谁」这类只需姓名的场景用本工具;"
-                  + "需要证件号、住址、名下号码等基本信息请用 list_persons。无入参。",
-          readOnly = true)
-    public ToolResultBlock listPersonNames() {
-        try {
-            List<String> names = personBasicInfoService.getPersonNames();
-            // ★ 不能直接把 List<String> 交给 ToolResultTable:它按「POJO 列表」处理,
-            //   会把每个姓名当成对象反序列化,抛
-            //   "Cannot construct instance of java.util.LinkedHashMap ... from String value"
-            //   (2026-09-20 在 MCP 链路上实测到,空人名时不会触发,所以一直没暴露)。
-            //   这里显式包成单列,列名与 list_persons 的姓名字段保持一致。
-            List<Map<String, Object>> rows = new ArrayList<>();
-            if (names != null) {
-                for (String name : names) {
-                    Map<String, Object> row = new LinkedHashMap<>();
-                    row.put("name", name);
-                    rows.add(row);
-                }
-            }
-            return renderList(rows, null);
-        } catch (Exception e) {
-            return fail("对象人员姓名查询", e);
-        }
-    }
 
-    /**
-     * 人员组(团伙/关系组)清单
-     */
-    @Tool(name = "list_person_groups",
-          description = "列出当前案件配置的人员组(关系组):组名、备注,以及组内成员列表(成员姓名、是否主体、主体标识)。"
-                  + "★ 问「本案分了哪些组」「某人和谁在同一组」「谁是主体人员」时用本工具,不要用 execute_sql 手写 SQL。"
-                  + "无入参。注意「异卡同号」等亲密度行为依赖人员组的主体标识,可用本工具确认主体是谁。",
-          readOnly = true)
-    public ToolResultBlock listPersonGroups() {
-        try {
-            List<PersonGroup> list = personGroupService.getList();
-            return renderList(list, null);
-        } catch (Exception e) {
-            return fail("人员组列表查询", e);
-        }
-    }
 
     // ==================== 内部实现 ====================
 
@@ -725,7 +484,7 @@ public class PersonAnalysisTool {
      * <p>9 个亲密度方法签名完全一致(单 String 入参、返回 {@code List<IntimacyDTO>}),
      * 抽出来既避免重复代码,也保证「空姓名报错文案」与「超限判定」在 9 个工具间完全一致。
      */
-    private ToolResultBlock runIntimacy(String action, String personName,
+    private ToolResultBlock runIntimacy(String personName,
                                         Function<String, List<IntimacyDTO>> actionFn) {
         String name = trimToNull(personName);
         if (name == null) {
@@ -734,7 +493,7 @@ public class PersonAnalysisTool {
         try {
             return renderList(actionFn.apply(name), null);
         } catch (Exception e) {
-            return fail(action, e);
+            return fail("亲密度总览统计", e);
         }
     }
 

+ 0 - 1
ai-server/src/test/java/com/zsjz/ai/module/agent/mcp/AgentScopeMcpToolProviderTest.java

@@ -121,7 +121,6 @@ class AgentScopeMcpToolProviderTest {
                 mock(GraphService.class),
                 mock(DataProfileService.class), mock(IntimacyService.class),
                 personBasicInfoService,
-                mock(PersonGroupService.class),
                 mock(FileAiProfileService.class));
     }
 

+ 1 - 1
ai-server/src/test/java/com/zsjz/ai/module/agent/service/AgentCapabilityToolkitTest.java

@@ -85,7 +85,7 @@ class AgentCapabilityToolkitTest {
                 mock(TrackTogetherLiveService.class), mock(TrackTogetherTravelService.class),
                 mock(GraphService.class),
                 mock(DataProfileService.class), mock(IntimacyService.class),
-                mock(PersonBasicInfoService.class), mock(PersonGroupService.class),
+                mock(PersonBasicInfoService.class),
                 mock(FileAiProfileService.class));
         return new AgentService(
                 mock(AgentModelFactory.class),

+ 2 - 2
ai-server/src/test/java/com/zsjz/ai/module/agent/tools/AgentToolRegistryTest.java

@@ -103,7 +103,7 @@ class AgentToolRegistryTest {
                 mock(TrackTogetherLiveService.class), mock(TrackTogetherTravelService.class),
                 mock(GraphService.class),
                 mock(DataProfileService.class), mock(IntimacyService.class),
-                mock(PersonBasicInfoService.class), mock(PersonGroupService.class),
+                mock(PersonBasicInfoService.class),
                 mock(FileAiProfileService.class));
         Toolkit toolkit = new Toolkit();
         registry.registerBusinessTools(toolkit);
@@ -296,7 +296,7 @@ class AgentToolRegistryTest {
                 mock(TrackTogetherLiveService.class), mock(TrackTogetherTravelService.class),
                 mock(GraphService.class),
                 mock(DataProfileService.class), mock(IntimacyService.class),
-                mock(PersonBasicInfoService.class), mock(PersonGroupService.class),
+                mock(PersonBasicInfoService.class),
                 mock(FileAiProfileService.class));
         registry.registerBusinessTools(toolkit, AgentToolRegistry.registeredGroupNames());