2AYE
Examples

The four things
you came here to do.

Working recipes with the JavaScript SDK’s real exports: authorize an agent action, gate it behind a named human, leave evidence of what ran, and protect the resource itself. The same loop reads identically in the other five languages.

  • 4 recipes
  • 1 security model
  • Real SDK surface
  1. 01

    Authorize an AI agent action

    Evaluate a proposed action against a signed intent, and only execute inside the helper that verifies the grant, redeems it once, and records what ran.

    executeWithAuthorization verifies the ES256 signature and exact envelope, redeems the single-use grant at the resource, runs your function, and submits the execution receipt - on failure as well as success.

    import {
      VeridProcurementClient,
      VeridGrantVerifier,
      executeWithAuthorization
    } from "@verid/agent-sdk";
    
    const client = new VeridProcurementClient({
      baseUrl, tenantId, accessToken
    });
    
    const proposal = {
      intentId: signedIntentId,
      agentId,
      tool: "datadog-billing",
      action: "renew",
      amount: "13800.00",
      currency: "USD",
      counterparty: "datadog"
    };
    
    const envelope = client.envelopeFor(proposal);
    const decision = await client.evaluate(proposal);
    if (decision.decision !== "ALLOW") {
      throw new Error(`Refused: ${decision.decision}`);
    }
    
    const grant = await client.authorizationById(decision.authorizationId);
    const verifier = new VeridGrantVerifier({baseUrl});
    
    const result = await executeWithAuthorization({
      client, verifier, grant, envelope, agentId,
      execute: () => renewSubscription(proposal),
      externalReference: "invoice-2026-0031"
    });
  2. 02

    Require human approval

    When the amount crosses the intent's approval threshold, the decision comes back REQUIRE_APPROVAL instead of ALLOW. Wait for a named human, then proceed only if they approved.

    The approval is a named, expiring decision bound to the exact envelope that was evaluated - who approved, what, when, and under which decision id are all recorded in the audit chain. Changing any material parameter afterwards invalidates it; there is no approved-in-general state.

    const decision = await client.evaluate({
      ...proposal,
      amount: "7500.00"   // above the 5,000 approval threshold
    });
    
    if (decision.decision === "REQUIRE_APPROVAL") {
      // Polls /v1/runtime/approvals/{id} until a named human decides,
      // or the timeout elapses. A timeout throws - it never approves.
      const approval = await client.waitForApproval(decision.approvalId, {
        timeoutMs: 300000,
        intervalMs: 1000
      });
    
      if (approval.status !== "Approved") {
        throw new Error(`Not approved: ${approval.status}`);
      }
    
      // The approval is an evidence artifact, not a flag. It records who
      // decided, what exact envelope they decided on, when, and under which
      // decision - and it joins the same audit chain as the receipt.
      console.log({
        approvedBy: approval.decidedBy,      // the named human
        evaluationId: approval.evaluationId, // the decision it answers
        actionHash: approval.actionHash,     // exactly what was approved
        decidedAt: approval.updatedAt,
        expiresAt: approval.expiresAt
      });
    }
    
    // The approval is bound to this exact action. Re-evaluate or fetch the
    // grant it unlocked; a different amount would need its own decision.
    const grant = await client.authorizationById(decision.authorizationId);
  3. 03

    Issue an evidence receipt

    Record what actually executed so the approved action and the executed action can be compared. The helper does this automatically; do it manually when you execute outside it.

    The receipt joins the hash-linked audit chain next to the decision, the grant, and the redemption. An authorization without a receipt is a visible gap, not a silent one.

    // Automatic: executeWithAuthorization submits the receipt for you,
    // with status recorded on success and on failure.
    
    // Manual, when your execution happens elsewhere:
    await client.submitReceipt({
      authorizationId: grant.id,
      status: "Succeeded",
      externalReference: "invoice-2026-0031",
      evidence: {
        invoiceTotal: "13800.00",
        confirmedBy: "billing-api"
      },
      executed: {
        tool: "datadog-billing",
        action: "renew",
        amount: "13800.00",
        currency: "USD"
      }
    });
  4. 04

    Protect a production deployment

    Flip the perspective: you own the protected resource. Caller possession of a decision or grant is insufficient - the protected resource independently verifies and redeems it. Refuse to deploy unless that verification and redemption succeed for this exact action.

    This is the most important idea on the page: the caller does not get to declare itself authorized. Verification and redemption happen where the action executes, so a compromised caller cannot skip them. Production verification refuses ephemeral signing keys by default.

    import {VeridGrantVerifier} from "@verid/agent-sdk";
    
    // Inside the deploy service - the protected resource.
    const verifier = new VeridGrantVerifier({baseUrl});
    
    export async function deploy({grant, envelope, agentId, release}) {
      // 1. Independent verification: ES256 signature against the
      //    published keys, and the exact envelope this grant covers.
      await verifier.verify(grant, {tenantId, agentId, envelope});
    
      // 2. Single-use redemption, here, immediately before acting.
      //    A replayed or already-consumed grant fails this call.
      await client.consume({
        authorizationId: grant.id,
        agentId,
        envelope
      });
    
      // 3. Only now does the consequential action run.
      const outcome = await rollOut(release);
    
      await client.submitReceipt({
        authorizationId: grant.id,
        status: "Succeeded",
        externalReference: release.id,
        executed: {tool: "deploy", action: "release", environment: "production"}
      });
      return outcome;
    }
The enforcement path

Follow each recipe above from identity to evidence.

Each consequential action moves through the same six control points. See where 2AYE evaluates authority, requests human review, and preserves the outcome.

  1. 01IdentityWho or what is acting
  2. 02IntentSigned purpose and limits
  3. 03PolicyDeterministic evaluation
  4. 04ApprovalA named human when required
  5. 05ExecutionSingle-use grant, redeemed at the resource
  6. 06EvidenceReceipt joined to the audit chain
Deterministic decisionsSingle-use, exact-action grantsHash-linked evidence
Your governed workflow

Bring the next consequential action under control.

Show us the actor, protected resource, and action that must never execute without exact authority. We’ll map the decision and evidence path with you.

Discuss your workflow Read the implementation guide
Examples | 2AYE