Guide

Aggiungere un gate di approvazione umana

Instrada un'azione di agente ad alto rischio attraverso KLA per la valutazione della policy, la firma umana e l'esecuzione gestita dal server.

5 min di lettura1195 parole

Alcune azioni di un agente richiedono la firma di una persona responsabile: eliminare un account, elaborare un pagamento o rilasciare un documento. Questa guida invia una di queste azioni attraverso l'SDK di KLA Control Plane. KLA valuta la Decision Request, instrada l'Escalation richiesta al Decision Desk, esegue tramite il connettore registrato dopo l'autorizzazione e restituisce il risultato registrato.

Come funziona un gate

executeAction in Node.js e execute_action in Python inviano una Decision Request che contiene l'azione e il suo contesto. KLA Policy Engine la risolve in allow, warn, require_approval o block. Un risultato require_approval apre una Escalation, un'unità di lavoro sospesa in attesa di una decisione umana. Il Decision Desk la instrada a un revisore autorizzato. L'SDK mantiene una sola identità di proposal durante polling e ripresa. KLA esegue una sola volta l'azione approvata tramite il connettore registrato e restituisce execution.result.

sequenceDiagram
  participant App as Il tuo agente
  participant KLA as Checkpoint KLA
  participant Desk as Decision Desk
  App->>KLA: executeAction("process_payment", context)
  KLA->>KLA: Valuta la Decision Request
  Note over KLA: esito = require_approval
  KLA->>Desk: Apre l'Escalation
  Desk-->>KLA: Il revisore approva o nega
  KLA->>KLA: Esegue una volta il connettore registrato
  KLA-->>App: execution.result o diniego tipizzato

Aggiungere il checkpoint

Qui sotto, un'azione process_payment ad alto rischio usa kla-governance per Python e @kla-digital/governance per Node.js. L'SDK effettua polling finché Decision Desk non risolve l'Escalation. L'approvazione associa conto, importo, Release dell'agente, mandato, strumento, operazione e destinazione a una sola proposal.

ℹ️ Note

I pacchetti di governance sono release candidate. I comandi di installazione saranno disponibili dopo la pubblicazione su npm e PyPI dei pacchetti 0.1.0 revisionati.

Python

from kla_governance import ActionRequest, AgentIdentity, DecisionDenied, KLAClient

client = KLAClient(
    base_url="https://api.kla.digital",
    credential=get_access_token,
    agent=AgentIdentity(agent_id="agt_9f81a7", release_version="1.4.2"),
    mandate_id="mnd_payments",
)

def process_payment(account_id: str, amount: float):
    try:
        return client.execute_action(
            ActionRequest(
                tool="payments",
                operation="charge",
                destination="gateway:acct_main",
                parameters={"account_id": account_id, "amount": amount},
            ),
            proposal_id=stable_id_for(account_id, amount),
        )
    except DecisionDenied as denial:
        raise PaymentNotAuthorized(
            f"Payment not authorized: {denial.reason_codes} ({denial.remediation})"
        )

TypeScript

import { KLAClient, DecisionDenied } from '@kla-digital/governance';

const client = new KLAClient({
  baseUrl: 'https://api.kla.digital',
  credential: () => getAccessToken(),
  agent: { agentId: 'agt_9f81a7', releaseVersion: '1.4.2' },
  mandateId: 'mnd_payments',
});

async function processPayment(accountId: string, amount: number) {
  try {
    return await client.executeAction(
      {
        tool: 'payments',
        operation: 'charge',
        destination: 'gateway:acct_main',
        parameters: { accountId, amount },
      },
      { proposalId: stableIdFor(accountId, amount) }
    );
  } catch (error) {
    if (error instanceof DecisionDenied) {
      throw new PaymentNotAuthorizedError(
        `Payment not authorized: ${error.reasonCodes} (${error.remediation})`
      );
    }
    throw error;
  }
}

Configura il client all'avvio con l'URL di base del control plane, un access token client credentials, l'id dell'agente registrato, la sua versione di Release fissata e l'id di un mandato attivo. Registra strumento e connettore nel Tool Catalog. Il mandato deve coprire strumento, operazione e destinazione. L'identità del tenant proviene dal token verificato. L'SDK invia Authorization: Bearer <token> con ogni richiesta di azione.

Usa resolve_binding() in Python o resolveBinding() in Node.js come controllo di avvio in sola lettura. Conferma la Release approvata corrente e la revisione del mandato attiva, inclusa la finestra di validità e le azioni consentite, prima che il worker accetti attività governate.

Comporre la governance con OpenTelemetry

Usa entrambi gli SDK in un agente strumentato. Hanno responsabilità distinte:

Pacchetto Responsabilità
@kla-digital/governance o kla-governance Invia la Decision Request, attende policy e revisione umana e restituisce il risultato di esecuzione registrato dal server. Questa chiamata è il punto di controllo dell'azione.
@kla-digital/otel-node o kla-otel-python Registra l'attività circostante di modello, framework e applicazione come span OpenTelemetry per Lineage Explorer.

Inizializza l'SDK OpenTelemetry all'avvio dell'applicazione, quindi chiama l'SDK di governance a ogni confine di azione rilevante. Trasmetti identificatori di trace e span OpenTelemetry attivi tramite l'opzione trace della chiamata di governance quando sono disponibili. Questo correla Decision Request ed esecuzione server al Lineage Record circostante. Una chiamata di governance risolta autorizza l'esecuzione del connettore registrato. L'esportazione degli span registra l'attività e non produce effetti di autorizzazione.

Per Node.js:

npm install @kla-digital/governance @kla-digital/otel-node @opentelemetry/api
import '@kla-digital/otel-node';
import { trace } from '@opentelemetry/api';

const activeSpan = trace.getActiveSpan()?.spanContext();
const result = await client.executeAction(action, {
  proposalId,
  trace: activeSpan
    ? { traceId: activeSpan.traceId, spanId: activeSpan.spanId }
    : undefined,
});

Per Python:

pip install kla-governance kla-otel-python
from opentelemetry import trace

span_context = trace.get_current_span().get_span_context()
correlation = None
if span_context.is_valid:
    correlation = {
        "trace_id": format(span_context.trace_id, "032x"),
        "span_id": format(span_context.span_id, "016x"),
    }

result = client.execute_action(
    action,
    proposal_id=proposal_id,
    trace=correlation,
)

Consulta la guida all'SDK OpenTelemetry per Node.js o la guida all'SDK OpenTelemetry per Python per la strumentazione del framework e la configurazione del collector.

Gestire un diniego in modo corretto

Un revisore può negare l'Escalation oppure la policy può restituire un block rigido. Entrambi emergono dall'helper di esecuzione come DecisionDenied con la decisione risolta associata. L'esito viene registrato. Tratta l'eccezione come un ramo previsto:

  • Leggi i reason code. Ogni decisione diversa da allow contiene reason_codes leggibili dalla macchina, ad esempio PAYMENT_OVER_THRESHOLD, e remediation leggibile da una persona. Ramifica sui codici; non analizzare la prosa.
  • Mostra il diniego. Restituisci un messaggio chiaro all'utente chiamante o all'agente a monte (“Il pagamento richiede l'approvazione del responsabile ed è stato rifiutato”). Il diniego è già registrato come Lineage Record, quindi non è necessario registrarlo separatamente per l'audit.
  • Non riprovare alla cieca. Un'azione negata non deve rientrare automaticamente nello stesso checkpoint. Passa a un percorso umano nel tuo prodotto.
⚠️ Warning

Un'azione require_approval può attendere per tutto il tempo necessario al revisore. Eseguila in un worker o in un'attività in background. Passa timeout (timeoutMs in Node.js) per limitare l'attesa. ApprovalTimeout significa che la Decision Request resta in attesa. Chiama di nuovo l'helper di esecuzione con lo stesso id di proposal per proseguire. L'annullamento dell'attività locale lascia aperta la proposal sul server. Usa cancel_action (cancelAction) per chiudere una proposal ricevuta o in attesa di approvazione.

💡 Tip

Passa un proposal_id stabile, qui derivato da conto e importo. KLA associa l'approvazione e la voce del ledger di esecuzione a quella proposal. Un nuovo tentativo dopo la firma riproduce il risultato registrato e conserva una sola invocazione del connettore.

Se la sigillatura delle evidenze resta incompleta dopo l'esecuzione del connettore, l'helper di esecuzione solleva ExecutionEvidencePending e trattiene ogni risultato associato a quello stato. L'errore conserva i riferimenti a decisione e ricevuta della proposal per la riconciliazione. Conserva quell'identità di proposal; una nuova identità rappresenta una nuova azione logica.

Entrambi gli SDK convalidano l'intera risposta di ingresso prima di rilasciare una decisione o un risultato. Versione dello schema, identità di proposal e azione, stati del ciclo di vita, hash del risultato e riferimenti alla ricevuta devono essere coerenti. Una risposta malformata solleva KLATransportError con response_schema_invalid.

Prima della pubblicazione

Scrivi la policy di gating in Policy Builder ed esegui una Simulation: riproduci Decision Request rappresentative sulla bozza e conferma che un pagamento di valore elevato si risolva in require_approval e uno di valore basso in allow. Dopo la convalida, la policy viene compilata in un policy pack firmato e pubblicata. Da quel momento ogni chiamata con gate produce una traccia difendibile: richiesta, esito, verdetto del revisore e azione risultante, tutti acquisiti come Lineage Record esportabile in seguito come Sealed Evidence Bundle.

Aggiungere un gate di approvazione umana | Developer Docs | KLA Control Plane