Skip to main content
The evaluate function provides final validation with full blockchain access in the Lit Action environment. This is where your Policy makes the definitive allow/deny decision.

Function Parameters

The evaluate function receives two parameters:
params
object
required
Object containing the ability and user parameters
policyContext
object
required
Context object provided by the SDK with helpers and metadata

Response Schemas

Allow Response

evalAllowResultSchema
ZodSchema
required
A Zod schema that defines the structure of successful evaluation results. Include details about why the evaluation passed, such as current state and validation context.

Deny Response

evalDenyResultSchema
ZodSchema
required
A Zod schema that defines the structure of failed evaluation results. Include details about why the evaluation failed, such as exceeded limits or validation errors.
  • Allow Schema
  • Deny Schema
import { createVincentPolicy } from '@lit-protocol/vincent-ability-sdk';
import { z } from 'zod';

const vincentPolicy = createVincentPolicy({
  // ... other policy definitions

  evalAllowResultSchema: z.object({
    maxDailySpendingLimit: z.number(),
    currentDailySpending: z.number(),
    allowedTokens: z.array(z.string()),
  }),
});
If any unhandled error occurs during evaluation, the Vincent Ability SDK automatically returns a deny result with the error message.

Example Implementation

import { createVincentPolicy } from '@lit-protocol/vincent-ability-sdk';
import { z } from 'zod';

const vincentPolicy = createVincentPolicy({
  // ... other policy definitions

  evalAllowResultSchema: z.object({
    maxDailySpendingLimit: z.number(),
    currentDailySpending: z.number(),
    allowedTokens: z.array(z.string()),
  }),

  evalDenyResultSchema: z.object({
    reason: z.string(),
    maxDailySpendingLimit: z.number(),
    currentDailySpending: z.number(),
    allowedTokens: z.array(z.string()),
  }),

  evaluate: async ({ abilityParams, userParams }, policyContext) => {
    const { amount, tokenAddress } = abilityParams;
    const { dailySpendingLimit, allowedTokens } = userParams;

    const isTokenAllowed = allowedTokens.includes(tokenAddress);
    const { isSpendingLimitExceeded, currentDailySpending } = await checkSpendingLimit(
      tokenAddress,
      amount,
      dailySpendingLimit,
    );

    if (!isTokenAllowed) {
      return policyContext.deny({
        reason: 'Token not allowed',
        maxDailySpendingLimit: dailySpendingLimit,
        currentDailySpending,
        allowedTokens: allowedTokens,
      });
    }

    if (isSpendingLimitExceeded) {
      return policyContext.deny({
        reason: 'Spending limit exceeded',
        maxDailySpendingLimit: dailySpendingLimit,
        currentDailySpending,
        allowedTokens: allowedTokens,
      });
    }

    return policyContext.allow({
      maxDailySpendingLimit: dailySpendingLimit,
      currentDailySpending,
      allowedTokens: allowedTokens,
    });
  },
});

Best Practices

  1. Use Fresh Data - Query current state rather than relying on cached values
  2. Consistent with Precheck - Apply the same validation logic as your precheck function
  3. Handle Errors Gracefully - Provide clear error messages for debugging
  4. Return Context - Include current state information in allow/deny responses

Next Steps

I