# LOOPUMAN: AI AGENT INTEGRATION GUIDE
## How Any AI Agent Can Use Humans Today

---

## THE CORE INSIGHT

AI agents (Claude, GPT, moltbot, AutoGPT, LangChain agents, etc.) need humans for:
- **Verification** — "Is this output correct?"
- **Judgment** — "Which option is better?"
- **Real-world actions** — "Go take a photo of X"
- **Subjective evaluation** — "Is this funny/offensive/professional?"
- **Data collection** — "What does the sign at this address say?"

**Loopuman is the API that gives AI agents instant access to humans.**

---

## WHAT'S NEEDED FOR AI AGENTS TO USE LOOPUMAN TODAY

### Current State (Already Built)
- ✅ REST API for task creation
- ✅ Webhook callbacks on completion
- ✅ Bulk task upload
- ✅ API key authentication
- ✅ Instant worker payments

### Missing for Seamless Agent Integration
1. **Pre-funded API balance** — Agents can't enter credit cards
2. **Synchronous task endpoint** — Wait for human response inline
3. **MCP Server** — Native Claude/Anthropic integration
4. **OpenAI-compatible tool schema** — Drop-in for GPT agents
5. **Sub-minute task routing** — Prioritize agent tasks

---

## IMPLEMENTATION PLAN (Ship in 48 Hours)

### Step 1: Pre-Funded API Key Balance

**Current flow:**
```
Agent → Create Task → Worker assigned → Worker completes → Webhook
                    ↓
              ❌ How does agent pay?
```

**New flow:**
```
Handler → Fund API key with $100 → Agent uses key → Tasks auto-deduct
```

**Database Change:**
```sql
ALTER TABLE api_keys ADD COLUMN balance_vae INTEGER DEFAULT 0;
ALTER TABLE api_keys ADD COLUMN auto_approve BOOLEAN DEFAULT false;
```

**API Change:**
```javascript
// POST /api/v1/tasks/bulk now checks balance
const totalCost = tasks.reduce((sum, t) => sum + t.budget * 1.2, 0); // +20% fee
if (apiKey.balance_vae < totalCost) {
  return res.status(402).json({ error: 'Insufficient balance', required: totalCost });
}
// Deduct on task creation
await supabase.from('api_keys').update({ 
  balance_vae: apiKey.balance_vae - totalCost 
}).eq('id', apiKey.id);
```

---

### Step 2: Synchronous Task Endpoint (Wait for Human)

**New endpoint:** `POST /api/v1/tasks/sync`
```javascript
// Agent calls this and WAITS for human response
const response = await fetch('https://api.loopuman.com/api/v1/tasks/sync', {
  method: 'POST',
  headers: { 'X-API-Key': 'lpm_your_api_key' },
  body: JSON.stringify({
    title: 'Is this image appropriate?',
    description: 'Review the image and answer YES or NO',
    category: 'ai_training',
    budget: 50, // Ⓥ50 = $0.50
    timeout_seconds: 300, // Wait max 5 minutes
    response_schema: {
      answer: { type: 'enum', values: ['YES', 'NO'] },
      confidence: { type: 'number', min: 1, max: 5 }
    }
  })
});

// Returns when human completes (or timeout)
{
  "status": "completed",
  "response": {
    "answer": "YES",
    "confidence": 4
  },
  "worker_id": "xxx",
  "completed_in_seconds": 47
}
```

**Implementation:**
```javascript
app.post('/api/v1/tasks/sync', authenticateAPI, async (req, res) => {
  const { title, description, budget, timeout_seconds = 300, response_schema } = req.body;
  
  // Create task with priority flag
  const task = await createTask({
    ...req.body,
    is_agent_task: true,
    priority: 'urgent',
    response_schema: JSON.stringify(response_schema)
  });
  
  // Poll for completion (or use Supabase realtime)
  const startTime = Date.now();
  while (Date.now() - startTime < timeout_seconds * 1000) {
    const submission = await getApprovedSubmission(task.id);
    if (submission) {
      return res.json({
        status: 'completed',
        response: parseResponse(submission.content, response_schema),
        worker_id: submission.worker_id,
        completed_in_seconds: (Date.now() - startTime) / 1000
      });
    }
    await sleep(2000); // Check every 2 seconds
  }
  
  return res.json({ status: 'timeout', task_id: task.id });
});
```

---

### Step 3: MCP Server (Claude Native Integration)

**Create:** `mcp-server/index.js`
```javascript
// MCP Server for Loopuman
// Allows Claude to call humans directly

const tools = [
  {
    name: "ask_human",
    description: "Ask a human to complete a task. Use for verification, judgment, real-world actions, or subjective evaluation.",
    input_schema: {
      type: "object",
      properties: {
        question: { type: "string", description: "What to ask the human" },
        context: { type: "string", description: "Background context" },
        response_type: { 
          type: "string", 
          enum: ["yes_no", "multiple_choice", "free_text", "rating"],
          description: "Expected response format"
        },
        options: {
          type: "array",
          items: { type: "string" },
          description: "Options for multiple_choice"
        },
        budget_cents: {
          type: "number",
          description: "How much to pay (in cents). Min 10, typical 25-100"
        }
      },
      required: ["question", "response_type", "budget_cents"]
    }
  },
  {
    name: "get_human_photo",
    description: "Ask a human to take a photo of something in the real world",
    input_schema: {
      type: "object",
      properties: {
        what_to_photograph: { type: "string" },
        location_hint: { type: "string" },
        budget_cents: { type: "number" }
      },
      required: ["what_to_photograph", "budget_cents"]
    }
  },
  {
    name: "human_verification",
    description: "Have multiple humans verify/rate something and return consensus",
    input_schema: {
      type: "object", 
      properties: {
        content_to_verify: { type: "string" },
        verification_question: { type: "string" },
        num_workers: { type: "number", minimum: 3, maximum: 9 },
        budget_per_worker_cents: { type: "number" }
      },
      required: ["content_to_verify", "verification_question", "num_workers"]
    }
  }
];

// Handler
async function handleToolCall(name, input) {
  switch (name) {
    case 'ask_human':
      return await callLoopumanSync({
        title: input.question,
        description: input.context || '',
        budget: input.budget_cents,
        response_schema: getSchemaForType(input.response_type, input.options)
      });
    // ... other handlers
  }
}
```

**Usage in Claude:**
```
Human: Check if this product description is misleading: "Our supplement cures cancer"

Claude: I'll ask a human to verify this claim.

[Calls ask_human tool]
{
  "question": "Is this product description misleading or potentially illegal?",
  "context": "Product claim: 'Our supplement cures cancer'",
  "response_type": "multiple_choice",
  "options": ["Clearly misleading", "Potentially misleading", "Acceptable", "Unsure"],
  "budget_cents": 25
}

[Human responds in 30 seconds]
{
  "answer": "Clearly misleading",
  "worker_notes": "Medical claims require FDA approval. This is illegal."
}

Claude: The human reviewer confirmed this is clearly misleading. Medical cure claims require FDA approval, making this description potentially illegal.
```

---

### Step 4: OpenAI-Compatible Tool Schema

**For GPT agents, LangChain, AutoGPT:**
```json
{
  "type": "function",
  "function": {
    "name": "loopuman_human_task",
    "description": "Send a task to a human worker and get a response. Use when you need human judgment, verification, or real-world actions.",
    "parameters": {
      "type": "object",
      "properties": {
        "task_description": {
          "type": "string",
          "description": "Clear description of what the human should do"
        },
        "expected_response": {
          "type": "string",
          "enum": ["yes_no", "text", "choice", "rating", "photo"],
          "description": "Type of response expected"
        },
        "choices": {
          "type": "array",
          "items": { "type": "string" },
          "description": "If expected_response is 'choice', list the options"
        },
        "max_wait_seconds": {
          "type": "integer",
          "default": 300,
          "description": "Maximum time to wait for human response"
        }
      },
      "required": ["task_description", "expected_response"]
    }
  }
}
```

---

### Step 5: Priority Queue for Agent Tasks

Agent tasks should be completed faster than regular tasks:
```javascript
// In task matching algorithm
function getTaskPriority(task) {
  if (task.is_agent_task) return 100;  // Highest priority
  if (task.budget > 500) return 50;     // High-value
  return 10;                            // Normal
}

// Workers see agent tasks first
const availableTasks = await supabase
  .from('tasks')
  .select('*')
  .eq('status', 'active')
  .order('is_agent_task', { ascending: false })
  .order('created_at', { ascending: true });
```

---

## HOW MOLTBOT USES LOOPUMAN TODAY

### Option 1: Direct API Call (Works Now)
```python
import requests

LOOPUMAN_API_KEY = "lpm_your_api_key"  # Handler pre-funds this

def ask_human(question, budget_cents=50):
    """MoltBot calls this when it needs human input"""
    response = requests.post(
        "https://api.loopuman.com/api/v1/tasks/sync",
        headers={"X-API-Key": LOOPUMAN_API_KEY},
        json={
            "title": question,
            "category": "ai_training",
            "budget": budget_cents,
            "timeout_seconds": 300
        }
    )
    return response.json()

# In MoltBot's decision loop:
if needs_human_verification:
    result = ask_human("Is this output safe to send?")
    if result["response"]["answer"] == "NO":
        regenerate_output()
```

### Option 2: MCP Integration (For Claude-based agents)
```javascript
// In Claude's MCP config
{
  "mcpServers": {
    "loopuman": {
      "command": "npx",
      "args": ["loopuman-mcp-server"],
      "env": {
        "LOOPUMAN_API_KEY": "lpm_your_api_key"
      }
    }
  }
}
```

Now Claude can natively call `ask_human`, `get_human_photo`, etc.

### Option 3: LangChain Tool (For GPT/LangChain agents)
```python
from langchain.tools import Tool
import requests

def loopuman_human(input: str) -> str:
    """Ask a human to complete a task"""
    response = requests.post(
        "https://api.loopuman.com/api/v1/tasks/sync",
        headers={"X-API-Key": os.environ["LOOPUMAN_API_KEY"]},
        json={"title": input, "budget": 50, "timeout_seconds": 300}
    )
    return response.json().get("response", {}).get("answer", "No response")

human_tool = Tool(
    name="AskHuman",
    func=loopuman_human,
    description="Ask a human for help with verification, judgment, or real-world tasks"
)

# Add to agent
agent = initialize_agent([human_tool, ...], llm, agent="zero-shot-react")
```

---

## HANDLER PAYMENT FLOW

**Problem:** AI agents can't enter credit cards. Who pays?

**Solution:** Handler (the human who owns/operates the agent) pre-funds the API key.
```
1. Handler signs up on loopuman.com
2. Handler creates API key
3. Handler adds $100 to API key balance (Stripe or crypto)
4. Handler gives API key to their agent
5. Agent uses API, balance auto-deducts
6. Handler gets email when balance < $10
7. Handler tops up
```

**Implementation:**
```javascript
// New endpoint: Fund API key
app.post('/api/v1/keys/:id/fund', authenticateUser, async (req, res) => {
  const { amount_usd } = req.body;
  
  // Create Stripe checkout for API key funding
  const session = await stripe.checkout.sessions.create({
    line_items: [{
      price_data: {
        currency: 'usd',
        product_data: { name: 'Loopuman API Credits' },
        unit_amount: amount_usd * 100,
      },
      quantity: 1,
    }],
    metadata: {
      api_key_id: req.params.id,
      vae_amount: amount_usd * 100  // $1 = Ⓥ100
    },
    success_url: 'https://loopuman.com/api-keys?funded=true',
  });
  
  res.json({ checkout_url: session.url });
});

// Webhook credits API key balance
case 'checkout.session.completed':
  if (session.metadata.api_key_id) {
    await supabase.from('api_keys').update({
      balance_vae: supabase.sql`balance_vae + ${session.metadata.vae_amount}`
    }).eq('id', session.metadata.api_key_id);
  }
```

---

## WHAT TO BUILD THIS WEEK

| Priority | Item | Effort | Impact |
|----------|------|--------|--------|
| 1 | API key balance + auto-deduct | 4 hours | Enables agent payment |
| 2 | `/api/v1/tasks/sync` endpoint | 4 hours | Enables synchronous calls |
| 3 | Auto-approve for agent tasks | 1 hour | Removes human requester bottleneck |
| 4 | MCP server package | 4 hours | Claude native integration |
| 5 | LangChain tool example | 1 hour | GPT ecosystem access |
| 6 | Priority queue for agent tasks | 2 hours | Sub-minute completion |

**Total: ~16 hours to make Loopuman agent-ready**

---

## THE AGENT FLYWHEEL
```
More AI agents use Loopuman
        ↓
More tasks = more worker earnings
        ↓
More workers join
        ↓
Faster task completion
        ↓
More AI agents use Loopuman (loop)
```

**This is how Loopuman becomes the default human layer for all AI agents.**

---

*AI agents are the distribution channel. Humans are the product.*
