Lead Enrichment
This example enriches sales leads with classification and prioritization, in a single nua.list() call.
Problem
Section titled “Problem”You have a list of sales leads with notes from various sources (forms, meetings, referrals). You need to:
- Classify leads by company size and type
- Assign priority based on purchase intent
- Recommend next steps for each lead
Solution
Section titled “Solution”import { Nua, z } from 'nuabase';import { findLocalAgent } from 'nuabase/local-agent';
const nua = Nua.direct({ localAgent: await findLocalAgent() });
// Define the enrichment schemaconst EnrichmentSchema = z.object({ companySize: z.enum(['solo', 'small', 'medium', 'enterprise']), companyType: z.enum(['startup', 'agency', 'saas', 'ecommerce', 'enterprise', 'other']), priority: z.enum(['low', 'medium', 'high', 'urgent']), purchaseIntent: z.enum(['exploring', 'evaluating', 'ready-to-buy']), recommendedPlan: z.string(), nextStep: z.string(),});
// Sample leads dataconst leads = [ { id: 'lead-001', name: 'Sarah Chen', notes: 'CEO at Acme Corp (500+ employees). Looking for enterprise solution. Budget approved for Q1. Wants demo next week.' }, { id: 'lead-002', name: 'Mike Johnson', notes: 'Freelance developer. Curious about the product. Checking pricing page frequently. No timeline mentioned.' }, { id: 'lead-003', name: 'Lisa Park', notes: 'Head of Engineering at a Series A startup (30 people). Evaluating tools for their engineering team. Decision in 2 weeks.' }, { id: 'lead-004', name: 'Tom Williams', notes: 'Digital agency with 150 employees. Managing 50+ client projects. Current tool is too slow. Urgent need.' }];
// Enrich all leadsasync function enrichLeads() { const result = await nua.list( `You are a sales analyst for a B2B SaaS company.
Analyze each lead and provide:- Company size based on context clues- Type of company/organization- Priority (urgent = ready to buy now, high = strong intent, medium = actively evaluating, low = just browsing)- Purchase intent level- Recommended plan tier- Specific next step for the sales team`, { input: leads, primaryKey: 'id', output: { name: 'enrichment', schema: EnrichmentSchema } } );
if (!result.success) { console.error('Enrichment failed:', result.error); return; }
// Display results console.log('Lead Enrichment Results\n'); console.log('='.repeat(60));
// Rows may come back in any order, so look each one up by its primary key const leadsById = new Map(leads.map(l => [l.id, l]));
for (const row of result.data) { const lead = leadsById.get(row.id)!; const e = row.enrichment;
console.log(`\n${lead.name} (${lead.email})`); console.log(` Company: ${e.companySize} ${e.companyType}`); console.log(` Priority: ${e.priority.toUpperCase()}`); console.log(` Intent: ${e.purchaseIntent}`); console.log(` Recommended: ${e.recommendedPlan}`); console.log(` Next Step: ${e.nextStep}`); }
// Show usage stats console.log('\n' + '='.repeat(60)); console.log(`Tokens used: ${result.usage.totalTokens}`); console.log(`Latency: ${result.latencyMs}ms`); console.log(`Model: ${result.model}`);}
enrichLeads();Output
Section titled “Output”From a run on Claude Code, with the default logger’s [INFO] lines left out. The wording of free-text fields such as the next step varies from run to run:
Lead Enrichment Results
============================================================
Sarah Chen ([email protected]) Company: enterprise enterprise Priority: URGENT Intent: ready-to-buy Recommended: Enterprise Next Step: Schedule a tailored executive demo for next week with Sarah and key stakeholders; prepare an enterprise proposal and pricing aligned to the approved Q1 budget.
Mike Johnson ([email protected]) Company: solo other Priority: LOW Intent: exploring Recommended: Free / Starter Next Step: Enroll in an automated nurture sequence with a free trial or starter plan offer, plus a limited-time discount to convert pricing-page interest.
Lisa Park ([email protected]) Company: small startup Priority: HIGH Intent: evaluating Recommended: Team / Growth Next Step: Book a technical demo with Lisa this week, offer a team trial for the engineering org, and share startup pricing and comparison materials before the 2-week decision deadline.
Tom Williams ([email protected]) Company: medium agency Priority: URGENT Intent: ready-to-buy Recommended: Business / Agency (multi-client) Next Step: Call Tom within 24 hours to show performance and multi-client project management, then offer a quick-start migration plan from the current tool and an agency pricing proposal.
============================================================Tokens used: 3272Latency: 6663msModel: claude-code:claude-opus-5-5Processing Many Leads
Section titled “Processing Many Leads”All rows go into one request. For hundreds of leads, split them into chunks and keep the prompt the same for every chunk, so the provider can reuse its cached copy of the prompt and schema:
const prompt = `You are a sales analyst for a B2B SaaS company. ...`;const output = { name: 'enrichment', schema: EnrichmentSchema };
for (let i = 0; i < allLeads.length; i += 50) { const result = await nua.list(prompt, { input: allLeads.slice(i, i + 50), primaryKey: 'id', output, }); // ...}Variations
Section titled “Variations”Add Scoring
Section titled “Add Scoring”const ScoredLeadSchema = z.object({ score: z.number().min(0).max(100), priority: z.enum(['low', 'medium', 'high', 'urgent']), factors: z.array(z.object({ factor: z.string(), impact: z.enum(['positive', 'negative']), })).max(3),});Industry Classification
Section titled “Industry Classification”const IndustrySchema = z.object({ industry: z.enum([ 'technology', 'healthcare', 'finance', 'retail', 'manufacturing', 'education', 'other' ]), subIndustry: z.string().optional(), relevantProducts: z.array(z.string()).max(3),});Multi-Language Support
Section titled “Multi-Language Support”const result = await nua.list( `Analyze the leads. Respond in English regardless of the input language.`, { input: internationalLeads, primaryKey: 'id', output });