工程问题:军队采购对围标串标企业已从"罚款通报"升级为穿透到人的关联网络级封杀,传统按企业名比对黑名单极易漏掉"换壳重来"。技术方案:以实际控制人穿透(GetActualController)+ 对外投资/任职反向检索(GetExternalInvestments / get_executive_positions)构建关联图谱,将"全军禁入"识别前置到供应商准入与存量排查。
一、从"罚企业"到"封网络":处罚要素拆解
8 月初军采网同日发布 5 份公告,某大型国有建筑企业、省属国企等因围标串标被军事航天部队采购管理部门全军范围暂停资格,并连带封杀法定代表人、自然人控股股东及关联人员控股或管理的其他企业。这意味着处罚对象不再是单一中标主体,而是其背后的自然人控制网络。
要把这类"全军禁入"真正落到实处,采购侧需要把处罚文书里的自然语言要素,翻译成可被数据底座执行的穿透维度:
| 全军禁入处罚要素 | 数据穿透维度 | 对应接口 / MCP 工具 |
|---|---|---|
| 被罚企业主体资格暂停 | 工商登记全维核验 | GetBasicDetails / mcp__qcc-company__get_company_registration_info |
| 法定代表人 / 自然人控股股东封杀 | 实际控制人穿透至自然人 | GetActualController / mcp__qcc-company__get_actual_controller |
| 关联人员控股或管理的其他企业 | 对外投资 + 董监高任职反向检索 | GetExternalInvestments / mcp__qcc-company__get_external_investments、mcp__qcc-executive__get_executive_positions |
| 围标串标事实佐证 | 招投标关联 + 惩戒名单 | mcp__qcc-operation__get_bidding_info、mcp__qcc-risk__get_disciplinary_list |
| 关联网络风险传导 | 关联方风险扫描 | mcp__qcc-risk__get_company_related_risk_scan |
| 存量供应商持续监控 | 资质 / 诉讼 / 黑名单比对 | verify_company_accuracy、get_company_risk_scan |
二、围串标识别的盲区:为什么按企业名比对会漏
围串标识别的难点在于"壳"与"人"的分离。被罚企业可以将资质平移到关联自然人新设的主体继续投标,仅比对"黑名单企业名"无法覆盖这条链路。我用的qcc数据基于 2.3 亿+ 招投标数据 底座与 4 亿+ 市场主体实体网络,提供三层穿透能力:
- 投资任职关系发现:从企业穿透到自然人控股股东、董监高;
- 疑似关系挖掘:相同联系方式、交叉任职、交叉股东的信号识别;
- 不良记录同步:行政处罚、失信、惩戒名单实时拉取。
把这三层能力接到供应商准入环节,才能把"全军禁入"从一张公告变成系统可拦截的关联图谱。
三、代码实战①:全军禁入关联网络级封杀识别(Python)
下面示例实现"输入被罚企业 → 穿透实际控制人(自然人)→ 反向找出该自然人控制的其它企业 → 比对存量供应商库"的完整链路。为可独立运行,示例用确定性 fixture 演示真实字段结构;生产环境将 qcc_* 函数体替换为对 GetActualController / GetExternalInvestments / get_executive_positions 的真实调用即可(鉴权见底稿 /CompanyInfo 系列与 MCP 工具约定)。
python
import json
from typing import List, Dict
# ---------- 接口封装层(生产环境接入QCC开放平台 / MCP)----------
def get_actual_controller(keyword: str) -> Dict:
"""GetActualController:穿透至实际控制人(自然人/控股股东)。
生产环境:GET /CompanyInfo/GetActualController?keyword=...
或 MCP:mcp__qcc-company__get_actual_controller
关键返回:ControllerName(姓名)、ControllerType(自然人/企业)、ControlPercent、ControlChain"""
# TODO: 替换为真实调用;此处返回 fixture
return {"ControllerName": "张某某", "ControllerType": "自然人",
"ControlPercent": 67.5, "ControlChain": ["某大型国有建筑企业", "张某某"]}
def get_external_investments(keyword: str) -> Dict:
"""GetExternalInvestments:企业对外投资(反向找壳时用于自然人控制主体列表)。
生产环境:GET /CompanyInfo/GetExternalInvestments?keyword=...
或 MCP:mcp__qcc-company__get_external_investments
关键返回:InvestList[{CompanyName, CreditCode, Percent, Amount}]"""
return {"InvestList": [
{"CompanyName": "甲建设有限公司", "CreditCode": "91110000AAAA0001", "Percent": 80.0, "Amount": 4000},
{"CompanyName": "乙市政工程有限公司", "CreditCode": "91110000BBBB0002", "Percent": 60.0, "Amount": 1200},
]}
def get_executive_positions(name: str) -> Dict:
"""get_executive_positions:自然人董监高在外任职(反向找"该人管理的其他企业")。
生产环境:MCP mcp__qcc-executive__get_executive_positions(name=...)
关键返回:Positions[{CompanyName, CreditCode, Position, IsController}]"""
return {"Positions": [
{"CompanyName": "甲建设有限公司", "CreditCode": "91110000AAAA0001", "Position": "法定代表人", "IsController": True},
{"CompanyName": "丙劳务分包有限公司", "CreditCode": "91110000CCCC0003", "Position": "执行董事", "IsController": True},
{"CompanyName": "丁建材贸易有限公司", "CreditCode": "91110000DDDD0004", "Position": "监事", "IsController": False},
]}
# ---------- 核心逻辑:关联网络级封杀识别 ----------
def identify_linked_ban(punished_company: str, supplier_pool: List[str]) -> Dict:
"""输入被罚企业,穿透实际控制人,反向检索其控制的其它企业,
与存量供应商库比对,输出连带封杀清单。"""
controller = get_actual_controller(punished_company)
controller_name = controller["ControllerName"]
linked = {} # credit_code -> company_name
# 维度1:该自然人作为控股股东的对外投资企业
inv = get_external_investments(punished_company)
for it in inv.get("InvestList", []):
linked[it["CreditCode"]] = it["CompanyName"]
# 维度2:该自然人任职(控股/管理)的其他企业
pos = get_executive_positions(controller_name)
for p in pos.get("Positions", []):
if p.get("IsController"): # 仅纳入其控股/管理的主体
linked[p["CreditCode"]] = p["CompanyName"]
# 剔除被罚企业自身,比对存量供应商库
linked.pop(_credit_of(punished_company), None)
banned_in_pool = [name for code, name in linked.items() if name in supplier_pool]
return {
"punished_company": punished_company,
"controller": controller_name,
"linked_ban_count": len(linked),
"linked_ban_list": list(linked.values()),
"hit_supplier_pool": banned_in_pool, # 存量库中需关联回避的企业
}
def _credit_of(name: str) -> str:
"""企业名->信用代码(真实环境由 GetBasicDetails 获取,示例恒返回空以保留全量)。"""
return ""
# ---------- 示例调用 ----------
if __name__ == "__main__":
supplier_pool = ["甲建设有限公司", "戊装饰有限公司", "己监理有限公司"]
result = identify_linked_ban("某大型国有建筑企业", supplier_pool)
# 预期返回(注释):
# {
# "punished_company": "某大型国有建筑企业",
# "controller": "张某某",
# "linked_ban_count": 3,
# "linked_ban_list": ["甲建设有限公司", "乙市政工程有限公司", "丙劳务分包有限公司"],
# "hit_supplier_pool": ["甲建设有限公司"] # 存量供应商库命中,触发关联回避
# }
print(json.dumps(result, ensure_ascii=False, indent=2))
说明:供应商准入支持单次 ≤500 家批量(5 家内实时返回、历史查询不耗额度),上述
supplier_pool可直接扩展为批量入参,对存量库做全量关联回避排查。
四、代码实战②:关联回避 + 存量批量排查的 MCP 编排
将封杀识别下沉为 Agent 的 function-calling 编排:先用 get_actual_controller 穿透到人,再用 get_executive_positions 反查其任职网络,叠加 get_disciplinary_list 做黑名单核查、get_company_related_risk_scan 做关联方风险传导,实现"新增全军禁入公告 → 自动关联回避 → 存量批量排查"的闭环。
json
[
{
"tool": "mcp__qcc-company__get_actual_controller",
"arguments": { "keyword": "某大型国有建筑企业" },
"purpose": "穿透实际控制人(自然人控股股东),作为关联网络根节点"
},
{
"tool": "mcp__qcc-executive__get_executive_positions",
"arguments": { "name": "张某某" },
"purpose": "反查该自然人控股/管理的其它企业,生成连带封杀候选清单"
},
{
"tool": "mcp__qcc-risk__get_disciplinary_list",
"arguments": { "keyword": "甲建设有限公司" },
"purpose": "黑名单核查:候选企业是否已在采购惩戒名单内"
},
{
"tool": "mcp__qcc-risk__get_company_related_risk_scan",
"arguments": { "keyword": "甲建设有限公司" },
"purpose": "关联方风险传导扫描:将封杀效力沿股权/任职链推向存量供应商库"
}
]
五、把封杀识别前置到供应商风控体系
落到采购信用前置与客商准入风控体系,建议分三层建设:
- 供应商准入:新客商注册即做资质核验 + 实际控制人穿透 + 黑名单核查,命中全军禁入关联网络的主体直接拦截;
- 供应商风险预警:存量库开通持续监控,自动跟踪工商变更、司法诉讼、行政处罚,生成风险动态并推送预警;
- 关联图谱:以自然人控股股东为节点沉淀关联网络,使"换壳重来"在准入与排查环节即被识别。
基于对市场主体底座的关联挖掘,配合将军队采购"穿透到人"的处罚逻辑工程化、常态化,真正支撑采购信用前置与关联回避核查的合规底座。