Vincent Abilities are modular, executable functions that define what operations your App can perform on behalf of users. This guide explains their structure, lifecycle, and implementation details.
Ability Lifecycle
Vincent Abilities execute in two phases to ensure reliability and security:
Precheck
Runs locally to validate that execution will likely succeed. This also runs precheck
on the Vincent Policies to ensure they are valid as well
Execute
Runs in the Lit Action environment to perform the actual operation. Policies also run their evaluate
function here
Only if all policies return allow
results will your Ability’s function execute. After successful execution, the Ability can optionally call Policy commit functions to update state.
Defining Your Ability
The npm package name of your Ability (e.g., @your-org/ability-name
)
A clear description of what your Ability does
Zod schema defining the input parameters your Ability requires
supportedPolicies
SupportedPolicies
required
Array of supported Vincent Policies, created with supportedPoliciesForAbility()
Zod schema for successful precheck return values
Zod schema for failed precheck return values
Async function that validates execution will likely succeed ( params : { abilityParams }, context : AbilityContext ) => Promise < PrecheckResult >
Zod schema for successful execution return values
Zod schema for failed execution return values
Async function that performs the actual Ability operation ( params : { abilityParams }, context : AbilityContext ) => Promise < ExecuteResult >
Creating Vincent Abilities
Vincent Abilities are created using createVincentAbility
from the Vincent Ability SDK:
import { createVincentAbility } from '@lit-protocol/vincent-ability-sdk' ;
export const vincentAbility = createVincentAbility ({
packageName: '@your-org/ability-name' ,
abilityDescription: 'What this ability does' ,
abilityParamsSchema ,
supportedPolicies: supportedPoliciesForAbility ([]),
precheckSuccessSchema ,
precheckFailSchema ,
precheck : async ({ abilityParams }, abilityContext ) => {
// Validation logic
},
executeSuccessSchema ,
executeFailSchema ,
execute : async ({ abilityParams }, abilityContext ) => {
// Main execution logic
},
});
Example Implementation
Full Token Transfer Ability
import {
createVincentAbility ,
createVincentAbilityPolicy ,
supportedPoliciesForAbility ,
} from '@lit-protocol/vincent-ability-sdk' ;
import { bundledVincentPolicy } from '@lit-protocol/vincent-policy-spending-limit' ;
import { z } from 'zod' ;
const abilityParamsSchema = z . object ({
tokenAddress: z . string (),
amountToSend: z . number (),
recipientAddress: z . string (),
});
const SpendingLimitPolicy = createVincentAbilityPolicy ({
abilityParamsSchema ,
bundledVincentPolicy ,
abilityParameterMappings: {
tokenAddress: 'tokenAddress' ,
amountToSend: 'amount' ,
},
});
export const vincentAbility = createVincentAbility ({
packageName: '@example/token-transfer-ability' ,
abilityDescription: 'Transfer ERC20 tokens to a recipient address' ,
abilityParamsSchema ,
supportedPolicies: supportedPoliciesForAbility ([ SpendingLimitPolicy ]),
precheckSuccessSchema: z . object ({
tokenBalance: z . number (),
estimatedGas: z . number (),
}),
precheckFailSchema: z . object ({
reason: z . string (),
currentBalance: z . number (). optional (),
requiredAmount: z . number (). optional (),
}),
executeSuccessSchema: z . object ({
transferTransactionHash: z . string (),
spendTransactionHash: z . string (). optional (),
}),
executeFailSchema: z . object ({
error: z . string (),
errorCode: z . string (). optional (),
}),
precheck : async ({ abilityParams }, abilityContext ) => {
// Validation logic here
},
execute : async ({ abilityParams }, abilityContext ) => {
// Execution logic here
},
});
Deep Dive Guides