Integration plan

Integrating real-time MiCA enforcement in one sprint

A realistic day-by-day plan for adding pre-execution, MiCA-aligned policy enforcement to an AI agent that already moves money — using only the documented Intaglio SDK and proxy API, no undocumented endpoints.

Day 1-2: write the APL policy

Encode existing limits and requirements (per-transaction caps, sanctions screening, destination allowlists, human-approval thresholds) as an APL policy file. This is usually a direct translation of an existing written treasury/compliance policy, not new policy design:

policy treasury-agent v1.0.0
agent  treasury-bot-01
operator acme-gmbh

scope {
  rails      [x402 solana-pay]
  currencies [USDC USDT]
}

limit {
  per_transaction { value 10000 currency USDC }
  per_day         { value 50000 currency USDC }
}

require {
  human_approval_above { value 5000  currency USDC }
  deny_if_sanctioned   true
  deny_if_destination  NOT_IN whitelist.json
}

obligation {
  log_to    solana:devnet
  retention 7y
}

Day 3: wrap outbound calls with the SDK

Install @intaglio/sdk and wrap the agent's existing outbound request function. This matches the documented fetch-wrapper pattern:

// intaglioFetcher.ts
import { randomUUID } from "crypto";

const INTA_PROXY_URL = process.env.INTA_PROXY_URL || "http://localhost:3001";
const INTA_AGENT_SECRET = process.env.INTA_AGENT_SECRET;

export async function intaglioFetch(actionObj: any, upstreamUrl: string, fetchOptions: RequestInit = {}) {
  const idempotencyKey = randomUUID();

  const response = await fetch(`${INTA_PROXY_URL}/v1/x402/forward`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${INTA_AGENT_SECRET}`,
      "Idempotency-Key": idempotencyKey,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      action: actionObj,
      x402_request: { url: upstreamUrl, options: fetchOptions },
    }),
  });

  if (!response.ok) {
    throw new Error(`[Intaglio] Enforced short-circuit: ${response.statusText}`);
  }

  return response;
}

Day 4: wire up REQUIRE_APPROVAL handling

Anything above the human-approval threshold needs a poll or webhook to resolve the pending decision before the agent can continue:

import { IntaglioClient } from "@intaglio/sdk";

const client = new IntaglioClient({
  baseUrl: process.env.INTA_PROXY_URL!,
  agentToken: process.env.INTA_AGENT_SECRET!,
});

const result = await client.enforce({ type: "payment", amount: 8000, currency: "USDC" });

if (result.decision.outcome === "REQUIRE_APPROVAL") {
  const approval = await client.getApproval(result.approval_id!);
  // GET /v1/approvals/:id -> { status: "APPROVED" | "PENDING" | "DENIED", ... }
}

Day 5: verify the audit chain, not just the happy path

Submit a deliberately out-of-policy action and confirm it is actually rejected — not just that the policy file parses:

curl -X POST http://localhost:3001/v1/actions \
  -H "Authorization: Bearer <agent-secret>" \
  -H "Content-Type: application/json" \
  -d '{
    "action": {
      "rail": "x402",
      "amount": { "value": 999999, "currency": "USD" },
      "timestamp": "2026-07-06T00:00:00Z"
    }
  }'
# Expect: { "decision": { "outcome": "DENY" }, ... }

Then confirm each returned record's prev_record_hash matches the self_hash of the record before it — that chain is what makes the audit trail tamper-evident rather than just a database table.

[VERIFY] "One sprint" assumes a team already operating the agent and an existing written policy to translate into APL. Teams without a documented policy, or needing custom rails beyond x402/solana-pay, should budget more time.

Start enforcing policy today

MiCA CASP enforcement is active as of July 1, 2026.

Open dashboardRead the APL spec