The Vincent Scaffold SDK is a specialized framework for creating Vincent Abilities and Vincent Policies that execute on Lit Actions - a blockchain-based execution environment with strict constraints. This document provides essential guidance for AI agents working with Vincent projects.
Vincent abilities and policies execute in a restricted environment:
- ❌ NO
globalThis- Standard global objects are not available - ❌ NO
process.env- Environment variables cannot be accessed - ❌ NO persistent memory - State doesn't persist between executions
- ❌ NO file system access - Cannot read/write files during execution
- ❌ NO standard Node.js APIs - Limited runtime environment
- NEVER use mock or fake data in implementations
- NEVER assume environment variables are available in abilities/policies
- NEVER rely on persistent state within the execution context
- NEVER use standard Node.js modules in ability/policy logic
- Vincent Abilities - Executable actions (e.g., token transfers, API calls)
- Vincent Policies - Governance rules that control ability execution
- Lit Actions - Secure execution environment for abilities/policies
- E2E Testing Framework - Integrated testing with blockchain simulation
- Precheck - Validate inputs (runs outside Lit Actions)
- Execute - Perform the operation (runs in Lit Actions)
- Precheck - Early validation (runs outside Lit Actions)
- Evaluate - Runtime checks (runs in Lit Actions)
- Commit - Record state changes (runs in Lit Actions)
All Vincent components MUST use Zod schemas for type safety:
// Ability parameters
export const abilityParamsSchema = z.object({
to: z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid address"),
amount: z.string().regex(/^\d*\.?\d+$/, "Invalid amount")
});
// Result schemas for each phase
export const precheckSuccessSchema = z.object({...});
export const precheckFailSchema = z.object({...});
export const executeSuccessSchema = z.object({...});
export const executeFailSchema = z.object({...});- Define schemas BEFORE implementation
- Use descriptive error messages
- Export type definitions:
export type AbilityParams = z.infer<typeof abilityParamsSchema>; - Validate ALL inputs and outputs
This are available in the:
- execute() hook inside the vincent policy
- evaluate() hook inside the vincent ability
import { laUtils } from "@lit-protocol/vincent-scaffold-sdk/la-utils";
laUtils.transaction.handler.contractCall(); // Execute contract calls
laUtils.transaction.handler.nativeSend(); // Send native tokens
laUtils.helpers.toEthAddress(); // Address utilities- ✅ CAN use in ability
executehooks - ✅ CAN use in policy
evaluateandcommithooks - ❌ CANNOT use in
precheckhooks (not in Lit Actions context)
vincent-packages/
├── abilities/
│ └── my-ability/
│ ├── src/lib/
│ │ ├── schemas.ts
│ │ ├── vincent-ability.ts
│ │ └── helpers/index.ts
│ ├── package.json
│ └── .gitignore
└── policies/
└── my-policy/
├── src/lib/
│ ├── schemas.ts
│ ├── vincent-policy.ts
│ └── helpers/index.ts
├── package.json
└── .gitignore
- Use CLI:
npx @lit-protocol/vincent-scaffold-sdk add ability my-ability - CD into the ability or policy directory
- Update schemas in
src/lib/schemas.ts - Implement logic in
src/lib/vincent-ability.tsorsrc/lib/vincent-policy.ts - Add helpers in
src/lib/helpers/index.tsif needed - Update root
package.jsonbuild script - Build:
npm run vincent:build - Test:
npm run vincent:e2e
// Import built abilities/policies
import { bundledVincentAbility } from "../../vincent-packages/abilities/my-ability/dist/index.js";
import { vincentPolicyMetadata } from "../../vincent-packages/policies/my-policy/dist/index.js";
// Register and test
const result = await chainClient.executeAbilities({
abilities: [myAbilityConfig],
// ... test configuration
});npm run vincent:hardreset # Reset all state and rebuild
npm run vincent:build # Build all abilities and policies
npm run vincent:e2e:reset # Reset E2E test state only
npm run vincent:e2e # Run native transfer E2E tests
npm run vincent:e2e:erc20 # Run ERC-20 transfer E2E tests- Follow existing code patterns exactly
- Use TypeScript strictly
- Implement comprehensive error handling
- Add detailed logging for debugging
- Maintain consistent naming conventions
- Validate all inputs with Zod schemas
- Never expose sensitive data in logs
- Use proper error messages without revealing internals
- Follow principle of least privilege
- Minimize computation in Lit Actions
- Use efficient data structures
- Cache expensive operations when possible
- Keep ability/policy logic focused and minimal
- Using forbidden APIs - Check Lit Actions constraints
- Missing schema validation - Always validate inputs/outputs
- Forgetting build script updates - New abilities won't build
- Incorrect import paths - Use relative paths to dist/
- Mock data usage - Never use fake data in implementations
- Environment variable access - Not available in Lit Actions
- State persistence assumptions - Memory doesn't persist
Always refer to existing working examples:
- Ability example:
vincent-packages/abilities/native-send/ - Policy example:
vincent-packages/policies/send-counter-limit/ - E2E tests:
vincent-e2e/src/e2e.ts - Template files:
src/templates/ability/andsrc/templates/policy/
If implementation details are unclear:
- DO NOT create mock or placeholder data
- DO NOT make assumptions about missing information
- DO ask for specific clarification about requirements
- DO provide concrete examples of what information is needed
- DO suggest proper solutions rather than workarounds
Remember: Vincent development requires precision due to blockchain execution constraints. When in doubt, ask for clarification rather than implementing potentially incorrect solutions.