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.
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 tipizzatoAggiungere 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.
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
allowcontienereason_codesleggibili dalla macchina, ad esempioPAYMENT_OVER_THRESHOLD, eremediationleggibile 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.
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.
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.
