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 project
mkdir customer-support-agent
cd customer-support-agent
# Initialize Node.js project
npm init -y
# Install dependencies
npm install @human/sdk openai dotenv
# Install dev dependencies
npm install -D typescript @types/node tsx

Create 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_here
OPENAI_API_KEY=your_openai_api_key_here

Step 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 setup
setupAgent().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 2
const AGENT_PASSPORT_ID = 'passport_agent_xxx';
const OPERATOR_PASSPORT_ID = 'passport_operator_xxx';
// Example customer inquiries
const 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.ts

Expected 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

What's Next?