首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >AI Agent 企业应用不是"能聊就行":集成、权限、审批、审计、成本五道关,附可运行代码

AI Agent 企业应用不是"能聊就行":集成、权限、审批、审计、成本五道关,附可运行代码

原创
作者头像
资源大佬 jzit-top
发布于 2026-10-17 16:03:15
发布于 2026-10-17 16:03:15
590
举报

企业级 Agent 和个人玩具 Agent 的分水岭不在模型多强,而在敢不敢让它碰真实系统。企业落地必须解决五件事:老系统怎么接(集成层)、谁能让它做什么(权限域)、高危操作谁拍板(人工审批)、出了事怎么查(审计脱敏)、烧钱失控怎么办(成本护栏)。下面逐层给可运行代码。

一、统一工具网关:把老系统包成Agent能调的"普通话"

企业系统往往API不统一:ERP是SOAP、CRM是REST、工单系统只有数据库视图。不要在Agent里直接调各系统,先做一层工具网关适配器,统一输入输出契约。

代码语言:javascript
复制
# gateway.py
import httpx
from abc import ABC, abstractmethod

class ToolAdapter(ABC):
    @abstractmethod
    def invoke(self, tenant_id: str, **kwargs) -> dict: ...

class CrmAdapter(ToolAdapter):
    def invoke(self, tenant_id, customer_id, **kw):
        r = httpx.get(f"https://crm.internal/api/customer/{customer_id}",
                      headers={"X-Tenant": tenant_id}, timeout=8)
        r.raise_for_status()
        return {"name": r.json()["name"], "level": r.json()["level"]}

class TicketAdapter(ToolAdapter):
    def invoke(self, tenant_id, title, content, **kw):
        # 老系统只有DB视图,走内部服务封装
        r = httpx.post("http://ticket-svc/internal/create",
                       json={"tenant": tenant_id, "title": title, "content": content},
                       timeout=8)
        return {"ticket_id": r.json()["id"], "status": "created"}

REGISTRY = {"get_customer": CrmAdapter(), "create_ticket": TicketAdapter()}

工程约束:适配器必须透传tenant_id并带超时;输出统一为dict,Agent不感知底层是REST还是SOAP,换系统只换适配器。

二、权限域:工具调用前先过RBAC+数据域

企业最怕Agent越权:A租户的Agent查到B租户数据,普通员工Agent触发财务操作。权限校验必须放在工具网关入口,而不是靠prompt约束。

代码语言:javascript
复制
# authz.py
from functools import wraps

ROLE_PERMS = {
    "support": {"get_customer", "create_ticket"},
    "finance": {"get_customer", "refund"},
    "admin":   {"*"},
}

def authorize(tool_name):
    def deco(fn):
        @wraps(fn)
        def wrapper(ctx, **kwargs):
            role = ctx["role"]; tenant = ctx["tenant_id"]
            perms = ROLE_PERMS.get(role, set())
            if "*" not in perms and tool_name not in perms:
                raise PermissionError(f"角色{role}无权调用{tool_name}")
            # 数据域:强制注入租户过滤,模型无法绕过
            kwargs["tenant_id"] = tenant
            result = fn(ctx, **kwargs)
            # 返回后做数据域二次校验(防越权读)
            assert result.get("tenant_id", tenant) == tenant, "跨租户数据泄漏"
            return result
        return wrapper
    return deco

工程约束:tenant_id由服务端注入,绝不从模型参数里取;返回结果再校验归属,防止上游接口本身越权。权限矩阵要配置化,随组织架构变更而更新。

三、人工审批:高危操作异步中断与恢复

退款、删数据、发通知这类操作,Agent不能直接执行。用"中断-持久化-审批-恢复"模式,而不是同步阻塞等人工。

代码语言:javascript
复制
# approval.py
import json, uuid

def execute_with_approval(ctx, tool_name, args, db):
    if tool_name in {"refund", "delete_user", "send_bulk_notice"}:
        approval_id = str(uuid.uuid4())
        db.approvals.insert_one({
            "approval_id": approval_id, "tenant": ctx["tenant_id"],
            "tool": tool_name, "args": args, "status": "PENDING",
            "agent_state": ctx["serialized_state"],   # 关键:保存Agent上下文
        })
        return {"status": "PENDING_APPROVAL", "approval_id": approval_id}
    return REGISTRY[tool_name].invoke(**args)          # 低危直接执行

def resume_after_approval(approval_id, approved, db):
    rec = db.approvals.find_one({"approval_id": approval_id})
    if rec["status"] != "PENDING": return
    if not approved:
        db.approvals.update_one({"approval_id": approval_id}, {"$set": {"status": "REJECTED"}})
        return
    REGISTRY[rec["tool"]].invoke(**rec["args"])        # 审批通过才执行
    db.approvals.update_one({"approval_id": approval_id}, {"$set": {"status": "APPROVED"}})
    # Agent从持久化状态恢复,继续后续步骤

工程约束:审批期间Agent状态必须持久化,否则进程重启任务丢失;审批通过后执行前要二次校验幂等,防重复点击。

四、审计与脱敏:每一步可查,敏感字段不出域

代码语言:javascript
复制
# audit.py
import re, hashlib

PII = [r"\d{17}[\dXx]", r"1[3-9]\d{9}", r"[\w.]+@[\w.]+"]

def mask(text: str) -> str:
    for p in PII:
        text = re.sub(p, lambda m: hashlib.sha256(m.group().encode()).hexdigest()[:8], text)
    return text

def audit_log(span: dict):
    # 每步落:租户、角色、工具、参数摘要(脱敏)、结果状态、耗时、token
    span["args"] = mask(json.dumps(span.get("args", {}), ensure_ascii=False))
    span["result_summary"] = mask(str(span.get("result"))[:200])
    db.audit.insert_one(span)

工程约束:审计日志要防篡改(追加写、定期归档到对象存储);脱敏在日志出口做,不能只在展示层做;原始敏感数据设保留期限,到期自动清理。

五、成本护栏与降级:预算、路由、熔断

代码语言:javascript
复制
# cost.py
BUDGET = {"tenant_daily": 50.0}   # 美元
PRICE = {"gpt-4o": 0.005, "gpt-4o-mini": 0.0005}

def route_model(tenant_id, task_complexity):
    spent = db.usage.aggregate_today(tenant_id)
    if spent > BUDGET["tenant_daily"] * 0.8:      # 超80%降级
        return "gpt-4o-mini"
    return "gpt-4o" if task_complexity == "high" else "gpt-4o-mini"

def check_circuit(tenant_id):
    fails = db.metrics.recent_fail_rate(tenant_id, window="5m")
    if fails > 0.3:
        raise RuntimeError("熔断:近期失败率过高,转人工")

工程约束:预算按租户+日维度控制,超限降级而非直接拒绝;熔断要联动人工兜底队列,不能静默失败。

六、评测与灰度:业务指标比准确率更重要

代码语言:javascript
复制
# eval_enterprise.py
CASES = [{"goal":"查客户C001等级","expect_tool":"get_customer","expect_kw":"VIP"}]

def evaluate(agent_fn, tenant):
    hit = tool_ok = 0
    for c in CASES:
        ans, trace = agent_fn(c["goal"], tenant=tenant)
        hit += c["expect_kw"] in ans
        tool_ok += any(t.get("tool")==c["expect_tool"] for t in trace)
    return {"answer_hit": hit/len(CASES), "tool_acc": tool_ok/len(CASES)}

企业评测还要加越权测试集(故意诱导跨租户查询,必须全部拒绝)和审批绕过测试集(高危操作必须返回PENDING)。上线先跑影子模式:Agent只给建议不执行,与人工结果对比,达标再逐步放量。

总结:AI Agent 企业应用的专业度不在prompt,而在工具网关统一集成、权限域服务端强制注入、高危操作异步审批、全链路审计脱敏、预算熔断降级、越权与审批评测、影子灰度这七件事。能给别人讲清楚"为什么tenant_id绝不能从模型参数取""审批期间Agent状态为什么要持久化",你就抓住了企业落地的命门。觉得有用点赞收藏,需要完整工程目录留言。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、统一工具网关:把老系统包成Agent能调的"普通话"
  • 二、权限域:工具调用前先过RBAC+数据域
  • 三、人工审批:高危操作异步中断与恢复
  • 四、审计与脱敏:每一步可查,敏感字段不出域
  • 五、成本护栏与降级:预算、路由、熔断
  • 六、评测与灰度:业务指标比准确率更重要
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档