EU AI Act 合规:面向 AI 智能体的人工监督

OpenRouter:Announcements(RSS)·2026-06-08 20:00·104天前·Kenny Rogers
AI 导读

使用智能体 SDK 的人机协作(HITL)工具,可满足 EU AI Act、Colorado AI Act 和 NIST AI RMF 对 AI 智能体的合规要求。

OpenRouter:Announcements(RSS)
精选
66AI 编辑部评分,满分 100

EU AI Act 合规:面向 AI 智能体的人工监督

2026-06-08 20:00· 104天前· Kenny Rogers
AI 导读

使用智能体 SDK 的人机协作(HITL)工具,可满足 EU AI Act、Colorado AI Act 和 NIST AI RMF 对 AI 智能体的合规要求。

推荐理由

虽然讲的是合规,但直接把监管要求翻译成可落地的代码模式,对做高风险Agent的团队来说是一份照着改就能过审的实操手册。

正文 · AI 翻译

AI 智能体不再只是回答问题。它们在审批贷款申请、分诊患者入院表单、计算工资、决定谁被标记进入欺诈审查。当其中某一次判断出错时,责任落在部署者身上。

监管已经跟上了。第一个硬性截止日期在 2026 年 8 月,如果你正在构建涉及金融服务、医疗、招聘、或任何错误输出会对真实的人造成真实后果的领域的智能体,合规倒计时已经开始。

三项法规指向同一项义务:必须有人能够监督、干预并覆盖影响人类的 AI 驱动决策。Agent SDK 今天就提供了把这些控制接入你的智能体所需的基础组件。

法规 生效时间 适用对象 核心要求
EU AI Act(欧盟人工智能法案),第 14 条 2026 年 8 月(高风险义务) 任何为欧盟居民提供高风险 AI 系统的提供者或部署者,无论公司位于何处。 人类监督,并具备干预和覆盖的能力。需保留监督行动的审计轨迹。
科罗拉多州 ADMT 法案(SB26-189) 2027 年 1 月 在科罗拉多州开展业务的任何开发者或部署者,包括对科罗拉多州居民做出重大决定(consequential decisions)的州外公司。 当受监管的 ADMT 对重大决定产生实质影响时,受监管的开发者/部署者必须提供文档、信息披露、消费者权利流程,以及有意义的人工审查/复议机制。
NIST AI RMF(GOVERN 1) 自愿性框架,被美国监管机构引用 任何开发或部署 AI 系统的组织(自愿采用,但美国联邦机构越来越期待其实施)。 与风险相称的人工监督,并对监督控制措施进行文档化记录。

共同点在于:如果你的智能体做出或影响了对人们产生实质影响的决定(信贷、就业、医疗、安全),你需要在模型的建议与行动的执行之间设置一个可审查的门控环节。

下面是使用 @openrouter/agent 满足这些要求的 5 种模式,基于 HITL 工具 cookbook(其中介绍了 SDK 的具体机制)构建。这里我们介绍的是在其之上叠加的合规模式。

注意: 本文提供的是工程实践模式,并非法律建议。请咨询法律顾问,以确定哪些法规适用于您的具体用例和司法辖区。

把这份内容交给你的智能体

想让你的编程智能体来实现这些?复制下面的提示词:

I need to add regulatory-compliant human-in-the-loop controls to my AI agent using the OpenRouter Agent SDK.

Inspect my codebase to identify which tools and actions are high-risk (financial, PII, legal, or safety-critical), then infer the appropriate risk tiers and implement a compliance layer using the Agent SDK HITL tools.

The compliance layer should:

1. Mark high-risk tools with requireApproval or onToolCalled gates based on my risk classification.
2. Log every oversight event (tool invocation, human decision, timestamp, reviewer ID) to my audit backend.
3. Add timeout-based escalation: if no human responds within the deadline, escalate to a supervisor or reject the action.
4. Stamp each human decision with reviewer identity and timestamp via onResponseReceived.
5. Persist conversation state with a StateAccessor backed by my chosen storage so audit records survive restarts.

Consult these pages for current SDK shapes and patterns:
- HITL tools reference: https://openrouter.ai/docs/sdks/typescript/call-model/tools#human-in-the-loop-hitl-tools
- Tool Approval & State: https://openrouter.ai/docs/sdks/typescript/call-model/approval-and-state
- callModel API reference: https://openrouter.ai/docs/sdks/typescript/call-model/api-reference

Do not hard-code secrets. Use environment variables for API keys and database credentials.

1. 按风险等级为工具分类

法规要求对具有 重大影响 的操作进行人工审查。首先将你的工具划分为不同等级:

等级 示例操作 管控方式
高风险 金融交易、PII(个人身份信息)处理、访问权限决策、医疗建议 带强制暂停的 HITL(人工介入)工具(return null
中风险 批量邮件、内容审核、数据导出 带条件谓词的 requireApproval
低风险 搜索、只读查询、格式化 无需审核关卡
import { OpenRouter, tool } from '@openrouter/agent';
import { z } from 'zod';

// High-risk: always pauses for human review
const processCreditDecision = tool({
  name: 'process_credit_decision',
  description: 'Issue or deny a credit application',
  inputSchema: z.object({
    applicationId: z.string(),
    recommendedAction: z.enum(['approve', 'deny', 'refer']),
    riskScore: z.number(),
    applicantName: z.string(),
  }),
  outputSchema: z.object({
    decision: z.enum(['approved', 'denied', 'referred']),
    reviewerId: z.string(),
    reviewedAt: z.number(),
    justification: z.string(),
  }),
  onToolCalled: async () => {
    // Always escalate to human. No auto-resolve path for high-risk.
    return null;
  },
});

对于中等风险的工具,使用基于上下文进行把关的条件谓词:

const sendBulkEmail = tool({
  name: 'send_bulk_email',
  description: 'Send email to a recipient list',
  inputSchema: z.object({
    recipients: z.array(z.string().email()),
    subject: z.string(),
    body: z.string(),
  }),
  outputSchema: z.object({ sent: z.boolean(), count: z.number() }),
  requireApproval: (params) => {
    // Gate kicks in above 50 recipients
    return params.recipients.length > 50;
  },
  execute: async (params) => {
    await sendEmails(params);
    return { sent: true, count: params.recipients.length };
  },
});

2. 为每个监督事件添加审计日志

法规要求你证明人工监督确实发生了。这意味着要记录谁审查了什么、何时审查、以及做出了什么决定。将此逻辑接入 onResponseReceived

import { tool } from '@openrouter/agent';
import { z } from 'zod';

const auditSchema = z.object({
  decision: z.enum(['approved', 'denied', 'referred']),
  reviewerId: z.string(),
  justification: z.string(),
});

const processCreditDecision = tool({
  name: 'process_credit_decision',
  description: 'Issue or deny a credit application',
  inputSchema: z.object({
    applicationId: z.string(),
    recommendedAction: z.enum(['approve', 'deny', 'refer']),
    riskScore: z.number(),
    applicantName: z.string(),
  }),
  outputSchema: z.object({
    decision: z.enum(['approved', 'denied', 'referred']),
    reviewerId: z.string(),
    reviewedAt: z.number(),
    justification: z.string(),
  }),
  onToolCalled: async (input) => {
    // Log the escalation event itself
    await writeAuditLog({
      event: 'escalated_to_human',
      toolName: 'process_credit_decision',
      input,
      timestamp: Date.now(),
    });
    return null;
  },
  onResponseReceived: async (raw) => {
    const parsed = auditSchema.parse(raw);
    const reviewedAt = Date.now();

    // Write the immutable audit record
    await writeAuditLog({
      event: 'human_decision_recorded',
      toolName: 'process_credit_decision',
      reviewerId: parsed.reviewerId,
      decision: parsed.decision,
      justification: parsed.justification,
      reviewedAt,
    });

    return { ...parsed, reviewedAt };
  },
});

writeAuditLog 函数应写入只追加(append-only)存储。一个最小化的接口:

interface AuditEntry {
  event: string;
  toolName: string;
  timestamp?: number;
  reviewerId?: string;
  decision?: string;
  justification?: string;
  input?: unknown;
  reviewedAt?: number;
  escalatedTo?: string;
}

async function writeAuditLog(entry: AuditEntry): Promise<void> {
  // Write to your audit backend: Postgres, S3, Datadog, Splunk, etc.
  // The record must be append-only and tamper-evident for compliance.
  await db.insertInto('audit_log').values({
    ...entry,
    timestamp: entry.timestamp ?? Date.now(),
    id: crypto.randomUUID(),
  }).execute();
}

EU AI Act 第 12 条(记录保存)要求高风险系统在其运行生命周期内保留日志。将审计日志存储在持久化的只追加存储中,并根据你的法规要求配置相应的保留策略。

3. 实现基于超时的升级机制

一个无人响应的人工审核关卡比没有关卡更糟糕。法规期望系统能够处理审查者无响应的情况。实现一个超时机制,默认情况下要么上报给主管,要么直接拒绝该操作。

这个模式运行在 callModel 循环之外,位于任何轮询过期待审核事项的服务中:

interface PendingReview {
  conversationId: string;
  callId: string;
  toolName: string;
  createdAt: number;
  assignedTo: string;
}

const REVIEW_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes

async function escalateStaleReviews(
  pendingReviews: PendingReview[],
): Promise<void> {
  const now = Date.now();

  for (const review of pendingReviews) {
    const elapsed = now - review.createdAt;
    if (elapsed < REVIEW_TIMEOUT_MS) continue;

    await writeAuditLog({
      event: 'review_timeout_escalated',
      toolName: review.toolName,
      reviewerId: review.assignedTo,
      timestamp: now,
    });

    // Option A: Escalate to supervisor
    await assignToSupervisor(review);

    // Option B: Default-deny and resume the agent with a rejection
    // await resumeWithDenial(review);
  }
}

选择哪个方案取决于你的风险偏好。对于需要符合欧盟 AI 法案的高风险系统,默认拒绝(方案 B)更安全:没有明确的人工批准,操作永远不会执行。对于延迟会带来运营成本的较低风险系统,升级给主管(方案 A)既能保持监督链,又能让流程继续推进。

4. 用持久化存储支撑你的 StateAccessor

内存中的状态在进程重启后会消失。出于合规要求,你的 StateAccessor 必须使用持久化存储,以便待审查项、对话历史和审计上下文能在崩溃、部署和横向扩展中得以保留。

import type { ConversationState, StateAccessor, Tool } from '@openrouter/agent';

function createDurableStateAccessor<TTools extends readonly Tool[]>(
  conversationId: string,
): StateAccessor<TTools> {
  return {
    load: async () => {
      const row = await db
        .selectFrom('conversation_state')
        .where('id', '=', conversationId)
        .selectAll()
        .executeTakeFirst();

      if (!row) return null;
      return JSON.parse(row.state) as ConversationState<TTools>;
    },
    save: async (state) => {
      await db
        .insertInto('conversation_state')
        .values({
          id: conversationId,
          state: JSON.stringify(state),
          updated_at: new Date(),
        })
        .onConflict((oc) =>
          oc.column('id').doUpdateSet({
            state: JSON.stringify(state),
            updated_at: new Date(),
          }),
        )
        .execute();
    },
  };
}

每当状态转换为 'awaiting_hitl''awaiting_approval' 时,待审查项都会被持久化。你的升级服务(第 3 步)会查询这张表来找出过期的审查。

5. 将所有部分串联起来

完整流程如下:分类、把关、记录、超时、恢复。这里假设使用第 1-2 步中的 processCreditDecisionsendBulkEmail、第 2 步的 writeAuditLog,以及第 4 步的 createDurableStateAccessor

import { OpenRouter } from '@openrouter/agent';

// processCreditDecision, sendBulkEmail defined in steps 1-2
// createDurableStateAccessor defined in step 4

const openrouter = new OpenRouter({
  apiKey: process.env.OPENROUTER_API_KEY,
});

const tools = [processCreditDecision, sendBulkEmail] as const;
const conversationId = `conv-${crypto.randomUUID()}`;
const state = createDurableStateAccessor<typeof tools>(conversationId);

// Initial request
const result = openrouter.callModel({
  model: 'openai/gpt-4o',
  input: 'Review application APP-2024-001 and issue a credit decision',
  tools,
  state,
});

// Wait for the call to complete (or pause for human review)
const snapshot = await result.getState();

if (snapshot?.status === 'awaiting_hitl' || snapshot?.status === 'awaiting_approval') {
  const pending = snapshot.pendingToolCalls ?? [];

  // Surface to your review UI, queue, or notification system.
  // 'awaiting_hitl' fires for onToolCalled tools (processCreditDecision).
  // 'awaiting_approval' fires for requireApproval tools (sendBulkEmail).
  // Both resume via function_call_output here; see approval-and-state docs
  // for the approveToolCalls/rejectToolCalls alternative for requireApproval tools.
  for (const call of pending) {
    await createPendingReview({
      conversationId,
      callId: call.id,
      toolName: call.name,
      createdAt: Date.now(),
      assignedTo: getReviewerForTool(call.name),
      arguments: call.arguments,
    });
  }
}

当审核者响应时(通过你的管理后台、Slack 操作、队列消费者等):

// Retrieve the pending call from your review queue (by conversationId, callId, etc.)
const pendingCall = await getPendingReview(conversationId);

// Human supplies their decision
const humanDecision = {
  decision: 'approved' as const,
  reviewerId: 'reviewer-jane-smith',
  justification: 'Risk score within policy limits, verified income docs',
};

const resumed = openrouter.callModel({
  model: 'openai/gpt-4o',
  input: [
    {
      type: 'function_call_output',
      callId: pendingCall.callId,
      output: JSON.stringify(humanDecision),
    },
  ],
  tools,
  state,
});

const text = await resumed.getText();

onResponseReceived 钩子被触发,盖印审计记录,模型接收到经过验证的决策。

今天就开始构建

欧盟 AI 法案的高风险义务将于 2026 年 8 月生效。科罗拉多州的 ADMT 法 于 2027 年 1 月 1 日生效。NIST AI RMF 是自愿性的,但越来越多地被美国联邦机构引用为基线要求。只需一套实现(风险分类、审计日志、超时升级、持久化状态)即可同时满足这三个框架。

Agent SDK 负责处理暂停执行、跨重启持久化状态、按照 schema 校验人类响应,以及干净地恢复运行。你的工作是把它接入你的审查工作流和审计存储。

关于相关治理控制(预算上限、数据保留策略、模型限制),请参见 Guardrails

完整的 SDK 参考和可运行的示例:HITL 工具文档

常见问题

欧盟 AI 法案第 14 条有什么要求?

第 14 条要求高风险 AI 系统必须包含人类监督措施。人类必须能够理解系统的能力、监控其运行、解读其输出,并能够干预或否决决策。审计日志保留要求则属于第 12 条(记录保存)和第 9 条(风险管理)。

欧盟 AI 法案何时生效?

《人工智能法案》于 2024 年 8 月生效,但高风险义务(包括第 14 条的人工监督)自 2026 年 8 月起适用。这是被归类为高风险的系统必须证明其具备合规监督控制的最后期限。

科罗拉多州的 ADMT 法何时生效?

科罗拉多州的《自动化决策技术》法(SB26-189)一般于 2027 年 1 月 1 日生效,并适用于在该日期或之后做出的重大决策。科罗拉多州总检察长的规则制定页面持续跟踪实施细节。

科罗拉多州的 ADMT 法是否适用于科罗拉多州以外的公司?

适用。该法适用于任何“在科罗拉多州开展业务”的开发者或部署者,而不仅仅是在该州设立总部的公司。如果你部署的 ADMT 对有关科罗拉多州居民的重大决策(就业、金融、住房、保险、医疗、教育、基本政府服务)产生实质性影响,你很可能受该法约束。这与《科罗拉多州隐私法》的管辖模式相同,后者涵盖在科罗拉多州开展业务或以商业产品或服务面向科罗拉多州居民的实体。执法通过《科罗拉多州消费者保护法》进行(违法行为被视为欺骗性商业行为)。

什么是 AI 智能体的人机协同(HITL,human-in-the-loop)?

HITL(人在回路)是指在 AI 智能体执行其提议的操作之前,由人工进行审核并批准(或拒绝)。在 Agent SDK 中,这是通过 onToolCalled(暂停执行并等待人工输入)和 requireApproval(根据参数有条件地把关工具执行)来实现的。

来源:OpenRouter:Announcements(RSS)· openrouter.ai