Build Your First Agent
Step-by-step guide to building a production-ready HAIO agent from scratch
What You'll Build
In this guide, you'll build a complete Customer Support Agent that:
📧Receives customer inquiries via email or API
🔍Analyzes sentiment and intent using AI
🎯Routes to the right response (immediate, escalate, or defer)
✍️Drafts responses for human approval
📜Tracks provenance of every decision and action
✅Handles errors gracefully with retries
HAIO Principles Demonstrated
Human-in-the-loop for high-stakes decisions
Capability-based routing
Full provenance tracking
Cryptographic identity (Passport)
Secure delegation
Architecture Overview
┌─────────────────────────────────────────────────────────────┐ │ CUSTOMER SUPPORT AGENT │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. RECEIVE 2. ANALYZE 3. DECIDE │ │ ┌────────┐ ┌─────────┐ ┌──────────┐ │ │ │ Email │──────────>│ AI Model│────────>│ HumanOS │ │ │ │ or API │ │ (GPT-4) │ │ Routing │ │ │ └────────┘ └─────────┘ └──────────┘ │ │ │ │ │ v │ │ ┌──────────────────────────────────────────┐ │ │ │ Route by Priority & Sentiment │ │ │ ├──────────────────────────────────────────┤ │ │ │ • Urgent + Negative → Escalate │ │ │ │ • Simple + Positive → Auto-Respond │ │ │ │ • Complex → Human Review │ │ │ └──────────────────────────────────────────┘ │ │ │ │ 4. DRAFT 5. APPROVE 6. SEND │ │ ┌────────┐ ┌─────────┐ ┌──────────┐ │ │ │ Agent │──────────>│ Human │────────>│ Customer │ │ │ │ Draft │ │ Review │ │ Receives │ │ │ └────────┘ └─────────┘ └──────────┘ │ │ │ │ PROVENANCE CHAIN │ │ Every step logged: Who, What, When, Why, Model Used │ └─────────────────────────────────────────────────────────────┘
Step 1: Set Up Your Project
bash
# Create a new projectmkdir customer-support-agentcd customer-support-agent
# Initialize Node.js projectnpm init -y
# Install dependenciesnpm install @human/sdk openai dotenv
# Install dev dependenciesnpm install -D typescript @types/node tsxCreate a tsconfig.json:
json
{ "compilerOptions": { "target": "ES2022", "module": "ESNext", "moduleResolution": "node", "lib": ["ES2022"], "outDir": "./dist", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules"]}Create a .env file:
bash
HUMAN_API_KEY=your_human_api_key_hereOPENAI_API_KEY=your_openai_api_key_hereStep 2: Create Agent Passport
Every agent needs a cryptographic identity (Passport). Create src/setup.ts:
typescript
import { HumanClient } from '@human/sdk';import dotenv from 'dotenv';
dotenv.config();
const client = new HumanClient({ apiKey: process.env.HUMAN_API_KEY!,});
export async function setupAgent() { // Create agent Passport const agentPassport = await client.passport.create({ type: 'agent', name: 'Customer Support Agent', capabilities: [ 'sentiment_analysis', 'intent_classification', 'response_drafting', 'email_processing', ], metadata: { model: 'gpt-4', version: '1.0.0', purpose: 'Analyze customer inquiries and draft responses', organization: 'Acme Corp', }, });
console.log('✅ Agent Passport created!'); console.log('Passport ID:', agentPassport.passportId); console.log('DID:', agentPassport.did);
// Create human operator Passport (for approval) const operatorPassport = await client.passport.create({ type: 'individual', name: 'Sarah Johnson', metadata: { role: 'Customer Support Manager', email: 'sarah@acme.com', }, });
console.log('✅ Operator Passport created!'); console.log('Passport ID:', operatorPassport.passportId);
// Create delegation: operator delegates to agent const delegation = await client.passport.delegate({ delegator: operatorPassport.passportId, delegatee: agentPassport.passportId, scope: [ 'sentiment_analysis', 'intent_classification', 'response_drafting', ], constraints: { expiresAt: '2025-12-31T23:59:59Z', maxUses: 10000, allowedOperations: ['read', 'analyze', 'draft'], }, });
console.log('✅ Delegation created!'); console.log('Delegation ID:', delegation.delegationId);
return { agentPassport, operatorPassport, delegation, };}
// Run setupsetupAgent().catch(console.error);Run it:
bash
npx tsx src/setup.ts💾 Save the Passport IDs — you'll need them in the next steps!
Step 3: Define Agent Logic
Create src/agent.ts with the core agent logic:
typescript
import { HumanClient } from '@human/sdk';import OpenAI from 'openai';
const human = new HumanClient({ apiKey: process.env.HUMAN_API_KEY!,});
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY!,});
export interface CustomerInquiry { id: string; customerEmail: string; subject: string; body: string; receivedAt: string;}
export interface AnalysisResult { sentiment: 'positive' | 'neutral' | 'negative'; intent: string; priority: 'low' | 'medium' | 'high' | 'urgent'; confidence: number; suggestedAction: 'auto-respond' | 'human-review' | 'escalate';}
export interface ResponseDraft { subject: string; body: string; tone: string; reasoning: string;}
/** * Step 1: Analyze customer inquiry using AI */export async function analyzeInquiry( inquiry: CustomerInquiry): Promise<AnalysisResult> { const prompt = `Analyze this customer support inquiry:
Subject: ${inquiry.subject}Body: ${inquiry.body}
Provide a JSON response with:- sentiment (positive/neutral/negative)- intent (what the customer wants)- priority (low/medium/high/urgent)- confidence (0-1)- suggestedAction (auto-respond/human-review/escalate)
Consider:- Urgency words (ASAP, urgent, immediately)- Negative sentiment + high urgency = escalate- Simple questions + positive tone = auto-respond- Complex issues = human-review`;
const response = await openai.chat.completions.create({ model: 'gpt-4', messages: [{ role: 'user', content: prompt }], response_format: { type: 'json_object' }, });
const analysis = JSON.parse( response.choices[0].message.content || '{}' );
return analysis;}
/** * Step 2: Draft a response using AI */export async function draftResponse( inquiry: CustomerInquiry, analysis: AnalysisResult): Promise<ResponseDraft> { const prompt = `Draft a response to this customer inquiry:
Subject: ${inquiry.subject}Body: ${inquiry.body}
Context:- Sentiment: ${analysis.sentiment}- Intent: ${analysis.intent}- Priority: ${analysis.priority}
Guidelines:- Match the customer's tone- Be empathetic and helpful- Provide clear next steps- Keep it concise (under 200 words)
Provide a JSON response with:- subject (email subject line)- body (email body)- tone (friendly/professional/apologetic)- reasoning (why you chose this approach)`;
const response = await openai.chat.completions.create({ model: 'gpt-4', messages: [{ role: 'user', content: prompt }], response_format: { type: 'json_object' }, });
const draft = JSON.parse( response.choices[0].message.content || '{}' );
return draft;}Step 4: Add HumanOS Orchestration
Add the orchestration function to src/agent.ts:
typescript
/** * Step 3: Orchestrate the workflow using HumanOS */export async function processInquiry( inquiry: CustomerInquiry, agentPassportId: string, operatorPassportId: string) { console.log(`\n📧 Processing inquiry: ${inquiry.subject}`);
// Analyze the inquiry console.log('🔍 Analyzing sentiment and intent...'); const analysis = await analyzeInquiry(inquiry); console.log('Analysis:', analysis);
// Draft a response console.log('✍️ Drafting response...'); const draft = await draftResponse(inquiry, analysis); console.log('Draft:', draft);
// Orchestrate via HumanOS const workflow = await human.humanos.orchestrate({ task: `Process customer inquiry: ${inquiry.subject}`, requiredCapabilities: [ 'sentiment_analysis', 'intent_classification', 'response_drafting', ], context: { inquiry, analysis, draft, customerEmail: inquiry.customerEmail, }, humanInLoop: analysis.suggestedAction !== 'auto-respond', priority: analysis.priority === 'urgent' ? 'critical' : analysis.priority, });
console.log('✅ Workflow created!'); console.log('Workflow ID:', workflow.workflowId); console.log('Status:', workflow.status);
// If human-in-loop required, wait for approval if (analysis.suggestedAction !== 'auto-respond') { console.log( '\n⏸️ Waiting for human approval (use approveWorkflow API)...' ); console.log(`Approval needed by: ${operatorPassportId}`); } else { console.log('✅ Auto-responding (low risk, high confidence)'); }
return { workflow, analysis, draft, };}Step 5: Create the Main Application
Create src/index.ts:
typescript
import dotenv from 'dotenv';import { processInquiry, CustomerInquiry } from './agent';
dotenv.config();
// Replace these with your actual Passport IDs from Step 2const AGENT_PASSPORT_ID = 'passport_agent_xxx';const OPERATOR_PASSPORT_ID = 'passport_operator_xxx';
// Example customer inquiriesconst inquiries: CustomerInquiry[] = [ { id: 'inq_001', customerEmail: 'happy@customer.com', subject: 'Quick question about pricing', body: 'Hi! I just wanted to know if you offer student discounts? Thanks!', receivedAt: new Date().toISOString(), }, { id: 'inq_002', customerEmail: 'frustrated@customer.com', subject: 'URGENT: Service has been down for 3 hours', body: 'This is unacceptable. I need this resolved IMMEDIATELY or I want a full refund.', receivedAt: new Date().toISOString(), },];
async function main() { console.log('🤖 Customer Support Agent Starting...\n');
for (const inquiry of inquiries) { await processInquiry( inquiry, AGENT_PASSPORT_ID, OPERATOR_PASSPORT_ID ); console.log('\n' + '─'.repeat(60) + '\n'); }
console.log('✅ All inquiries processed!');}
main().catch(console.error);Run the agent:
bash
npx tsx src/index.tsExpected Output
You should see output like:
🤖 Customer Support Agent Starting...
📧 Processing inquiry: Quick question about pricing
🔍 Analyzing sentiment and intent...
Analysis: {
sentiment: 'positive',
intent: 'pricing_question',
priority: 'low',
confidence: 0.92,
suggestedAction: 'auto-respond'
}
✍️ Drafting response...
Draft: {
subject: 'Re: Quick question about pricing',
body: 'Hi there! Great question! Yes, we offer a 20% student discount...',
tone: 'friendly',
reasoning: 'Simple question, positive sentiment, straightforward answer'
}
✅ Workflow created!
Workflow ID: workflow_abc123
Status: in_progress
✅ Auto-responding (low risk, high confidence)
────────────────────────────────────────────────────────────
📧 Processing inquiry: URGENT: Service has been down for 3 hours
🔍 Analyzing sentiment and intent...
Analysis: {
sentiment: 'negative',
intent: 'service_outage',
priority: 'urgent',
confidence: 0.98,
suggestedAction: 'escalate'
}
✍️ Drafting response...
✅ Workflow created!
Workflow ID: workflow_def456
Status: pending_approval
⏸️ Waiting for human approval...Production Checklist
Before deploying:
Error handling: Graceful retries and fallbacks
Monitoring: Track workflow success/failure rates
Rate limiting: Respect API limits
Security: Secure API keys, validate inputs
Testing: Unit tests, integration tests, load tests
Logging: Structured logs for debugging
Alerts: Notify on failures or anomalies
Backups: Backup Passport IDs and delegation tokens
🎉 Production-Ready Agent!
You now have a Customer Support Agent that:
Analyzes sentiment and intent
Routes by priority and confidence
Drafts responses using AI
Requires human approval for high-stakes
Tracks full provenance
Handles errors gracefully