Skip to main content

What does validate do?

The validate command checks a transaction against the policy engine before your agent signs anything. If the policy allows it, you get an intentId. If it blocks, you get a blockReason. If it requires approval, you get an intentId and a prompt to wait. Preflight validation is action-based. You describe what you want to do, and the policy engine evaluates it. No gas parameters, no calldata, no intentHash computation.
npx @mandate.md/cli validate \
  --action transfer \
  --amount 50 \
  --to 0x036CbD53842c5426634e7929541eC2318f3dCF7e \
  --token USDC \
  --reason "Payment for API access"

Options

FlagRequiredDescription
--actionYesAction type: transfer, approve, swap, or custom
--reasonYesPlain-language explanation of why the agent is transacting
--amountNoAmount in token units
--toNoDestination address (0x…)
--tokenNoToken symbol (e.g. USDC) or contract address
--chainNoChain name or chain ID

Success output

{
  "ok": true,
  "intentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "feedback": "Mandate: policy check passed"
}

Blocked output

{
  "error": "POLICY_BLOCKED",
  "message": "Mandate: blocked: amount exceeds per-transaction limit",
  "blockReason": "SPEND_LIMIT_PER_TX"
}
The blockReason code tells you exactly which policy check failed. See the block reasons reference for the full list.

Approval required

When the transaction triggers an approval workflow, the response includes the intentId and a next step:
{
  "ok": true,
  "requiresApproval": true,
  "intentId": "a1b2c3d4-...",
  "feedback": "Mandate: approval required, waiting for owner decision",
  "next": "Run: mandate approve a1b2c3d4-..."
}
Run mandate approve <intentId> to poll until the owner approves or rejects in the dashboard.

The reason field

Every validation requires a --reason. This is not optional decoration. The policy engine scans the reason for prompt injection patterns, anomalous behavior, and policy violations. A clear, specific reason (“Payment for March invoice from Acme Corp”) is more likely to pass than a vague one (“sending money”).
If you omit --reason, the command returns an error. The policy engine requires it for every transaction.

Raw mode (legacy)

Raw mode sends full EVM transaction parameters and computes an intentHash locally. Use this only for self-custodial flows where you build the transaction yourself.
Deprecated. Use preflight mode instead. Raw validation is kept for legacy self-custodial flows but will be removed in a future version.
npx @mandate.md/cli validate --raw \
  --to 0x036CbD53842c5426634e7929541eC2318f3dCF7e \
  --calldata 0xa9059cbb000000000000000000000000 \
  --nonce 42 \
  --gasLimit 90000 \
  --maxFeePerGas 1000000000 \
  --maxPriorityFeePerGas 1000000000 \
  --reason "Invoice #127 from Alice"

Raw mode required flags

FlagDescription
--rawEnable raw EVM validation
--toContract or recipient address
--nonceTransaction nonce
--gasLimitGas limit
--maxFeePerGasMax fee per gas (wei)
--maxPriorityFeePerGasMax priority fee per gas (wei)
--reasonWhy this transaction is being sent

Raw mode optional flags

FlagDefaultDescription
--calldata0xTransaction calldata
--valueWei0Value in wei
--chainIdFrom credentialsChain ID
--txType2Transaction type
--accessList[]Access list (JSON string)
Raw mode returns an additional next field pointing to the event command for posting the txHash after broadcast.

Next Steps

Transfer Command

Shorthand for ERC20 transfers with automatic action mapping.

Wait for Approval

Poll until the owner approves a pending intent.

Validate Guide

End-to-end walkthrough of the validation flow.