LangChain
Installation
Section titled “Installation”npm install @langchain/core truvalBasic tool definition
Section titled “Basic tool definition”import { tool } from '@langchain/core/tools'import { z } from 'zod'
const verifyEmailTool = tool( async ({ email }) => { const res = await fetch('https://api.truval.dev/v1/email/verify', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TRUVAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ email }), }) return res.json() }, { name: 'verify_email', description: 'Verify if an email address is real and deliverable. Returns valid, confidence score, and whether the address is disposable or a role address.', schema: z.object({ email: z.string().email().describe('The email address to verify'), }), })Creating a resilient onboarding agent
Section titled “Creating a resilient onboarding agent”An agent shouldn’t just fetch the validation status; it should act on it. Here is an example of a LangGraph agent that handles typos, rejects disposable emails, and asks for confirmation on low confidence scores.
import { ChatOpenAI } from '@langchain/openai'import { createReactAgent } from '@langchain/langgraph/prebuilt'
const agent = createReactAgent({ llm: new ChatOpenAI({ model: 'gpt-5.4' }), tools: [verifyEmailTool], stateModifier: `You are an onboarding agent. Your goal is to collect a valid email address. Always verify the email before proceeding. Use status, mx_found, smtp_blocked, not confidence alone. - If suggestion is present, ask "Did you mean [suggestion]?" - If disposable is true, reject and ask for a real email. - If status is invalid or undeliverable, ask for a different email. - If catch_all or status is catch_all, ask the user to confirm. - If status is unknown, mx_found is true, and smtp_blocked is false (often confidence 0.50), ask the user to confirm — not invalid. - If smtp_blocked is true with confidence ~0.75, accept. - If confidence < 0.50 after the above, ask for a different email. - If confidence >= 0.9 (deliverable), accept and proceed.`,})
const result = await agent.invoke({ messages: [{ role: 'user', content: 'My email is test@mailinator.com' }],})
// The agent runs the tool, sees disposable: true, and autonomously// asks the user for a non-throwaway address.Filtering low-confidence results
Section titled “Filtering low-confidence results”const verifyEmailTool = tool( async ({ email, min_confidence = 0.7 }) => { const res = await fetch('https://api.truval.dev/v1/email/verify', { method: 'POST', headers: { Authorization: `Bearer ${process.env.TRUVAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ email }), }) const data = await res.json()
const inconclusive = data.status === 'unknown' && data.mx_found && !data.smtp_blocked const blockedOk = data.smtp_blocked && data.confidence >= 0.7 if ( data.confidence < min_confidence && !inconclusive && !blockedOk && data.status !== 'catch_all' && !data.catch_all ) { return { ...data, recommendation: 'low confidence — consider rejecting' } } return data }, { name: 'verify_email', description: 'Verify email deliverability with confidence scoring.', schema: z.object({ email: z.string().email(), min_confidence: z.number().min(0).max(1).optional() .describe('Minimum confidence threshold (default: 0.7)'), }), })Environment variables
Section titled “Environment variables”TRUVAL_API_KEY=sk_live_...Get your API key at dash.truval.dev.
Public Repositories
Section titled “Public Repositories”- SDK: truval-dev/truval-sdk
- MCP Server: truval-dev/truval-mcp-server
- Agent Skills: truval-dev/truval-skills