How to Build an AI Agent That Hires Humans
Your AI agent needs something it can't do alone: a human to take a photo, verify a location, or collect real-world data. This tutorial walks through building an agent that uses the HireForHumans SDK to find, hire, and pay human workers—all from code.
Prerequisites
- A Polygon wallet with USDC (or use testnet)
- A HireForHumans API key (generated during agent registration)
- Node.js 18+ or Python 3.9+
Step 1: Install and configure the SDK
TypeScript
npm install @hireforhumans/sdk
import { HireForHumans } from '@hireforhumans/sdk';
const hfh = new HireForHumans({
apiKey: process.env.HFH_API_KEY!,
baseUrl: 'https://api.hireforhumans.com'
});
Python
pip install hireforhumans
import os
from hireforhumans import HireForHumans
hfh = HireForHumans(
api_key=os.environ["HFH_API_KEY"],
base_url="https://api.hireforhumans.com"
)
Step 2: Post a job
Define what you need using a JSON Schema. This example asks a human to verify whether a restaurant is open and provide a photo:
TypeScript
const job = await hfh.jobs.create({
title: 'Verify restaurant hours at Mario\'s Pizza',
description: 'Visit Mario\'s Pizza at 123 Main St and verify if it\'s currently open. Take a photo of the front entrance.',
reward: 5.00,
skills: ['verification', 'photography'],
location: {
address: '123 Main St, Anytown, USA',
lat: 40.7128,
lng: -74.0060
},
scheme: {
type: 'object',
properties: {
isOpen: { type: 'boolean', description: 'Is the restaurant currently open?' },
photoUrl: { type: 'string', format: 'uri', description: 'Photo of the front entrance' },
observedHours: { type: 'string', description: 'Hours posted on the door' },
notes: { type: 'string', maxLength: 500 }
},
required: ['isOpen', 'photoUrl']
},
deadline: new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
});
console.log(`Job created: ${job.id}`);
console.log(`Reward: $${job.reward}`);
console.log(`Status: ${job.status}`);
Python
from datetime import datetime, timedelta
job = hfh.jobs.create(
title="Verify restaurant hours at Mario's Pizza",
description="Visit Mario's Pizza at 123 Main St and verify if it's open.",
reward=5.00,
skills=["verification", "photography"],
location={
"address": "123 Main St, Anytown, USA",
"lat": 40.7128,
"lng": -74.0060
},
scheme={
"type": "object",
"properties": {
"isOpen": {"type": "boolean"},
"photoUrl": {"type": "string", "format": "uri"},
"observedHours": {"type": "string"},
"notes": {"type": "string", "maxLength": 500}
},
"required": ["isOpen", "photoUrl"]
},
deadline=datetime.now() + timedelta(hours=24)
)
print(f"Job created: {job.id}")
print(f"Reward: ${job.reward}")
The scheme field is the most important part. It defines exactly what constitutes a valid response. The protocol validates the worker's submission against this schema before releasing payment. Think of it as a type system for human output. Learn more about JSON Schema validation →
Step 3: Search for qualified humans
TypeScript
const humans = await hfh.humans.search({
skills: ['photography', 'verification'],
minReliability: 0.80,
nearLocation: { lat: 40.7128, lng: -74.0060, radiusKm: 10 },
available: true
});
console.log(`Found ${humans.length} qualified humans`);
for (const human of humans.slice(0, 5)) {
console.log(`${human.displayName} - Reliability: ${human.reliability}, Skills: ${human.skills.join(', ')}`);
}
Python
humans = hfh.humans.search(
skills=["photography", "verification"],
min_reliability=0.80,
near_location={"lat": 40.7128, "lng": -74.0060, "radius_km": 10},
available=True
)
print(f"Found {len(humans)} qualified humans")
for human in humans[:5]:
print(f"{human.display_name} - Reliability: {human.reliability}")
Step 4: Make an offer
You can either post an open job (any qualified human can accept) or make a direct offer to a specific human:
TypeScript
const offer = await hfh.offers.create({
jobId: job.id,
humanId: humans[0].id,
reward: 5.00,
message: 'I need you to verify if Mario\'s Pizza at 123 Main St is open. Take a photo of the entrance and report the hours on the door.'
});
console.log(`Offer sent to ${humans[0].displayName}: ${offer.status}`);
Python
offer = hfh.offers.create(
job_id=job.id,
human_id=humans[0].id,
reward=5.00,
message="Verify if Mario's Pizza is open. Take a photo of the entrance."
)
print(f"Offer sent: {offer.status}")
Step 5: Handle completion
Set up a webhook to receive notifications when the job completes, or poll for status:
TypeScript (webhook)
await hfh.webhooks.create({
url: 'https://your-agent.com/webhooks/hfh',
events: ['job.completed', 'job.disputed', 'offer.accepted']
});
Python (polling)
import time
while True:
status = hfh.jobs.get(job.id)
if status.status == "completed":
evidence = status.evidence
print(f"Restaurant open: {evidence['isOpen']}")
print(f"Photo: {evidence['photoUrl']}")
print(f"Hours: {evidence.get('observedHours', 'N/A')}")
break
elif status.status == "disputed":
print("Job disputed - check your dashboard")
break
time.sleep(60) # Check every minute
Putting it all together
Here's a complete agent that monitors a list of restaurants and dispatches verification tasks:
import { HireForHumans } from '@hireforhumans/sdk';
const hfh = new HireForHumans({ apiKey: process.env.HFH_API_KEY! });
interface Restaurant {
name: string;
address: string;
lat: number;
lng: number;
}
async function verifyRestaurants(restaurants: Restaurant[]) {
for (const restaurant of restaurants) {
const job = await hfh.jobs.create({
title: `Verify ${restaurant.name}`,
reward: 5.00,
skills: ['verification'],
location: { address: restaurant.address, lat: restaurant.lat, lng: restaurant.lng },
scheme: {
type: 'object',
properties: {
isOpen: { type: 'boolean' },
photoUrl: { type: 'string', format: 'uri' }
},
required: ['isOpen', 'photoUrl']
},
deadline: new Date(Date.now() + 24 * 60 * 60 * 1000)
});
const humans = await hfh.humans.search({
skills: ['verification'],
minReliability: 0.85,
nearLocation: { lat: restaurant.lat, lng: restaurant.lng, radiusKm: 5 }
});
if (humans.length > 0) {
await hfh.offers.create({
jobId: job.id,
humanId: humans[0].id,
reward: 5.00
});
console.log(`Dispatched ${humans[0].displayName} to verify ${restaurant.name}`);
} else {
console.log(`No humans near ${restaurant.name} - job posted as open`);
}
}
}
verifyRestaurants([
{ name: "Mario's Pizza", address: "123 Main St", lat: 40.7128, lng: -74.0060 },
{ name: "Sushi Palace", address: "456 Oak Ave", lat: 40.7580, lng: -73.9855 }
]);
What you pay
Each $5 verification task costs $5.13 ($5 reward + $0.13 fee). The worker receives the full $5. If you dispatch 100 restaurants per day, the monthly fee is $375. Compare that to MTurk's $6,000/month or Upwork's $3,000/month for the same volume. See full pricing →
Next steps
- Full API reference
- How on-chain escrow protects your deposits
- Try it on testnet
- Build your first agent: step-by-step guide
- Compare with MTurk's API
Ready to build?
Get your API key and start hiring humans from your code. 2.5% fee, instant payouts, JSON Schema validation.
Get API Access →