企业级 AI Agent 执行控制与审计架构:Skill 治理、工具代理与多源审计管控

72 阅读19分钟

摘要

随着 AI Agent 从内容生成走向任务执行,其安全治理重点也随之发生变化。对于企业场景而言,真正需要控制的不只是模型输出本身,而是 Skill 如何接入、如何加载、如何调用工具、如何访问业务系统、是否存在执行旁路、是否能够被审计,以及出现异常后是否具备可操作的处置机制。对于具备文件访问、接口调用、业务编排和自动处理能力的 Agent,如果缺乏统一治理,往往会引入越权访问、执行绕行、代码篡改、身份伪造、日志失真和审计缺失等问题。 本文讨论一套面向企业业务落地过程的 AI Agent 执行控制与审计架构。该架构以 Security Core、ToolProxy 与业务侧多源日志为核心,通过 Skill 白名单、AST 插桩、插桩后完整性校验、访问票据、统一工具代理以及多源核验机制,将 Skill 的接入、加载、执行、调用与审计纳入统一治理链路。整体目标不是覆盖全部 AI 安全议题,而是围绕企业最关心的执行过程,建立一条可控、可查、可核验、可分级处置的治理主链路。

一、整体架构:设计目标、原则与作用逻辑

1. 设计目标

企业环境中的 AI Agent 往往不只是生成文本,而是通过 Skill 调用文件系统、数据库、HTTP 接口、内部服务和业务系统,从而完成检索、编排、写入、审批、同步等操作。在这一过程中,企业真正需要纳入治理的,不只是“模型生成了什么”,更是“执行了什么、访问了什么、是否在授权范围内、是否可以被追溯”。 围绕这一目标,执行控制与审计架构需要满足以下要求: Skill 的执行边界必须明确定义; 工具调用路径必须统一收口; Skill 的身份和代码状态必须可以验证; 执行结果必须可以被交叉核验; 异常行为必须能够分级处置。

2. 设计原则

整套架构遵循以下原则: 安全前置。 治理从 Skill 安装与加载阶段开始,而不是等运行结束后再做补充审计。 最小权限。 Skill 只允许访问其声明范围内的工具、路径、域名、接口和业务动作。 统一出口。 涉及文件、网络、数据库、命令执行等关键能力时,应统一通过 ToolProxy 访问,而不是由 Skill 直接访问底层资源。 可信校验。 平台信任的对象不是开发者最初上传的原始 Skill 包,而是完成 AST 插桩并通过完整性登记的受控运行版本。 分级裁决。 多源核验结果用于风险等级判断与后续处置,而不是将所有不一致直接等同为强阻断。

3. 架构的作用逻辑

从执行链路来看,这套架构的作用逻辑非常明确: Skill 在接入前先声明可执行边界; Security Core 在安装或加载阶段对 Skill 做 AST 插桩或等效改写; 插桩后的受控产物完成完整性登记; Security Core 为符合条件的 Skill 分发短周期访问票据; Skill 在执行过程中只能通过 ToolProxy 调用工具和业务接口; 业务系统入口只接受来自 ToolProxy 的受控流量; Security Core 汇总 Skill 声明、ToolProxy 日志和业务日志,完成多源核验与分级裁决。 换句话说,这套架构不是单纯增加一层日志,而是在 Skill 的执行路径上建立从“前置受管化”到“运行期访问控制”再到“结果核验与处置”的完整闭环。 换句话说,这套架构不是单纯增加一层日志,而是在 Skill 的执行路径上建立从“前置受管化”到“运行期访问控制”再到“结果核验与处置”的完整闭环。

11111111111111.png

二、核心组件与核心安全机制

1. Security Core

Security Core 是整套架构的安全控制中枢。它不是普通 Skill,也不只是审计页面,而是 Agent 执行体系中的控制平面。其核心职责包括: Skill 白名单与版本状态管理; Skill 声明管理; AST 插桩或等效改写; 插桩后受控产物的完整性登记与校验; 访问票据的签发、轮转与吊销; 对 ToolProxy 的策略判定支持; 对 Skill 声明、代理日志与业务日志的多源核验与分级裁决。 Security Core 管理和校验的对象,应是插桩后的受控产物,而不是原始上传文件。因为真正进入执行面的,是被治理后的运行版本。

2. ToolProxy

ToolProxy 是统一工具代理层,用于承接 Skill 的文件访问、网络访问、数据库访问和其他敏感能力调用。它并不是简单转发,而是在请求真正触达底层资源之前执行统一鉴权、权限判断和标准化留痕。 ToolProxy 需要至少具备以下能力: 校验短周期访问票据; 校验 Skill ID、实例 ID、版本状态; 校验调用目标是否位于声明和策略允许范围内; 对高风险动作执行同步决策; 输出标准化代理日志; 对越权、无票据、伪造身份或状态异常的调用直接拒绝。

3. 业务侧日志

业务侧日志是外部事实来源,用于回答代理层发起的调用是否真实到达,以及最终落地动作是否与受控边界一致。业务日志可以来自 API 网关、数据库审计、文件服务、审批系统、工单系统或业务服务本身。

4. 核心安全机制

整套架构的核心不在某个单独组件,而在机制之间的联动: 声明约束机制:先定义 Skill 的合法边界; AST 插桩机制:将原始 Skill 改写为受控执行体; 完整性机制:确保运行时没有被替换或篡改; 票据机制:让访问代理建立在短期可信身份之上; 统一代理机制:确保调用路径可见、可控、可留痕; 多源核验机制:将声明、代理日志和业务日志形成闭环证据链。

三、整体执行流程

1. Skill 生命周期管理流程

第一步:提交结构化声明

Skill 在进入执行体系前,需要提交结构化声明。声明建议至少包括: Skill ID、版本、发布者; 允许调用的工具集合; 允许访问的路径、域名、资源标识; 风险等级; 资源边界,如执行时长、并发限制、内存限制; 是否需要审批的动作类型; 审计字段要求。

第二步:Security Core 执行 AST 插桩

在安装或加载阶段,由 Security Core 对 Skill 执行 AST 插桩或等效改写。插桩的目标不是简单加日志,而是完成受控执行改造,通常至少包括: 将原始文件、网络、数据库等敏感能力访问替换为通过 ToolProxy 调用; 将票据承载点和运行上下文注入到调用路径; 在关键调用点、异常分支和返回点增加标准化事件上报逻辑。

第三步:插桩后完整性登记

Skill 完成插桩后,平台需要对受控版本计算摘要,并登记以下信息: Skill ID 与版本; 插桩后摘要; 声明摘要; 允许的代理调用模板; 当前状态; 票据签发策略。 完整性校验的基准必须是插桩后的受控产物,而不是原始代码文件。

第四步:加载前校验

Skill 进入加载态或执行态前,Security Core 需要校验: 当前版本是否仍在白名单内; 当前摘要是否与登记值一致; 当前运行环境是否符合要求; 当前策略版本是否有效; 当前 Skill 是否具备申请访问票据的资格。

第五步:票据分发与轮转

对于通过校验的 Skill,Security Core 分发短周期访问票据。票据建议绑定以下信息: Skill ID; 版本; 实例 ID; 有效期; 可选的策略版本或声明摘要; 可选的会话 ID、任务 ID。 票据不应被固化在原始 Skill 源码中,而应在受控运行上下文中动态注入。

2. ToolProxy 实现流程

Skill 发起工具调用时,请求统一进入 ToolProxy。ToolProxy 典型处理流程如下: 接收调用请求; 提取 Skill 身份、实例信息和访问票据; 验证票据签名和有效期; 查询 Security Core 中当前 Skill 的状态与摘要校验结果; 判断本次调用目标是否在声明和策略允许范围内; 对高风险动作执行同步判定; 对低风险动作执行代理放行; 记录标准化代理日志; 将结果和上下文异步上报至 Security Core。

3. 无旁路保证:业务只接受来自 ToolProxy 的流量

ToolProxy 是否真正具备控制意义,取决于业务系统是否只接受来自 ToolProxy 或受信入口的流量。仅有 AST 插桩和代理层,并不足以保证强控制。如果业务系统仍允许 Skill 所在执行环境直接访问底层接口,那么旁路风险始终存在。 因此,业务侧需要落实明确的入口约束: 业务接口只开放给 ToolProxy 所在网段或服务身份; 业务系统通过 mTLS、服务账户、HMAC 签名或专用网关校验调用来源; 业务服务不接受来自 Skill 容器、沙箱或普通执行节点的直接流量; 高风险业务动作必须通过 ToolProxy 代发。 这部分是整套架构中非常关键的控制点。只有当业务侧明确“只接受来自 ToolProxy 的调用”,ToolProxy 才是工程上真正成立的执行门禁。

四、Security Core 和 ToolProxy 的安全保障机制

1. Security Core 的安全保障

Security Core 应独立于普通 Skill 部署,不作为可被随意替换的插件运行,而应由框架主进程或平台控制面优先启动。其安全保障重点包括: 自身完整性校验; 配置签名或摘要校验; 最小接口暴露; 独立日志通道; 核心功能不可被普通业务面关闭; 异常状态具备告警与降级机制。 若 Security Core 本身被篡改或静默失效,整个执行控制链路将失去可信基础。

2. ToolProxy 的安全保障

ToolProxy 需要重点防范以下风险:

身份伪造

仅凭一个 skill_name 不足以标识合法调用。建议至少校验: Skill ID; 实例 ID; 访问票据; 时间戳; 策略版本或声明摘要; 可选签名字段。

重放攻击

票据必须具备时效性,必要时结合 nonce、请求签名和幂等键防止重放。

越权访问

权限判断不能停留在“工具级”,还应细化到: 文件路径; 域名; HTTP 方法; 资源标识; 数据对象; 操作风险等级。

日志失真

ToolProxy 日志至少应包含: 请求前记录; 判定结果; 执行结果; 失败原因; 关联上下文标识。 否则多源核验阶段无法形成稳定证据链。

五、分级管理机制

多源核验的目标不是做一组被动日志对账,而是输出可落地的风险等级和处置动作。考虑到业务日志可能存在延迟、字段缺失和聚合差异,不宜将所有不一致都直接视为唯一实时阻断证据。

1. 轻微异常

包括: 非关键字段缺失; 低风险参数存在偏差; 业务日志短时未到齐; 时序存在轻微错位。 对应处置: 记录异常; 触发告警; 纳入后续观察; 不直接影响当前任务。

2. 中等异常

包括: 代理日志与业务日志持续不一致; 调用目标偏离声明范围但未触及高危资源; 票据多次校验失败; 低风险接口出现跨边界访问尝试。 对应处置: 触发人工确认或审批; 暂时限制部分权限; 提升监控等级; 对后续步骤做附加校验。

3. 严重异常

包括: 插桩后完整性校验失败; 无票据访问; 身份伪造; 高危工具越权调用; 业务系统确认收到非 ToolProxy 来源的敏感访问。 对应处置: 中止当前执行; 冻结相关 Skill 权限; 吊销票据; 触发事件升级与溯源处理。

六、技术落地可行性判断与评估

从工程角度看,Skill 声明管理、AST 插桩、插桩后摘要计算、票据签发、ToolProxy 统一代理和规则化分级裁决都属于相对成熟的技术能力。真正的实施难点通常集中在以下几个方面: 多语言 Skill 的统一插桩; 存量 Skill 的迁移与适配; 业务日志格式标准化; 业务系统入口收口; 执行环境旁路能力的收敛。 因此,这套架构的价值不在于“绝对安全”,而在于在企业既有基础设施之上,构建一条清晰的受控执行主链路。较为稳妥的落地路径通常是分阶段推进:先实现 Skill 声明、AST 插桩和 ToolProxy 统一代理,再引入完整性校验与票据机制,随后接入业务日志,最终形成多源核验和分级处置闭环。

七、演示代码

下面的代码是演示骨架,目标是体现模块关系和控制逻辑,而不是直接作为生产代码使用。示例语言使用 Python,按模块拆分如下:

agent_control_demo/
├── manifest.py
├── integrity.py
├── instrumentor.py
├── ticket.py
├── security_core.py
├── tool_proxy.py
├── business_system.py
└── demo.py

1. manifest.py:Skill 声明结构

from dataclasses import dataclass, field
from typing import List, Dict


@dataclass
class SkillManifest:
    skill_id: str
    version: str
    allowed_tools: List[str]
    allowed_paths: List[str] = field(default_factory=list)
    allowed_domains: List[str] = field(default_factory=list)
    risk_level: str = "medium"
    max_execution_time: int = 30
    extra: Dict = field(default_factory=dict)

作用:定义 Skill 的结构化声明,作为 AST 插桩、完整性登记、ToolProxy 权限判断和多源核验的基准。

2. integrity.py:完整性计算

import hashlib
import os


def sha256_text(content: str) -> str:
    return hashlib.sha256(content.encode("utf-8")).hexdigest()


def sha256_file(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        while chunk := f.read(8192):
            h.update(chunk)
    return h.hexdigest()


def sha256_dir(root: str) -> str:
    h = hashlib.sha256()
    for base, _, files in os.walk(root):
        for name in sorted(files):
            full_path = os.path.join(base, name)
            h.update(full_path.encode("utf-8"))
            with open(full_path, "rb") as f:
                while chunk := f.read(8192):
                    h.update(chunk)
    return h.hexdigest()

作用:对插桩后的 Skill 产物计算摘要,并将其作为 Security Core 可信登记和运行时校验的基准。

3. instrumentor.py:AST 插桩器

import ast


class ToolProxyRewriter(ast.NodeTransformer):
    """
    简化示例:
    将 open(path) 改写为 toolproxy.file_open(path, ticket_ctx=...)
    生产中通常需要覆盖 requests、subprocess、数据库驱动等更多模式。
    """

    def visit_Call(self, node: ast.Call):
        self.generic_visit(node)

        if isinstance(node.func, ast.Name) and node.func.id == "open":
            if len(node.args) >= 1:
                return ast.Call(
                    func=ast.Attribute(
                        value=ast.Name(id="toolproxy", ctx=ast.Load()),
                        attr="file_open",
                        ctx=ast.Load()
                    ),
                    args=node.args,
                    keywords=[
                        ast.keyword(
                            arg="ticket_ctx",
                            value=ast.Name(id="ticket_ctx", ctx=ast.Load())
                        )
                    ]
                )

        return node


def instrument_code(source: str) -> str:
    tree = ast.parse(source)
    tree = ToolProxyRewriter().visit(tree)
    ast.fix_missing_locations(tree)
    return ast.unparse(tree)

作用:在 Skill 安装或加载阶段,将直接访问底层能力的代码改写为通过 ToolProxy 访问,并为运行时上下文预留插入点。

4. ticket.py:访问票据签发与校验

import time
import hmac
import json
import base64
import hashlib


class TicketService:
    def __init__(self, secret: str):
        self.secret = secret.encode("utf-8")

    def issue_ticket(self, skill_id: str, version: str, instance_id: str, ttl_seconds: int = 300) -> str:
        payload = {
            "skill_id": skill_id,
            "version": version,
            "instance_id": instance_id,
            "exp": int(time.time()) + ttl_seconds
        }
        raw = json.dumps(payload, separators=(",", ":"), sort_keys=True).encode("utf-8")
        sig = hmac.new(self.secret, raw, hashlib.sha256).hexdigest()
        token = {
            "payload": base64.urlsafe_b64encode(raw).decode("utf-8"),
            "sig": sig
        }
        return base64.urlsafe_b64encode(json.dumps(token).encode("utf-8")).decode("utf-8")

    def verify_ticket(self, token_str: str) -> dict | None:
        try:
            token = json.loads(base64.urlsafe_b64decode(token_str.encode("utf-8")).decode("utf-8"))
            raw = base64.urlsafe_b64decode(token["payload"].encode("utf-8"))
            sig = hmac.new(self.secret, raw, hashlib.sha256).hexdigest()
            if not hmac.compare_digest(sig, token["sig"]):
                return None
            payload = json.loads(raw.decode("utf-8"))
            if payload["exp"] < int(time.time()):
                return None
            return payload
        except Exception:
            return None

作用:由 Security Core 为合法 Skill 实例发放短周期访问票据,ToolProxy 在运行期用票据建立可信身份链路。

5. security_core.py:Security Core

from dataclasses import asdict
from typing import Dict, Any
from manifest import SkillManifest
from integrity import sha256_text
from ticket import TicketService


class SecurityCore:
    def __init__(self, secret: str):
        self.ticket_service = TicketService(secret)
        self.skill_registry: Dict[str, Dict[str, Any]] = {}
        self.proxy_logs = []
        self.biz_logs = []

    def register_instrumented_skill(
        self,
        manifest: SkillManifest,
        instrumented_code: str
    ) -> dict:
        code_hash = sha256_text(instrumented_code)
        self.skill_registry[manifest.skill_id] = {
            "manifest": asdict(manifest),
            "instrumented_hash": code_hash,
            "status": "active"
        }
        return {
            "skill_id": manifest.skill_id,
            "instrumented_hash": code_hash
        }

    def verify_skill_state(self, skill_id: str, current_hash: str) -> bool:
        item = self.skill_registry.get(skill_id)
        if not item:
            return False
        if item["status"] != "active":
            return False
        return item["instrumented_hash"] == current_hash

    def issue_access_ticket(self, skill_id: str, instance_id: str) -> str:
        item = self.skill_registry.get(skill_id)
        if not item or item["status"] != "active":
            raise ValueError("skill not active")
        version = item["manifest"]["version"]
        return self.ticket_service.issue_ticket(skill_id, version, instance_id, ttl_seconds=300)

    def check_permission(self, skill_id: str, tool_name: str, target: str) -> bool:
        item = self.skill_registry.get(skill_id)
        if not item:
            return False

        manifest = item["manifest"]
        if tool_name not in manifest["allowed_tools"]:
            return False

        if tool_name.startswith("file_"):
            return any(target.startswith(p.rstrip("*")) for p in manifest["allowed_paths"])

        if tool_name.startswith("http_"):
            return any(target.startswith(d) for d in manifest["allowed_domains"])

        return True

    def append_proxy_log(self, log: dict):
        self.proxy_logs.append(log)

    def append_biz_log(self, log: dict):
        self.biz_logs.append(log)

    def adjudicate(self, skill_id: str, tool_name: str, target: str) -> dict:
        related_proxy = [
            x for x in self.proxy_logs
            if x["skill_id"] == skill_id and x["tool"] == tool_name and x["target"] == target
        ]
        related_biz = [
            x for x in self.biz_logs
            if x["skill_id"] == skill_id and x["tool"] == tool_name and x["target"] == target
        ]

        if not related_proxy:
            return {"level": "high", "action": "block", "reason": "missing proxy log"}

        if not related_biz:
            return {"level": "medium", "action": "confirm", "reason": "missing business log"}

        return {"level": "low", "action": "allow", "reason": "matched"}

作用:承担 Skill 受控登记、完整性校验、票据发放、权限判断和多源核验的核心控制逻辑。

6. tool_proxy.py:ToolProxy

from integrity import sha256_text


class ToolProxy:
    def __init__(self, security_core):
        self.security = security_core

    def _verify_context(self, ticket_ctx: dict) -> tuple[bool, str]:
        ticket = ticket_ctx.get("ticket")
        current_code = ticket_ctx.get("instrumented_code", "")
        ticket_payload = self.security.ticket_service.verify_ticket(ticket)
        if not ticket_payload:
            return False, "invalid ticket"

        skill_id = ticket_payload["skill_id"]
        current_hash = sha256_text(current_code)

        if not self.security.verify_skill_state(skill_id, current_hash):
            return False, "skill integrity check failed"

        return True, skill_id

    def file_open(self, path: str, ticket_ctx: dict) -> str:
        ok, result = self._verify_context(ticket_ctx)
        if not ok:
            raise PermissionError(result)

        skill_id = result
        if not self.security.check_permission(skill_id, "file_read", path):
            raise PermissionError("permission denied")

        proxy_log = {
            "skill_id": skill_id,
            "tool": "file_read",
            "target": path,
            "result": "allow"
        }
        self.security.append_proxy_log(proxy_log)

        with open(path, "r", encoding="utf-8") as f:
            return f.read()

    def http_get(self, url: str, ticket_ctx: dict) -> dict:
        ok, result = self._verify_context(ticket_ctx)
        if not ok:
            raise PermissionError(result)

        skill_id = result
        if not self.security.check_permission(skill_id, "http_get", url):
            raise PermissionError("permission denied")

        proxy_log = {
            "skill_id": skill_id,
            "tool": "http_get",
            "target": url,
            "result": "allow"
        }
        self.security.append_proxy_log(proxy_log)

        return {"status": 200, "data": f"mock response from {url}"}

作用:实现工具统一代理,对请求执行票据校验、完整性状态校验和资源边界判断。

7. business_system.py:业务系统只接受来自 ToolProxy 的访问

class BusinessSystem:
    def __init__(self, security_core):
        self.security = security_core

    def receive_proxy_call(self, skill_id: str, tool: str, target: str, source: str = "toolproxy"):
        if source != "toolproxy":
            raise PermissionError("only toolproxy traffic is accepted")

        biz_log = {
            "skill_id": skill_id,
            "tool": tool,
            "target": target,
            "source": source
        }
        self.security.append_biz_log(biz_log)
        return {"ok": True}

作用:在演示中模拟“业务侧只接受 ToolProxy 来源流量”的设计要求。生产环境中,这一约束通常应由网络 ACL、mTLS、服务身份、专用网关或签名机制实现,而不是像示例一样仅通过参数判断。

8. demo.py:最小执行闭环

from manifest import SkillManifest
from instrumentor import instrument_code
from security_core import SecurityCore
from tool_proxy import ToolProxy
from business_system import BusinessSystem

RAW_SKILL = """
def run():
    return open('/tmp/demo.txt').read()
"""

def main():
    manifest = SkillManifest(
        skill_id="skill_file_reader",
        version="1.0.0",
        allowed_tools=["file_read"],
        allowed_paths=["/tmp/"],
        allowed_domains=[]
    )

    # 1. 初始化 Security Core、ToolProxy、业务系统
    security = SecurityCore(secret="demo-secret")
    proxy = ToolProxy(security)
    biz = BusinessSystem(security)

    # 2. AST 插桩
    instrumented = instrument_code(RAW_SKILL)

    # 3. 登记插桩后的受控 Skill
    security.register_instrumented_skill(manifest, instrumented)

    # 4. 发放票据
    instance_id = "inst-001"
    ticket = security.issue_access_ticket(manifest.skill_id, instance_id)

    # 5. 运行时上下文
    ticket_ctx = {
        "ticket": ticket,
        "instrumented_code": instrumented
    }

    # 6. Skill 通过 ToolProxy 访问文件
    try:
        content = proxy.file_open("/tmp/demo.txt", ticket_ctx)
        print("proxy result:", content)

        # 7. 业务系统只接受 ToolProxy 来源流量
        biz.receive_proxy_call(
            skill_id=manifest.skill_id,
            tool="file_read",
            target="/tmp/demo.txt",
            source="toolproxy"
        )

        # 8. Security Core 做多源核验
        decision = security.adjudicate(
            skill_id=manifest.skill_id,
            tool_name="file_read",
            target="/tmp/demo.txt"
        )
        print("decision:", decision)

    except Exception as e:
        print("error:", str(e))


if __name__ == "__main__":
    main()

这段演示代码体现了完整闭环: Skill 提交结构化声明; Security Core 对 Skill 做 AST 插桩; 对插桩后的受控版本做摘要登记; Security Core 发放短周期票据; Skill 在运行期通过 ToolProxy 调用工具; ToolProxy 校验票据和完整性状态; 业务系统只接受来自 ToolProxy 的访问; Security Core 汇总代理日志和业务日志执行核验并输出裁决结果。 这也对应了整套架构最核心的思想:Skill 的安全治理不是停留在上线前审核,而是贯穿安装、加载、执行、调用、审计和裁决整个生命周期。

八、总结

企业级 AI Agent 的治理重点,正在从“模型输出管理”延伸到“执行过程控制”。当 Agent 已经能够通过 Skill 调用工具、访问资源并推动业务落地时,仅依赖 Prompt 约束或单一日志审计,往往不足以支撑企业级安全要求。 围绕 Skill 治理、ToolProxy 统一代理和多源审计管控建立执行控制链路,有助于将企业最关心的部分——即业务执行过程本身——纳入一套清晰、可验证、可分级处置的体系之中。其核心逻辑可以概括为:先定义边界,再完成插桩与完整性登记;先建立可信身份,再允许代理访问;最后用多源事实对执行结果进行核验,并按风险等级实施处置。对于需要在企业环境中稳步引入 AI Agent 的组织而言,这是一条更接近真实落地需求的治理路径。

需要说明的是,本架构的有效性建立在一定前提之上。例如,Agent 需要运行在企业可控的宿主、容器或沙箱环境中;系统具备基础的身份体系、策略体系与日志体系;业务侧能够提供最基本的接口、资源或访问行为留痕。对于完全无运行时控制能力、完全依赖 Prompt 层约束、或仅依靠模型自身对齐能力的场景,本文所述架构并不直接适用。