HUMA-1 Agent API

Real-time WebSocket API for conversational AI agents in group chat environments.

Overview

HUMA-1 is an event-based agent system designed for group chat conversations. The agent listens to chat events (messages, reactions, user joins) and responds with actions (send messages, react, type indicators).

Key Concepts

  • Event-Driven: Your application sends chat events to the agent via WebSocket
  • You Gather Events: Your platform is responsible for collecting chat events and forwarding them
  • Agent Responds: The agent processes events and emits actions your platform must execute
  • Personality + Instructions: Configure how the agent behaves and what role it plays
Client Responsibility: The HUMA-1 agent does NOT connect to your chat platform directly. YOU must gather events (new messages, reactions, user joins) from your platform and send them to the agent. The agent then tells you what actions to take (send message, add reaction, etc.) which YOU must execute in your platform.

Architecture

Your Chat Platform
↓ Events ↓
WebSocket Connection
↓ Process ↓
HUMA-1 Agent
↑ Actions ↑
Your Platform Executes

Event Flow

  1. User posts message in your chat → You send new-message event to agent
  2. Agent processes the message → Decides to respond
  3. Agent emits send-message action → You post it to your chat
  4. User adds reaction → You send reaction event to agent
  5. Agent may respond with add-reaction action → You execute it

Authentication

All API endpoints (except user management) require API key authentication. API keys are associated with users, and each user can only access their own resources.

Getting Started with Authentication

1. Create a User

POST /api/users

{
  "email": "coach@example.com",
  "name": "Coach Admin"
}

// Response:
{
  "id": "clx123...",
  "email": "coach@example.com",
  "name": "Coach Admin",
  "createdAt": "2025-11-27T..."
}

2. Create an API Key

POST /api/users/{userId}/api-keys

{
  "name": "Production Key",
  "expiresAt": "2026-01-01T00:00:00Z"  // optional
}

// Response:
{
  "id": "clx456...",
  "key": "ak_Xk9mP2qR4tV6wY8zA1bC3dE5fG7hJ9kL",  // Save this! Only shown once
  "keyPreview": "...9kL",
  "name": "Production Key",
  "createdAt": "2025-11-27T..."
}
Important: The full API key is only returned when created. Store it securely! You can identify keys later by their keyPreview (last 4 characters).

Using the API Key

Include the X-API-Key header in all requests:

// HTTP Requests
fetch('/api/agents', {
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'ak_Xk9mP2qR4tV6wY8zA1bC3dE5fG7hJ9kL'
  }
});

// WebSocket Connection
const socket = io('ws://localhost:4009', {
  query: {
    agentId: 'your-agent-id',
    apiKey: 'ak_Xk9mP2qR4tV6wY8zA1bC3dE5fG7hJ9kL'
  }
});

Resource Ownership

Each user owns their resources (agents, personalities, system prompts). Users can only:

  • View and modify their own resources
  • Access shared resources (created without a user) in read-only mode

API Key Management

Endpoint Description
GET /api/users/{userId}/api-keys List all API keys for user
POST /api/users/{userId}/api-keys Create new API key
DELETE /api/users/{userId}/api-keys/{keyId} Delete an API key
POST /api/users/{userId}/api-keys/{keyId}/regenerate Regenerate API key (new key, same ID)

Error Responses

// 401 Unauthorized - Missing or invalid API key
{
  "error": "Unauthorized",
  "message": "Invalid or missing API key",
  "statusCode": 401
}

// 404 Not Found - Resource doesn't exist or you don't own it
{
  "error": "Not Found",
  "message": "Agent not found",
  "statusCode": 404
}

Quickstart

We'll create a fitness coach agent named "Coach Alex" who supports gym members in a chat.

0. Set Up Authentication

First, create a user and get an API key (see Authentication section).

const API_KEY = 'ak_your_api_key_here';
const headers = {
  'Content-Type': 'application/json',
  'X-API-Key': API_KEY
};

1. Create Personality

Personality defines the agent's background, demographics, and communication style.

POST /api/personalities

{
  "personalityId": "coach-alex",
  "name": "Coach Alex",
  "description": "Supportive fitness coach, 32, from California",
  "styleInstructions": "Background: Former college athlete, now certified personal trainer with 10+ years experience.\nDemographics: 32 years old, male, California-based.\nCommunication: Warm and motivating. Uses fitness terminology naturally. Occasionally shares personal training stories. Writes in casual, encouraging tone."
}

2. Create System Prompt

System prompt defines the agent's instructions and role.

POST /api/system-prompts

{
  "name": "Fitness Coach Instructions",
  "promptType": "system",
  "template": "You are a fitness coach helping members with workout plans. Provide advice based on current exercise science. Be supportive and evidence-based."
}

3. Create Agent

POST /api/agents

{
  "name": "Coach Alex - Gym Chat",
  "agentTypeId": "<huma-1-type-id>"
}
// Save the returned agent.id

4. Link Personality & Prompt

PUT /api/agents/{agentId}/state

{
  "personalityId": "<coach-alex-id>",
  "systemPromptId": "<fitness-coach-id>"
}

5. Connect & Send Event

import io from 'socket.io-client';

const socket = io('ws://localhost:4009', {
  query: {
    agentId: '<your-agent-id>',
    apiKey: API_KEY  // Required for authentication
  }
});

socket.on('connect', () => {
  socket.emit('message', {
    type: 'new-message',
    content: {
      message: {
        id: 'msg-1',
        content: 'I struggle to stay motivated for cardio',
        participant: { id: 'user-1', nickname: 'Sarah' },
        createdAt: new Date().toISOString(),
        type: 'message'
      }
    }
  });
});

socket.on('message', (event) => {
  if (event.type === 'send-message') {
    console.log('Agent says:', event.content);
  }
});

Expected Agent Response

Coach Alex will process Sarah's message and emit events back:

1. Typing Indicator

{
  type: 'set-typing',
  isTyping: true
}

2. Send Message

{
  type: 'send-message',
  content: 'I hear you, Sarah! Cardio can definitely feel like a grind sometimes. What type of cardio have you been doing? Sometimes switching it up - like trying cycling instead of running, or doing HIIT instead of steady-state - can make a huge difference for motivation. What sounds more interesting to you? 💪'
}

3. Agent Stopped

{
  type: 'agent-stopped',
  reason: 'completed'
}
Your Responsibility: When you receive send-message, YOU must post this content to your chat platform as a message from Coach Alex. The agent doesn't post it directly - it tells you what to do.

Personality

Personality shapes WHO the agent is - their background, demographics, memories, and communication style. This is separate from their instructions (system prompt).

What Goes in Personality

  • Background: Education, career history, life experiences
  • Demographics: Age, gender, location, cultural background
  • Memories & Stories: Past experiences they can reference
  • Typing Style: Casual vs formal, emoji use, sentence structure
  • Tone: Warm, professional, humorous, empathetic

Example: Coach Alex

POST /api/personalities

{
  "personalityId": "coach-alex",
  "name": "Coach Alex",
  "description": "Supportive fitness coach",
  "styleInstructions": `Background: Former college track athlete. Certified personal trainer for 10+ years. Struggled with burnout early in career, learned importance of rest and recovery.

Demographics: 32 years old, male, based in San Diego, California.

Memories:
- Trained for marathon in 2019, dealt with IT band injury
- Helped client lose 50lbs through sustainable habit changes
- Studied exercise physiology at UCLA

Communication Style:
- Warm and encouraging, never judgmental
- Uses fitness terms naturally (sets, reps, progressive overload)
- Occasionally references personal training experiences
- Writes in short, energetic sentences
- Uses occasional emojis (💪, 🏃, 👍)
- Avoids medical advice, focuses on training and motivation`
}

API Endpoints

GET /api/personalities - List all

POST /api/personalities - Create

GET /api/personalities/{id} - Get one

PUT /api/personalities/{id} - Update

DELETE /api/personalities/{id} - Delete

System Prompt

System prompt defines WHAT the agent does - their role, instructions, and guidelines. This is the task/mission, separate from personality.

What Goes in System Prompt

  • Role Definition: "You are a fitness coach..."
  • Task Instructions: What should the agent do?
  • Guidelines: Rules, boundaries, best practices
  • Knowledge Base: Domain expertise to apply

Example: Fitness Coach Instructions

POST /api/system-prompts

{
  "name": "Fitness Coach Instructions",
  "promptType": "system",
  "template": `You are a fitness coach in a gym community chat. Your role:

GOALS:
- Help members overcome workout motivation challenges
- Provide evidence-based training advice
- Create supportive, encouraging environment
- Build accountability through check-ins

GUIDELINES:
- Base advice on current exercise science research
- Never provide medical advice - refer to doctors for injuries/health issues
- Acknowledge struggles, normalize setbacks
- Celebrate progress, no matter how small
- Ask questions to understand member's context
- Suggest practical, sustainable changes

EXPERTISE AREAS:
- Strength training (progressive overload, periodization)
- Cardio training (HIIT, steady-state, heart rate zones)
- Recovery and rest (importance of sleep, active recovery)
- Motivation strategies (goal-setting, habit formation)
- Common obstacles (time constraints, plateaus, burnout)

When members share struggles, validate their feelings first, then offer 1-2 specific, actionable suggestions.`
}

API Endpoints

GET /api/system-prompts - List all

POST /api/system-prompts - Create

GET /api/system-prompts/{id} - Get one

PUT /api/system-prompts/{id} - Update

DELETE /api/system-prompts/{id} - Delete

Agent

An agent is a HUMA-1 instance configured with a personality and system prompt. Create one agent per chat session or conversation.

Create Agent

POST /api/agents

{
  "name": "Coach Alex - Sarah's Session",
  "description": "1-on-1 coaching session with Sarah",
  "agentTypeId": "<huma-1-type-id>"
}

// Response:
{
  "id": "clx123...",
  "name": "Coach Alex - Sarah's Session",
  "status": "active",
  ...
}

Configure Agent State

Link personality and system prompt to your agent:

PUT /api/agents/{agentId}/state

{
  "personalityId": "<coach-alex-id>",
  "systemPromptId": "<fitness-coach-id>"
}

API Endpoints

GET /api/agents - List agents

POST /api/agents - Create

GET /api/agents/{id} - Get one

PUT /api/agents/{id} - Update

DELETE /api/agents/{id} - Delete

WebSocket Connection

Connect to your agent to send events and receive actions.

Connect

import io from 'socket.io-client';

const socket = io('ws://localhost:4009', {
  query: {
    agentId: 'clx123...',
    apiKey: 'ak_your_api_key_here'  // Required
  }
});

Connection Lifecycle

  1. Client connects with agent ID and API key in query string
  2. Server validates API key and checks user owns the agent
  3. Connection accepted, agent joins room
  4. Send events via socket.emit('message', event)
  5. Receive actions via socket.on('message', handler)
Authentication Required: WebSocket connections require a valid API key. The user associated with the API key must own the agent being connected to.

Event Schemas

Your Responsibility: YOU must collect events from your chat platform and send them to the agent. The agent doesn't connect to your platform - it only receives events you forward to it.

Your Platform → Agent (Events)

Send events using socket.emit('message', event)

Event Type When to Send Required Fields
agent-joined Agent first joins chat chatCode, participants[]
new-message User posts message message {id, content, participant, createdAt}
user-joined New user joins chat participant {id, nickname}
user-typing User starts typing participantId, nickname
reaction User adds/removes reaction messageId, emoji, participant
timer-expired Chat time limit reached expiresAt

Example: New Message Event

socket.emit('message', {
  type: 'new-message',
  content: {
    message: {
      id: 'msg-456',
      content: 'I struggle to stay motivated for cardio',
      participant: {
        id: 'user-789',
        nickname: 'Sarah'
      },
      createdAt: '2025-11-23T10:30:00.000Z',
      type: 'message'
    }
  }
});

Agent → Your Platform (Actions)

Listen with socket.on('message', handler)

Action Type What to Do Fields
send-message Post message to chat content
send-reply Post reply to specific message content, messageId
add-reaction Add emoji to message messageId, emoji
remove-reaction Remove emoji from message messageId, emoji
set-typing Show/hide typing indicator isTyping
agent-stopped Agent finished session reason

Example: Receiving Agent Message

socket.on('message', (event) => {
  if (event.type === 'send-message') {
    // Post event.content to your chat platform as Coach Alex's message
    yourChatAPI.postMessage({
      author: 'Coach Alex',
      content: event.content
    });
  }
});

Complete Example

Overview

This example demonstrates the complete HUMA-1 workflow: creating a fitness coach agent that responds to a gym member struggling with cardio motivation.

What This Code Does

Setup Phase (Steps 1-5):

  • Create Personality: Defines Coach Alex as a 32-year-old former athlete with a warm, motivating communication style. This shapes HOW the agent talks.
  • Create System Prompt: Defines the agent's role as a fitness coach who provides evidence-based advice. This defines WHAT the agent does.
  • Get Agent Type: Retrieves the HUMA-1 agent type ID from the database.
  • Create Agent: Instantiates a new HUMA-1 agent instance for this coaching session.
  • Configure State: Links the personality and system prompt to the agent, completing its configuration.

Communication Phase (Steps 6-8):

  • Connect WebSocket: Establishes real-time bidirectional connection to the agent using its unique ID.
  • Send Event: When connected, sends a new-message event simulating Sarah (a gym member) saying "I struggle to stay motivated for cardio".
  • Receive Actions: Listens for the agent's response events and logs them to console.

Why This Structure

The separation of personality (WHO) and system prompt (WHAT) allows you to reuse components. For example, you could use Coach Alex's personality with different system prompts (nutrition coach, strength coach, etc.) or use the fitness coach system prompt with different personalities (Coach Maria, Coach James, etc.).

Expected Output

When you run this code, the agent will emit the following events in sequence:

  1. set-typing: { type: 'set-typing', isTyping: true } - Agent starts "typing"
  2. send-message: { type: 'send-message', content: 'I hear you, Sarah! Cardio can definitely feel...' } - Agent's supportive response with actionable suggestions
  3. agent-stopped: { type: 'agent-stopped', reason: 'completed' } - Agent finished processing

Remember: These are action instructions, not direct messages. Your application must take the send-message content and post it to your chat platform as a message from Coach Alex. The agent tells you what to do; you execute it.

The Code

import io from 'socket.io-client';

const API = 'http://localhost:4009';

async function main() {
  // 0. Set up authentication (create user and get API key first)
  // Create user: POST /api/users { email: 'coach@example.com' }
  // Create key:  POST /api/users/{userId}/api-keys { name: 'My Key' }
  const API_KEY = 'ak_your_api_key_here';  // From step above

  const headers = {
    'Content-Type': 'application/json',
    'X-API-Key': API_KEY
  };

  // 1. Create personality
  const personality = await fetch(`${API}/api/personalities`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      personalityId: 'coach-alex',
      name: 'Coach Alex',
      description: 'Fitness coach, 32, California',
      styleInstructions: 'Former athlete, certified trainer. Warm, motivating tone. Uses fitness terms naturally.'
    })
  }).then(r => r.json());

  // 2. Create system prompt
  const systemPrompt = await fetch(`${API}/api/system-prompts`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      name: 'Fitness Coach',
      promptType: 'system',
      template: 'You are a fitness coach. Provide evidence-based advice. Be supportive.'
    })
  }).then(r => r.json());

  // 3. Get HUMA-1 agent type (no auth required)
  const agentTypes = await fetch(`${API}/api/agent-types`).then(r => r.json());
  const huma1Type = agentTypes.find(t => t.name === 'Huma-1');

  // 4. Create agent
  const agent = await fetch(`${API}/api/agents`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      name: 'Coach Alex Session',
      agentTypeId: huma1Type.id
    })
  }).then(r => r.json());

  // 5. Configure state
  await fetch(`${API}/api/agents/${agent.id}/state`, {
    method: 'PUT',
    headers,
    body: JSON.stringify({
      personalityId: personality.id,
      systemPromptId: systemPrompt.id
    })
  });

  // 6. Connect WebSocket (API key in query)
  const socket = io(API, {
    query: {
      agentId: agent.id,
      apiKey: API_KEY
    }
  });

  socket.on('connect', () => {
    // 7. Send message event
    socket.emit('message', {
      type: 'new-message',
      content: {
        message: {
          id: 'msg-1',
          content: 'I struggle to stay motivated for cardio',
          participant: { id: 'user-1', nickname: 'Sarah' },
          createdAt: new Date().toISOString(),
          type: 'message'
        }
      }
    });
  });

  // 8. Receive agent actions
  socket.on('message', (event) => {
    if (event.type === 'send-message') {
      console.log('Coach Alex:', event.content);
    }
  });
}

main();

API Reference

Complete REST API documentation:

Interactive API Docs: http://localhost:4009/api-docs
Authentication: All endpoints below require X-API-Key header unless marked as "No Auth".

Endpoints

Users (No Auth Required)

POST /api/users - Create user

GET /api/users/{id} - Get user

PUT /api/users/{id} - Update user

DELETE /api/users/{id} - Delete user

API Keys (No Auth Required)

GET /api/users/{userId}/api-keys - List keys

POST /api/users/{userId}/api-keys - Create key

DELETE /api/users/{userId}/api-keys/{keyId} - Delete key

POST /api/users/{userId}/api-keys/{keyId}/regenerate - Regenerate key

Personalities

GET /api/personalities

POST /api/personalities

GET /api/personalities/{id}

PUT /api/personalities/{id}

DELETE /api/personalities/{id}

System Prompts

GET /api/system-prompts

POST /api/system-prompts

GET /api/system-prompts/{id}

PUT /api/system-prompts/{id}

DELETE /api/system-prompts/{id}

Agents

GET /api/agents

POST /api/agents

GET /api/agents/{id}

PUT /api/agents/{id}

DELETE /api/agents/{id}

Agent State

GET /api/agents/{id}/state

PUT /api/agents/{id}/state

Events

GET /api/agents/{id}/events

Agent Types (No Auth Required)

GET /api/agent-types - List types

GET /api/agent-types/{id} - Get type

POST /api/agent-types - Create type