Guides

Einen bestehenden Agent mit einer Richtlinie steuern

Simulieren, prüfen, veröffentlichen und binden Sie eine fail-closed Zahlungsrichtlinie an einen Agent, der bereits in der KLA Control Plane existiert.

11 Min. Lesezeit2440 Wörter

Diese Anleitung fügt einem Agent, der bereits in der KLA Control Plane existiert, eine geprüfte Richtlinie hinzu. Die Richtlinie erlaubt payments.create-Aufrufe bis 10.000 EUR, leitet höhere Zahlungen an den Decision Desk weiter und blockiert jede Zahlungsanfrage, die keiner der beiden Regeln entspricht. Die veröffentlichte Version gilt nur für diesen einen Agent, sodass andere Produktions-Agents des Tenants unberührt bleiben.

Ein auf einen Agent eingegrenzter Entwurf kann erst zur Prüfung eingereicht werden, wenn der Agent eine gesteuerte Umgebung trägt, und ein Agent erhält eine gesteuerte Umgebung nur durch eine bereitgestellte Richtlinienbindung. Die Abfolge umfasst daher zwei Richtlinienversionen: Version 1.0.0 wird geprüft und gebunden, um dem Agent seine Umgebung zu geben, und wird nie veröffentlicht; Version 1.1.0 nennt den Agent in ihrem Geltungsbereich, wird veröffentlicht und als durchgesetzte Richtlinie gebunden.

Jeder Befehl ist zum Kopieren bereit. Die Befehle legen Datensätze im gewählten Tenant an. Verwenden Sie daher einen Tenant, den Sie kontrollieren.

Bevor Sie beginnen

Sie benötigen:

  • die aus dem Repository gebaute kla-CLI, wie in der Installationsanleitung beschrieben;
  • jq;
  • einen bestehenden Agent, dessen Zahlungswerkzeug payments.create heißt und einen numerischen amount sowie eine Zeichenkette currency erhält;
  • ein Maker-Zugriffstoken eines Mitglieds, das Richtlinien erstellen, simulieren und veröffentlichen sowie Agents konfigurieren und bereitstellen darf;
  • ein Checker-Zugriffstoken eines anderen Mitglieds mit der Rolle kla:approver, die Richtlinien prüft, Decision Requests entscheidet und Agent-Releases genehmigt.

Die CLI liest KLA_ACCESS_TOKEN. Das Maker-Token bleibt für die gesamte Anleitung exportiert. Jeder Checker-Befehl erhält das Checker-Token nur für diesen einen Befehl. Halten Sie beide Token aus Dateien und Befehlsargumenten heraus.

export KLA_API_URL='https://api.dev.kla.digital'
export KLA_TENANT_ID='<tenant external ID>'
export KLA_ACCESS_TOKEN='<maker short-lived access token>'
export KLA_CHECKER_ACCESS_TOKEN='<checker short-lived access token>'

KLA_REPO_ROOT="$(git rev-parse --show-toplevel)"
kla() { node "$KLA_REPO_ROOT/cli/dist/index.js" "$@"; }

kla auth status > maker-auth.json
KLA_ACCESS_TOKEN="$KLA_CHECKER_ACCESS_TOKEN" kla auth status > checker-auth.json
jq -e '.token.subject | type == "string"' maker-auth.json
jq -e '.token.subject | type == "string"' checker-auth.json
jq -en --slurpfile maker maker-auth.json --slurpfile checker checker-auth.json \
  '$maker[0].token.subject != $checker[0].token.subject'
jq -e '.token.roles | index("kla:approver") != null' checker-auth.json

kla api tenants getSettings | jq -e '.governance.publishApprovalMode == "two_person"'

kla auth status gibt die nicht geheimen Claims jedes Tokens aus. Die beiden Subjekte müssen sich unterscheiden: Die API lehnt eine Prüfung oder Genehmigung durch die Identität ab, die die Anfrage gestellt hat. Der Veröffentlichungsmodus des Tenants muss two_person sein; im Modus single_actor zeichnet der Veröffentlichungsschritt seine eigene Genehmigung auf, und Schritt 7 hat keinen Decision Request zu entscheiden.

Schritt 1: Den Agent identifizieren

Durchsuchen Sie die Agent Registry, kopieren Sie die UUID aus dem Ergebnis und speichern Sie den Agent-Datensatz. Der Agent darf keinen ausstehenden Entwurf haben: Eine Richtlinienbindung wird in einen bestehenden Entwurf eingemischt, und der Checker würde dann fremde Änderungen zusammen mit der Bindung genehmigen.

kla agent list --search 'payment'
export AGENT_UUID='<agent UUID>'
kla agent get "$AGENT_UUID" > agent-before.json
jq -e --arg agent "$AGENT_UUID" '.id == $agent' agent-before.json

kla agent release history "$AGENT_UUID" > agent-history-before.json
jq -e '[.versions[] | select(.is_draft == true)] | length == 0' agent-history-before.json

Existiert ein ausstehender Entwurf, steht sein manifest in dieser Historienausgabe. Lassen Sie ihn vom Checker genehmigen oder vom Maker verwerfen, bevor Sie fortfahren.

Die folgende Richtlinie nennt das Werkzeug payments.create und die Argumente amount und currency. Verwendet Ihr Agent einen anderen Werkzeug- oder Argumentnamen, ändern Sie diese Werte in der Richtlinie und in beiden Simulationseingaben.

Schritt 2: Die fail-closed Richtlinie schreiben

Speichern Sie diese Datei als policy.template.json. Version 1.0.0 gilt für die gesteuerte Umgebung production und ist die Bootstrap-Version. Schritt 6 grenzt den Geltungsbereich für Version 1.1.0 auf den Agent ein.

{
  "schemaVersion": "1.0.0",
  "policyId": "existing-agent-payment-controls",
  "workspaceId": "TENANT_EXTERNAL_ID",
  "name": "Existing agent payment controls",
  "description": "Allows EUR payments of 10,000 or less and routes larger EUR payments to review.",
  "status": "draft",
  "version": "1.0.0",
  "scope": {
    "environments": ["production"]
  },
  "defaultDecision": "block",
  "rules": [
    {
      "ruleId": "allow-managed-execution-gate",
      "name": "Allow the managed Process execution gate",
      "interceptionPoint": "input",
      "when": {
        "expression": {
          "==": [{ "var": "context.action.actionType" }, "policy_gate"]
        }
      },
      "then": {
        "decision": "allow",
        "reason": "The execution may start; each payment tool call is evaluated separately.",
        "reasonCodes": ["execution_gate_allowed"]
      },
      "execution": { "mode": "deterministic" },
      "evidence": {
        "evaluatedFields": ["context.action.actionType"],
        "artifactRefs": []
      }
    },
    {
      "ruleId": "allow-payment-up-to-10000",
      "name": "Allow positive payment up to EUR 10,000",
      "interceptionPoint": "tool_call",
      "when": {
        "expression": {
          "and": [
            { "in": [{ "var": "context.action.actionType" }, ["tool_input", "tool_call"]] },
            { "==": [{ "var": "context.action.toolName" }, "payments.create"] },
            { "==": [{ "var": "context.action.toolArgs.currency" }, "EUR"] },
            { ">": [{ "var": "context.action.toolArgs.amount" }, 0] },
            { "<=": [{ "var": "context.action.toolArgs.amount" }, 10000] }
          ]
        }
      },
      "then": {
        "decision": "allow",
        "reason": "Payment is within the approved automatic limit.",
        "reasonCodes": ["payment_within_automatic_limit"]
      },
      "execution": { "mode": "deterministic" },
      "evidence": {
        "evaluatedFields": [
          "context.action.actionType",
          "context.action.toolName",
          "context.action.toolArgs.currency",
          "context.action.toolArgs.amount"
        ],
        "artifactRefs": []
      }
    },
    {
      "ruleId": "review-payment-over-10000",
      "name": "Review payment over EUR 10,000",
      "interceptionPoint": "tool_call",
      "when": {
        "expression": {
          "and": [
            { "in": [{ "var": "context.action.actionType" }, ["tool_input", "tool_call"]] },
            { "==": [{ "var": "context.action.toolName" }, "payments.create"] },
            { "==": [{ "var": "context.action.toolArgs.currency" }, "EUR"] },
            { ">": [{ "var": "context.action.toolArgs.amount" }, 10000] }
          ]
        }
      },
      "then": {
        "decision": "require_approval",
        "reason": "Payment exceeds the approved automatic limit.",
        "reasonCodes": ["payment_over_automatic_limit"],
        "approverGroup": "kla:approver",
        "remediation": {
          "summary": "Obtain a payment approval before execution.",
          "steps": []
        }
      },
      "execution": { "mode": "deterministic" },
      "evidence": {
        "evaluatedFields": [
          "context.action.actionType",
          "context.action.toolName",
          "context.action.toolArgs.currency",
          "context.action.toolArgs.amount"
        ],
        "artifactRefs": []
      }
    }
  ]
}

Die erste Regel erlaubt das Ausführungs-Gate. Eine gebundene Richtlinie wird zum ersten policy_gate des verwalteten Process des Agent, und dieses Gate wird mit dem actionType policy_gate und der Richtlinien-ID als toolName ausgewertet; ohne diese Regel würde der fail-closed Standard jede Ausführung vor dem ersten Werkzeugaufruf stoppen. Die beiden Zahlungsregeln gelten für Werkzeugaufrufe, deren actionType tool_input oder tool_call ist, und schließen sich gegenseitig aus. Ein fehlender, null oder negativer Betrag, eine andere Währung oder ein anderes Werkzeug entspricht keiner Regel und führt zur defaultDecision block. Die Bedingung > 0 ist wichtig: Ein fehlender Betrag wird in Regelausdrücken als 0 ausgewertet und würde sonst <= 10000 erfüllen. approverGroup wird zur erforderlichen Rolle des Decision Request und nennt daher die konfigurierte Rolle kla:approver. Der Richtlinien-Lint weist eine defaultDecision allow mit POLICY_DEFAULT_DECISION_FAIL_OPEN zurück.

Fügen Sie die externe Tenant-ID ein und erstellen Sie den Bootstrap-Entwurf:

jq --arg workspace "$KLA_TENANT_ID" '.workspaceId = $workspace' \
  policy.template.json > policy.json

export POLICY_ID='existing-agent-payment-controls'
export BOOTSTRAP_VERSION='1.0.0'
export POLICY_VERSION='1.1.0'

kla policy registry create --file policy.json
kla policy registry get "$POLICY_ID" --version "$BOOTSTRAP_VERSION" \
  | jq -e '.versions[0].status == "draft"'

Schritt 3: Zwei dauerhafte Simulationen ausführen

Eine Simulation sendet dem Entwurf einen GateContext, den Anfrageumschlag, den die KLA Policy Engine auswertet. Die Policy Registry speichert jede abgeschlossene Simulation mit einer Nachweisreferenz, und die Prüfbereitschaft verlangt eine gespeicherte Simulation des exakten Entwurfsinhalts.

Speichern Sie den GateContext mit niedrigem Betrag als simulate-500.template.json:

{
  "context": {
    "schemaVersion": "1.0.0",
    "occurredAt": "2026-09-06T12:00:00Z",
    "identifiers": {
      "workspaceId": "TENANT_EXTERNAL_ID",
      "environment": "production"
    },
    "agentId": "AGENT_UUID",
    "action": {
      "actionType": "tool_input",
      "toolName": "payments.create",
      "toolArgs": { "amount": 500, "currency": "EUR" },
      "environment": "production"
    }
  }
}

Speichern Sie den GateContext mit hohem Betrag als simulate-15000.template.json:

{
  "context": {
    "schemaVersion": "1.0.0",
    "occurredAt": "2026-09-06T12:00:00Z",
    "identifiers": {
      "workspaceId": "TENANT_EXTERNAL_ID",
      "environment": "production"
    },
    "agentId": "AGENT_UUID",
    "action": {
      "actionType": "tool_input",
      "toolName": "payments.create",
      "toolArgs": { "amount": 15000, "currency": "EUR" },
      "environment": "production"
    }
  }
}

Fügen Sie die Tenant- und Agent-Kennungen ein und führen Sie beide Simulationen aus. kla policy registry simulate sendet den Idempotency-Key-Header, den die Route verlangt.

for amount in 500 15000; do
  jq --arg workspace "$KLA_TENANT_ID" --arg agent "$AGENT_UUID" \
    '.context.identifiers.workspaceId = $workspace | .context.agentId = $agent' \
    "simulate-${amount}.template.json" > "simulate-${amount}.json"
done

kla policy registry simulate "$POLICY_ID" "$BOOTSTRAP_VERSION" \
  --input @simulate-500.json > simulation-500.json
jq -e '
  .decision.decision == "allow" and
  .decision.primaryBasis.ruleId == "allow-payment-up-to-10000" and
  (.simulation.simulationId | type == "string") and
  (.simulation.evidenceId | type == "string")
' simulation-500.json

kla policy registry simulate "$POLICY_ID" "$BOOTSTRAP_VERSION" \
  --input @simulate-15000.json > simulation-15000.json
jq -e '
  .decision.decision == "require_approval" and
  .decision.primaryBasis.ruleId == "review-payment-over-10000" and
  .decision.approval.assigneeGroup == "kla:approver" and
  (.simulation.simulationId | type == "string") and
  (.simulation.evidenceId | type == "string")
' simulation-15000.json

Beide Prüfungen müssen bestanden sein, bevor der Entwurf eingereicht wird. Jede spätere Änderung am Entwurf ändert seinen Inhalts-Hash und verlangt eine neue Simulation.

Schritt 4: Die Bootstrap-Version einreichen und genehmigen

Der Maker reicht Version 1.0.0 ein, und der Checker genehmigt sie. Die Version bleibt approved und wird nie veröffentlicht, sodass sie für kein Gate wirksam wird.

kla policy registry submit-review "$POLICY_ID" "$BOOTSTRAP_VERSION" \
  --comment 'Threshold outcomes and fail-closed default verified by Simulation.'

KLA_ACCESS_TOKEN="$KLA_CHECKER_ACCESS_TOKEN" \
  kla policy registry review "$POLICY_ID" "$BOOTSTRAP_VERSION" \
  --decision approve \
  --comment 'Rule scope, outcomes, and Simulation evidence reviewed.' \
  --yes

kla policy registry get "$POLICY_ID" --version "$BOOTSTRAP_VERSION" \
  | jq -e '.versions[0].status == "approved"'

Eine 409-Antwort mit readiness nennt die blockierende Prüfung. required_simulation_missing bedeutet, dass die gespeicherte Simulation nicht zum aktuellen Entwurfsinhalt passt; wiederholen Sie Schritt 3.

Schritt 5: Dem Agent seine gesteuerte Umgebung geben

kla agent policy bind akzeptiert eine genehmigte, veröffentlichte oder aktive Richtlinie. Der Befehl schreibt die Bindung in einen neuen Agent-Entwurf, erstellt den verwalteten Process für die gesteuerte Umgebung und liefert die Entwurfs-UUID. Der Checker genehmigt den Entwurf und veröffentlicht ihn damit als unveränderliches Release, und der Maker stellt das Release bereit. agent release deploy verlangt eine production-Bindung und verschiebt das aktive Manifest des Agent, aus dem die gesteuerte Umgebung bei der Richtlinienprüfung gelesen wird.

kla agent policy bind "$AGENT_UUID" \
  --policy "$POLICY_ID" \
  --environment production \
  --description 'Bind the reviewed payment control to establish the production environment.' \
  > agent-binding-bootstrap.json

jq -e --arg agent "$AGENT_UUID" '.success == true and .agentId == $agent' \
  agent-binding-bootstrap.json
export BOOTSTRAP_DRAFT_UUID="$(jq -er '.draftId' agent-binding-bootstrap.json)"

KLA_ACCESS_TOKEN="$KLA_CHECKER_ACCESS_TOKEN" \
  kla agent release approve "$BOOTSTRAP_DRAFT_UUID" \
  --notes 'Bootstrap binding for the production governed environment reviewed.' \
  --yes | jq -e '.success == true'

kla agent release deploy "$BOOTSTRAP_DRAFT_UUID" --yes > agent-rollout-bootstrap.json

kla agent get "$AGENT_UUID" \
  | jq -e '.manifest.governedExecution.environment == "production"'

Von hier bis zum Abschluss von Schritt 8 verweist der verwaltete Process des Agent auf eine unveröffentlichte Richtlinienversion, und seine Ausführungen schlagen fail-closed fehl.

Schritt 6: Die Agent-spezifische Version erstellen, simulieren und prüfen

Version 1.1.0 hat dieselben Regeln und nennt den Agent in scope.agentIds. Die Simulationseingaben aus Schritt 3 werden wiederverwendet.

jq --arg workspace "$KLA_TENANT_ID" --arg agent "$AGENT_UUID" --arg version "$POLICY_VERSION" \
  '.workspaceId = $workspace | .version = $version | .scope.agentIds = [$agent]' \
  policy.template.json > policy-agent-scoped.json

kla policy registry create --file policy-agent-scoped.json

kla policy registry simulate "$POLICY_ID" "$POLICY_VERSION" \
  --input @simulate-500.json | jq -e '.decision.decision == "allow"'
kla policy registry simulate "$POLICY_ID" "$POLICY_VERSION" \
  --input @simulate-15000.json | jq -e '.decision.decision == "require_approval"'

kla policy registry submit-review "$POLICY_ID" "$POLICY_VERSION" \
  --comment 'Agent-scoped version; outcomes verified by Simulation.'

KLA_ACCESS_TOKEN="$KLA_CHECKER_ACCESS_TOKEN" \
  kla policy registry review "$POLICY_ID" "$POLICY_VERSION" \
  --decision approve \
  --comment 'Agent scope, outcomes, and Simulation evidence reviewed.' \
  --yes

kla policy registry get "$POLICY_ID" --version "$POLICY_VERSION" \
  | jq -e '.versions[0].status == "approved"'

Die Prüfbereitschaftskontrolle löst jeden Agent aus scope.agentIds in der Agent Registry auf und verlangt, dass jeder eine gesteuerte Umgebung trägt, die zu scope.environments passt. Schritt 5 hat das für diesen Agent erfüllt.

Schritt 7: Veröffentlichen

Der Maker beantragt die Veröffentlichung. Im Modus two_person liefert die Anfrage pendingApproval: true und eine Decision-Request-Kennung.

export KLA_EFFECTIVE_FROM="$(date -u +%Y-%m-%dT%H:%M:%SZ)"

kla policy registry publish "$POLICY_ID" "$POLICY_VERSION" \
  --effective-from "$KLA_EFFECTIVE_FROM" \
  --reason 'Activate the reviewed payment control.' \
  --yes > publication-request.json

jq -e '.success == true and .pendingApproval == true and .status == "PENDING"' \
  publication-request.json
export APPROVAL_UUID="$(jq -er '.approvalId' publication-request.json)"

Der Checker entscheidet den Decision Request über approvals.decide:

jq -n --arg approvalId "$APPROVAL_UUID" '{
  approvalId: $approvalId,
  decision: "approve",
  decisionAcknowledged: true,
  reason: "Reviewed policy version approved for publication."
}' > approval-decision.json

KLA_ACCESS_TOKEN="$KLA_CHECKER_ACCESS_TOKEN" \
  kla api approvals decide --input @approval-decision.json > publication-decision.json
jq -e '.decision == "approve" and .status == "APPROVED"' publication-decision.json

Die Veröffentlichung läuft, nachdem die Entscheidung aufgezeichnet wurde. Warten Sie, bis die Version published oder active erreicht, und lesen Sie dann das kompilierte Richtlinienpaket.

for attempt in $(seq 1 30); do
  kla policy registry get "$POLICY_ID" --version "$POLICY_VERSION" > published-policy.json
  jq -e '.versions[0].status == "published" or .versions[0].status == "active"' \
    published-policy.json > /dev/null && break
  sleep 2
done
jq -e '.versions[0].status == "published" or .versions[0].status == "active"' \
  published-policy.json

kla policy registry compiled "$POLICY_ID" "$POLICY_VERSION" > compiled-policy.json
jq -e --arg policy "$POLICY_ID" --arg version "$POLICY_VERSION" '
  .integrity.policyId == $policy and
  .integrity.policyVersion == $version and
  .integrity.manifestHashVerified == true
' compiled-policy.json

integrity.verification.status ist PASS, wenn der Tenant Richtlinienpakete signiert, und SKIPPED, wenn die Signierung in dieser Umgebung ausgeschaltet ist. Brechen Sie ab, wenn die Version unveröffentlicht bleibt oder manifestHashVerified false ist.

Schritt 8: Die veröffentlichte Version binden

Die Bindung wählt die aktive oder veröffentlichte Version der Richtlinie, sodass derselbe Bindungsbefehl jetzt Version 1.1.0 festhält und den verwalteten Process aktualisiert. Der Checker genehmigt den neuen Entwurf, und der Maker stellt ihn bereit.

kla agent policy bind "$AGENT_UUID" \
  --policy "$POLICY_ID" \
  --environment production \
  --description 'Bind the published Agent-scoped payment control.' \
  > agent-binding.json

jq -e --arg agent "$AGENT_UUID" '.success == true and .agentId == $agent' agent-binding.json
export DRAFT_UUID="$(jq -er '.draftId' agent-binding.json)"

kla agent release history "$AGENT_UUID" > agent-history-draft.json
jq -e --arg release "$DRAFT_UUID" --arg policy "$POLICY_ID" --arg version "$POLICY_VERSION" '
  any(.versions[];
    .id == $release and
    .is_draft == true and
    .manifest.governedExecution.policyId == $policy and
    .manifest.governedExecution.policyVersion == $version)
' agent-history-draft.json

KLA_ACCESS_TOKEN="$KLA_CHECKER_ACCESS_TOKEN" \
  kla agent release approve "$DRAFT_UUID" \
  --notes 'Published policy binding and managed Process reviewed.' \
  --yes | jq -e '.success == true'

kla agent release deploy "$DRAFT_UUID" --yes > agent-rollout.json

Die Historienprüfung zeigt dem Checker vor der Genehmigung, dass der Entwurf die Bindung an Version 1.1.0 trägt.

Schritt 9: Verifizieren

Lesen Sie den Agent und seine Release-Historie.

kla agent get "$AGENT_UUID" > agent-after.json
jq -e --arg policy "$POLICY_ID" --arg version "$POLICY_VERSION" '
  .manifest.governedExecution.policyId == $policy and
  .manifest.governedExecution.policyVersion == $version and
  .manifest.governedExecution.environment == "production" and
  (.manifest.governedExecution.workflowId | type == "string") and
  any(.passport.activePolicies[]; .policyId == $policy and .version == $version)
' agent-after.json

kla agent release history "$AGENT_UUID" > agent-history.json
jq -e --arg release "$DRAFT_UUID" '
  any(.versions[];
    .id == $release and
    .is_draft == false and
    .is_current_version == true and
    .approved_at != null and
    .deployed_at != null)
' agent-history.json

Führen Sie beide Simulationen gegen die veröffentlichte Version aus und bewahren Sie die Ergebnisse beim Änderungsdatensatz auf.

kla policy registry simulate "$POLICY_ID" "$POLICY_VERSION" \
  --input @simulate-500.json | jq -e '.decision.decision == "allow"'

kla policy registry simulate "$POLICY_ID" "$POLICY_VERSION" \
  --input @simulate-15000.json | jq -e '.decision.decision == "require_approval"'

Sie haben jetzt eine veröffentlichte, Agent-spezifische Richtlinie, deren Simulationen 500 EUR zu allow und 15.000 EUR zu require_approval auflösen, sowie ein bereitgestelltes Agent-Release, das sie bindet. Ein echter payments.create-Aufruf über 10.000 EUR von diesem Agent öffnet im Decision Desk einen Decision Request für die Rolle kla:approver. Die Anleitung Einen Agent durchgängig steuern behandelt die anschließende Ausführung, Genehmigung und den Nachweisexport.

Einen bestehenden Agent mit einer Richtlinie steuern | Developer Docs | KLA Control Plane