惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Securelist
C
CERT Recently Published Vulnerability Notes
Forbes - Security
Forbes - Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
L
LINUX DO - 最新话题
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
The Last Watchdog
The Last Watchdog
S
Schneier on Security
T
Troy Hunt's Blog
N
News | PayPal Newsroom
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Schneier on Security
Schneier on Security
P
Privacy & Cybersecurity Law Blog
T
Tor Project blog
T
Threatpost
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
A
Arctic Wolf
S
Secure Thoughts
P
Proofpoint News Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Security Latest
Security Latest
Scott Helme
Scott Helme
Security Archives - TechRepublic
Security Archives - TechRepublic
Latest news
Latest news
PCI Perspectives
PCI Perspectives
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
L
LINUX DO - 热门话题
P
Palo Alto Networks Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V2EX - 技术
V2EX - 技术
Google DeepMind News
Google DeepMind News
Project Zero
Project Zero
V
Vulnerabilities – Threatpost
T
Threat Research - Cisco Blogs
Webroot Blog
Webroot Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
大猫的无限游戏
大猫的无限游戏
T
Tenable Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
H
Hacker News: Front Page
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog

OpenRouter Blog

Choosing the Optimal Image Input Detail Level in LLMs — OpenRouter Blog DeepSeek V4 Is Earning Agentic Token Share — OpenRouter Blog The Open Weight Models that Matter: June 2026 — OpenRouter Blog The OpenRouter MCP Server — OpenRouter Blog Introducing the Unified Image API — OpenRouter Blog The AI Governance Checklist That Maps to Your Stack — OpenRouter Blog Enforce AI Data Residency at the Routing Layer — OpenRouter Blog OpenRouter vs Portkey: Routing Network vs Control Plane — OpenRouter Blog OpenRouter vs LiteLLM: Managed vs Self-Hosted Gateway — OpenRouter Blog Connect OpenClaw to OpenRouter: One Key, Failover, Free Models — OpenRouter Blog Connect SillyTavern to OpenRouter: Setup, Models, Fixes — OpenRouter Blog A Robot is Sprinting Towards You: Do You Want it Running on Claude or Grok? Kilo Code + OpenRouter: Setup, Routing, and Free Models — OpenRouter Blog Codex CLI with OpenRouter: config.toml Setup and Models — OpenRouter Blog Claude Code with OpenRouter: Setup, Models, and Costs — OpenRouter Blog How to Use OpenRouter With Any Coding Agent or AI Tool — OpenRouter Blog Subagent: Let Your Model Delegate the Busywork — OpenRouter Blog Free LLM API in 2026: 13 Options Ranked and Compared — OpenRouter Blog How to Enforce Agentic AI Governance at the API Layer — OpenRouter Blog Keep Your Agent Running When Models Disappear — OpenRouter Blog Hermes Agent + OpenRouter: Setup, Model Choice & Routing Config — OpenRouter Blog Lowest-Cost LLM Inference: The Complete OpenRouter Guide — OpenRouter Blog How OpenRouter Model Routing Works: Providers, Fallbacks & Auto Router — OpenRouter Blog OpenRouter Failover: Provider Failover vs Model Fallbacks Explained — OpenRouter Blog Surpassing Frontier Performance with Fusion — OpenRouter Blog Dinner is Served — OpenRouter Blog LLM Gateway: What It Is and How to Choose One — OpenRouter Blog Advisor: Give Any Model a Lifeline to a Smarter One — OpenRouter Blog Gemini 2.5 Flash API - Pricing, Quickstart & Provider Comparison — OpenRouter Blog May Release Spotlight — OpenRouter Blog Guardrails: Protect your Agents, Data, and Costs — OpenRouter Blog OpenRouter Raises $113M Series B — OpenRouter Blog Human-in-the-Loop Tools for the Agent SDK — OpenRouter Blog Consistent Web Search and Fetch Across Every Model — OpenRouter Blog GPT-5.5 Price Increase: What It Actually Costs — OpenRouter Blog New Audio APIs for Speech and Transcription — OpenRouter Blog Response Caching: Zero Cost for Identical Requests — OpenRouter Blog April Release Spotlight — OpenRouter Blog Create OpenRouter Accounts via CLI with Stripe Projects — OpenRouter Blog Opus 4.7 Agent SDK: Building Multi-turn Agent Workflows on OpenRouter — OpenRouter Blog Build Your Own Harness with the Agent SDK — OpenRouter Blog Introducing Workspaces — OpenRouter Blog Announcing Video Generation — OpenRouter Blog Auto Exacto: Adaptive Quality Routing, On by Default — OpenRouter Blog February Release Spotlight — OpenRouter Blog OpenRouter Outages on February 17 and 19, 2026 — OpenRouter Blog January Release Spotlight — OpenRouter Blog Distillable Models and Synthetic Data Pipelines with NeMo Data Designer — OpenRouter Blog December Release Spotlight — OpenRouter Blog Response Healing: Reduce JSON Defects by 80%+ — OpenRouter Blog The 2025 State of AI Report — OpenRouter Blog Is Implicit Caching Prompt Retention? — OpenRouter Blog Provider Variance: Introducing Exacto — OpenRouter Blog 1 million free BYOK requests per month — OpenRouter Blog The First-Ever Image Model Is Up on OpenRouter — OpenRouter Blog GPT-5 is now live — OpenRouter Blog Audio Inputs and PDF URLs for Apps — OpenRouter Blog Presets: How To Seamlessly Transfer Model Configurations Across Apps — OpenRouter Blog New Privacy-Focused Provider Drop: Venice — OpenRouter Blog Use OpenRouter Models in Cursor: Try it with Moonshot AI Updates to Our Free Tier: Sustaining Accessible AI for Everyone — OpenRouter Blog New Stealth Model: "Cypher Alpha" — OpenRouter Blog Introducing Presets: Manage LLM Configs from Your Dashboard! — OpenRouter Blog Dev & BYOK Updates: Uptime API + Smarter Key Management — OpenRouter Blog Simplifying Our Platform Fee — OpenRouter Blog GIF Prompts, Omni Search, Tool Caching, and BYOK Flags — OpenRouter Blog New Features: Reasoning Streams, Crypto Invoices, End-User IDs & More — OpenRouter Blog Passkeys, DevEx Upgrades, and a New Guide for TypeScript Agents — OpenRouter Blog New Provider Drop: Cerebras Is Here — OpenRouter Blog Better Insights, Faster Metrics, and New Developer Power Tools — OpenRouter Blog Privacy Clarity, New Providers, OAuth Upgrade, and Gemini Gets Parallel Tools — OpenRouter Blog Universal PDF Support — OpenRouter Blog Smarter Charts, Inline SVGs, and Live Usage Accounting — OpenRouter Blog Quasar Alpha and Optimus Alpha Reveal — OpenRouter Blog "Stealth" model: Optimus Alpha — OpenRouter Blog “Stealth” model: Quasar Alpha — OpenRouter Blog Never Pay for Empty AI Responses Again — OpenRouter Blog Deep Research & Many New Models — OpenRouter Blog Introducing Nitro and Floor Price Shortcuts — OpenRouter Blog Introducing Cloudflare as a new provider — OpenRouter Blog Reasoning Tokens for Thinking Models — OpenRouter Blog Introducing Web Search via the API — OpenRouter Blog Standardized finish reasons — OpenRouter Blog Happy New Year! Introducing a new Auto Router — OpenRouter Blog Holiday launches: Web Search & Price Cuts — OpenRouter Blog Bring Your Own API Keys — OpenRouter Blog Crypto Payments API — OpenRouter Blog Structured Outputs & Free Gemini Flash 2.0 — OpenRouter Blog Price Drops and Llama 3.3 70b — OpenRouter Blog Author Pages & Amazon Nova — OpenRouter Blog
EU AI Act & Colorado ADMT Compliance: Human Oversight for AI Agents — OpenRouter Blog
Kenny Rogers · 2026-06-08 · via OpenRouter Blog

AI agents aren’t just answering questions anymore. They’re approving loan applications, triaging patient intake forms, running payroll calculations, deciding who gets flagged for fraud review. When one of those calls goes wrong, the liability sits with the deployer.

Regulators caught up. The first hard deadline lands in August 2026, and if you’re building agents that touch financial services, healthcare, hiring, or any domain where a wrong output has real consequences for a real person, the compliance clock is already running.

Three regulations converge on the same obligation: a human must be able to oversee, intervene in, and override AI-driven decisions that affect people. The Agent SDK has the primitives to wire these controls into your agent today.

RegulationEffectiveWho it applies toCore requirement
EU AI Act, Article 14Aug 2026 (high-risk obligations)Any provider or deployer of high-risk AI systems serving EU residents, regardless of where the company is based.Human oversight with ability to intervene and override. Audit trail of oversight actions.
Colorado ADMT Law (SB26-189)Jan 2027Any developer or deployer doing business in Colorado, including companies outside Colorado that make consequential decisions about Colorado residents.Covered developers/deployers must provide documentation, disclosures, consumer rights processes, and meaningful human review/reconsideration where covered ADMT materially influences consequential decisions.
NIST AI RMF (GOVERN 1)Voluntary, referenced by US regulatorsAny organization developing or deploying AI systems (voluntary, but increasingly expected by US federal agencies).Human oversight proportional to risk. Documentation of oversight controls.

The common thread: if your agent makes or influences decisions that materially affect people (credit, employment, healthcare, safety), you need a reviewable gate between the model’s recommendation and the action’s execution.

Below are 5 patterns that satisfy those requirements using @openrouter/agent, building on the HITL tools cookbook (which covers the SDK mechanics). Here we cover the compliance patterns you bolt on top.

Note: This post provides engineering patterns, not legal advice. Consult legal counsel to determine which regulations apply to your specific use case and jurisdiction.

Give this to your agent

Want your coding agent to implement this? Copy the prompt below:

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.

Regulations require human review on actions that are consequential. Start by splitting your tools into tiers:

TierExample actionsControl
High-riskFinancial transactions, PII processing, access decisions, medical recommendationsHITL tool with mandatory pause (return null)
Medium-riskBulk emails, content moderation, data exportsrequireApproval with conditional predicate
Low-riskSearch, read-only queries, formattingNo gate needed
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;
  },
});

For medium-risk tools, use a conditional predicate that gates on context:

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. Add audit logging to every oversight event

Regulations require you to prove that human oversight happened. That means logging who reviewed what, when, and what they decided. Wire this into 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 };
  },
});

The writeAuditLog function should write to append-only storage. A minimal interface:

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 Article 12 (Record-Keeping) requires that high-risk systems maintain logs for their operational lifetime. Store audit logs in durable, append-only storage with retention policies that match your regulatory requirements.

3. Implement timeout-based escalation

A human review gate that nobody responds to is worse than no gate at all. Regulations expect the system to handle unresponsive reviewers. Implement a timeout that either escalates to a supervisor or rejects the action by default.

This pattern runs outside the callModel loop, in whatever service polls for stale pending reviews:

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);
  }
}

Which option to pick depends on your risk appetite. For EU AI Act compliance with high-risk systems, default-deny (Option B) is safer: the action never executes without explicit human approval. For lower-risk systems where delays have operational cost, escalation to a supervisor (Option A) keeps things moving while preserving the oversight chain.

4. Back your StateAccessor with durable storage

In-memory state disappears on process restart. For compliance, your StateAccessor must use durable storage so that pending reviews, conversation history, and audit context survive crashes, deploys, and horizontal scaling.

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();
    },
  };
}

Every time state transitions to 'awaiting_hitl' or 'awaiting_approval', the pending review is persisted. Your escalation service (step 3) queries this table to find stale reviews.

5. Wire it all together

Here’s the complete flow: classify, gate, log, timeout, resume. This assumes processCreditDecision and sendBulkEmail from steps 1-2, writeAuditLog from step 2, and createDurableStateAccessor from step 4.

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,
    });
  }
}

When the reviewer responds (through your admin UI, Slack action, queue consumer, etc.):

// 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();

The onResponseReceived hook fires, stamps the audit record, and the model receives the validated decision.

Start building today

EU AI Act high-risk obligations land August 2026. Colorado’s ADMT law takes effect January 1, 2027. NIST AI RMF is voluntary but increasingly referenced by US federal agencies as the baseline expectation. One implementation (risk classification, audit logging, timeout escalation, durable state) satisfies all three frameworks.

The Agent SDK handles pausing execution, persisting state across restarts, validating human responses against schemas, and resuming cleanly. Your job is to wire it into your review workflows and audit storage.

For related governance controls (budget caps, data retention policies, model restrictions), see Guardrails.

Full SDK reference and working examples: HITL tools documentation.

FAQ

What does EU AI Act Article 14 require?

Article 14 mandates that high-risk AI systems include human oversight measures. Humans must be able to understand the system’s capabilities, monitor its operation, interpret outputs, and intervene or override decisions. Audit log retention requirements fall under Article 12 (Record-Keeping) and Article 9 (Risk Management).

When does the EU AI Act take effect?

The AI Act entered into force August 2024, but the high-risk obligations (including Article 14 human oversight) apply starting August 2026. That’s the deadline for systems classified as high-risk to demonstrate compliant oversight controls.

When does Colorado’s ADMT law take effect?

Colorado’s Automated Decision-Making Technology law (SB26-189) generally takes effect January 1, 2027 and applies to consequential decisions made on or after that date. The Colorado AG’s rulemaking page tracks implementation details.

Does Colorado’s ADMT law apply to companies outside Colorado?

Yes. The law applies to any developer or deployer “doing business in” Colorado, not just companies headquartered there. If you deploy ADMT that materially influences consequential decisions (employment, finance, housing, insurance, healthcare, education, essential government services) about Colorado residents, you’re likely subject to the law. This follows the same jurisdictional pattern as the Colorado Privacy Act, which covers entities that conduct business in Colorado or target Colorado residents with commercial products or services. Enforcement runs through the Colorado Consumer Protection Act (violations are treated as deceptive trade practices).

What is human-in-the-loop (HITL) for AI agents?

HITL means a human reviews and approves (or rejects) an AI agent’s proposed action before it executes. In the Agent SDK, this is implemented through onToolCalled (which pauses execution and waits for human input) and requireApproval (which conditionally gates tool execution based on parameters).