Skip to content

Intent Contracts

Plan-level authorisation. Instead of judging every action in isolation, the Xybern Authorisation Layer can authorise the whole mission once, then check every action against the approved plan.

An agent (or a human on its behalf) submits its mission plan in natural language. Xybern compiles the plan into a bounded permission set: the specific actions the plan requires, per-action caps (maximum amount, maximum uses), actions that must still be held for a human, whole-mission budgets, an expiry, and plain-English guardrails. A reviewer approves the compiled contract once in the dashboard, it is HMAC signed and sealed to the Provenance Vault, and from then on every intercept carrying the contract gets a cheap, deterministic conformance check. In-plan actions flow fast. Out-of-plan actions block or escalate.

One approval per mission instead of one escalation per action, and stricter at the same time, because the approved plan is part of every decision.

Lifecycle

submit (plan compiled by LLM)  →  pending
pending   →  active     (human approves in the dashboard; contract is signed)
pending   →  rejected
active    →  completed  (mission finished)
active    →  revoked    (pulled by an operator)
active    →  expired    (validity window passed, checked lazily)

The compiled permission set

{
  "allowed": [
    {"action": "query_database", "max_amount": null, "max_count": 2, "note": "Look up order 8841"},
    {"action": "make_payment",   "max_amount": 200,  "max_count": 1, "note": "Refund for order 8841"},
    {"action": "send_email",     "max_amount": null, "max_count": 1, "note": "Confirmation to the customer"}
  ],
  "escalated": [
    {"action": "transfer_funds", "reason": "Bank transfers must be held for approval"}
  ]
}
  • action is an exact action type or a prefix* wildcard.
  • max_amount caps the monetary value of a single use (read from structured metadata).
  • max_count caps how many times the action may run within the contract.
  • Entries in escalated are always held for a human, even on an enforce contract.
  • Whole-mission budgets live beside the permission set: {"max_actions": 14, "max_total_amount": 200, "ttl_hours": 24}.
  • Guardrails ([{"rule": "Only touch order 8841 and its customer"}]) are shown to the reviewer and fed to the intent judge; they are not enforced deterministically in this version.

Conformance semantics

On every intercept carrying a contract_id, in order: the contract must be active and unexpired, mission budgets must have headroom, then the action is matched against the allowed entries (exact names first, then wildcards, most specific first). A matching entry must also pass its amount cap and use count. The first entry that passes consumes budget and the action is in plan. A match in the escalated list means held for approval. Anything else is out of plan.

Amounts are read from structured metadata (keys containing amount, value, price, total, fee and similar). An amount hidden in free text will not hit a cap; the mission budget, normal policies and the LLM intent judge remain in force for that case.

Observe vs enforce

Mode In plan Out of plan
observe (default) recorded, decision unchanged recorded as drift in the vault, decision unchanged
enforce fast path: LLM verification skipped, policies still run and always win blocked or escalated per on_violation, sealed as a violation, webhook fired

Policies always win: a policy block or escalate applies even to an in-plan action on an enforce contract. Expired, exhausted, revoked and pending contracts are treated as out of plan with a clear reason. A stale or unknown contract_id never breaks enforcement; the action simply gets normal evaluation.

Risk Verdict anchoring

When a contract is present, the Risk Verdict's intent alignment dimension is judged against the approved mission plan (the sharpest declared intent available), and on paths where the LLM does not run it is synthesized deterministically from the conformance result. The decision record carries the full conformance detail in decision_analysis.contract_conformance and the response in contract.

API

Agent facing (API key auth):

Method Path Notes
POST /v1/enforce/contracts {plan_text, agent_id?, session_id?, mode?, on_violation?, expires_in_hours?} → compiled contract, status pending
GET /v1/enforce/contracts list, filter by status, agent_id
GET /v1/enforce/contracts/{id} full detail including signature and consumption
GET /v1/enforce/contracts/{id}/status lightweight poll
POST /v1/enforce/contracts/{id}/complete mark the mission finished
POST /v1/enforce/intercept pass contract_id alongside the action

Dashboard (Intent Contracts tab): review the compiled permission table, approve (choosing observe or enforce and the violation behavior), reject, revoke, and watch budget consumption live.

SDK

from xybern import Xybern

client = Xybern(api_key="xb_live_...")

contract = client.enforce.submit_contract(
    "Look up order 8841, issue a refund of up to 200 dollars, then email a confirmation to the customer.",
    agent_id="support-bot", mode="enforce")

client.enforce.wait_until_approved(contract["contract_id"])

result = client.enforce.intercept(
    "make_payment", "Refund 150 dollars for order 8841",
    metadata={"amount": 150, "order_id": "8841"},
    agent_id="support-bot", contract_id=contract["contract_id"])
# result["decision"] == "allow", result["decision_path"] == "contract"

client.enforce.complete_contract(contract["contract_id"])

Webhooks and vault

Webhook events: contract.submitted, contract.approved, contract.rejected, contract.violation.

Every lifecycle event (submission, approval, rejection, revocation, completion, expiry, observe-mode drift, enforce-mode violations) is sealed to the Provenance Vault with source_type intent_contract. On approval the contract terms (permission set, budgets, expiry, approver, approval time) are HMAC signed with the workspace vault key over canonical JSON, so the approved terms are tamper evident twice: in the signature and in the hash chain.