AI 工具

Microsoft 365 Copilot 连接器:校验 externalItem JSON

通过 Graph 连接器把外部知识喂给 Microsoft 365 Copilot 时,条目形如 externalItem:必有 id、properties、acl,体积有上限(文档约 30MB)。本篇只做 JSON 形状校验。

BINBHO · 图文教程

通过 Graph 连接器把外部知识喂给 Microsoft 365 Copilot 时,条目形如 externalItem:必有 id、properties、acl,体积有上限(文档约 30MB)。本篇只做 JSON 形状校验。

先看清成品

  • sample_ok → OK;缺 id/acl 的 bad → INVALID。
  • 3 项 pytest 通过。

合规提醒:个人 Copilot 与 Microsoft 365 Copilot 是不同产品;企业场景用公司账号并遵守组织数据政策。不要把密钥、客户名单、未公开财报等粘贴进个人版聊天。Graph 连接器写入的外部内容受 ACL 约束;错误开放等于数据泄露。本文不编造价格。

运行说明:无 Microsoft 365 / Graph 租户密钥。三篇均为本地离线助手:A 从会议记录抽待办;B 粘贴前 DLP 启发式扫描;C 校验 externalItem 形状。未调用官方聊天 API(消费级 Copilot 无通用「随便调」的公开 chat API)。2026-10-23(Asia/Shanghai)pytest 通过。

做完之后你会得到什么?

成果 说明
external_item_check.py 形状校验
样例 JSON ok/bad
test_102c.py 测试

需要准备哪些环境?

项目 说明
Python 3.10+

关键事实

事实 来源
externalItem 含 acl,决定谁能在 Copilot 里看见 官方 Graph 文档
单项大小上限约 30 MB(以 Graph 文档为准) 官方
本校验不调用 Graph,不能代替连接器注册与权限配置 重要

文件结构

102-microsoft-copilot-C-src/
├── external_item_check.py
├── sample_ok.json
├── sample_bad.json
└── test_102c.py

第 1 步:校验脚本

#!/usr/bin/env python3
"""Validate a Microsoft 365 Copilot connector externalItem-shaped JSON (offline)."""
from __future__ import annotations

import argparse
import json
from pathlib import Path

MAX_BYTES = 30 * 1024 * 1024  # Graph docs: max externalItem size 30 MB


def validate(item: dict) -> list[str]:
    errs = []
    if "id" not in item or not str(item.get("id") or "").strip():
        errs.append("id 必填(外部系统主键)")
    props = item.get("properties")
    if props is None:
        errs.append("properties 必填")
    elif not isinstance(props, dict):
        errs.append("properties 须为对象")
    acl = item.get("acl") or item.get("accessControlList")
    if acl is None:
        errs.append("acl 必填(谁能看见这条外部内容)")
    elif isinstance(acl, list):
        for i, ace in enumerate(acl):
            if not isinstance(ace, dict):
                errs.append(f"acl[{i}] 须为对象")
                continue
            if not ace.get("type") or not ace.get("value"):
                errs.append(f"acl[{i}] 需要 type 与 value")
            if ace.get("accessType") not in (None, "grant", "deny"):
                errs.append(f"acl[{i}].accessType 非法")
    else:
        errs.append("acl 须为数组")
    raw = json.dumps(item, ensure_ascii=False).encode()
    if len(raw) > MAX_BYTES:
        errs.append(f"序列化后超过 30MB 限制({len(raw)} bytes)")
    # content
    content = item.get("content")
    if content is not None:
        if not isinstance(content, dict) or "value" not in content:
            errs.append("content 应含 value(及可选 type)")
    return errs


def main(argv=None) -> int:
    ap = argparse.ArgumentParser(description=__doc__)
    ap.add_argument("item_json")
    args = ap.parse_args(argv)
    item = json.loads(Path(args.item_json).read_text(encoding="utf-8"))
    errs = validate(item)
    if errs:
        print("INVALID")
        for e in errs:
            print("-", e)
        return 1
    print("OK")
    print(json.dumps({"id": item.get("id"), "acl_entries": len(item.get("acl") or [])}, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

第 2 步:测试

from pathlib import Path
import json, subprocess, sys
from external_item_check import validate
HERE = Path(__file__).resolve().parent

def test_ok():
    assert validate(json.loads((HERE/"sample_ok.json").read_text())) == []

def test_bad():
    assert validate(json.loads((HERE/"sample_bad.json").read_text()))

def test_cli():
    r = subprocess.run([sys.executable, str(HERE/"external_item_check.py"), str(HERE/"sample_ok.json")], capture_output=True, text=True)
    assert r.returncode == 0

第 3 步:运行

$ python external_item_check.py sample_ok.json
OK
{"id": "kb-42", "acl_entries": 1}

$ python external_item_check.py sample_bad.json
INVALID
- id 必填(外部系统主键)
- acl[0] 需要 type 与 value

$ pytest -q
...                                                                      [100%]
3 passed in 0.03s

怎么检查结果?

  • OK 样例通过。
  • bad 指出 id 或 acl 问题。

调试示例

acl 写成全公司 Everyone 图省事。 校验只查字段存在;过宽 ACL 是安全事故。按部门/用户最小权限建模。

常见问题

现象 原因 处理
没有 Graph 权限 本篇仍可练形状 上线需管理员同意
content 怎么放 properties / content 字段 以当前 Graph 文档为准
30MB 教程软检查 超限请切片

模板规则

  • ACL 默认拒绝,显式授权。
  • 勿索引无授权数据源。
  • 变更连接器要审计。

项目资源

用途 地址
externalItem 资源(官方) https://learn.microsoft.com/en-us/graph/api/resources/externalconnectors-externalitem
管理外部项(官方) https://learn.microsoft.com/en-us/graph/connecting-external-content-manage-items
Copilot 扩展性概览(官方) https://learn.microsoft.com/en-us/microsoft-365-copilot/extensibility/overview

形状对了,还要 ACL 对——否则 Copilot 会「帮你泄密」。