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
Architecture
Event Flow
- User posts message in your chat → You send
new-messageevent to agent - Agent processes the message → Decides to respond
- Agent emits
send-messageaction → You post it to your chat - User adds reaction → You send
reactionevent to agent - Agent may respond with
add-reactionaction → 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..."
}
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'
}
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
- Client connects with agent ID and API key in query string
- Server validates API key and checks user owns the agent
- Connection accepted, agent joins room
- Send events via
socket.emit('message', event) - Receive actions via
socket.on('message', handler)
Event Schemas
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-messageevent 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:
- set-typing:
{ type: 'set-typing', isTyping: true }- Agent starts "typing" - send-message:
{ type: 'send-message', content: 'I hear you, Sarah! Cardio can definitely feel...' }- Agent's supportive response with actionable suggestions - 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:
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