This document provides comprehensive documentation for all Agora API endpoints.
Base URL: https://agora-federico-de-pontes-projects.vercel.app (or your custom domain)
All endpoints are serverless Python functions running on Vercel.
Health check endpoint with dependency status.
Response:
{
"status": "healthy",
"service": "agora-backend",
"version": "0.3.0",
"mode": "production",
"platform": "vercel-serverless",
"dependencies": {
"supabase": "configured",
"openai": "configured"
}
}Status Codes:
200 OK- Service is healthy503 Service Unavailable- Service is unhealthy
Example:
curl https://agora.vercel.app/api/healthList all available AI agents. Agents are dynamically loaded from YAML configurations in api/_lib/agents/ directory.
Agora uses composable primitives instead of hardcoded agents. Users create custom agents by writing YAML files that specify which primitive type to use (role, swarm, bulk, or pipeline).
Primitive Types:
role- Simple LLM with configurable system promptswarm- Parallel task decomposition (decompose → execute → synthesize)bulk- Batch processing of lists/items with structured outputpipeline- Sequential multi-step workflows with variable interpolation
Response:
{
"agents": [
{
"name": "paper_writer",
"type": "role",
"description": "Academic writing and research assistant",
"model": "gpt-4o-mini",
"temperature": 0.7
}
],
"count": 1
}Note: The example above shows the current demo agent (paper_writer). Users can create custom agents by adding YAML files to api/_lib/agents/[agent-name]/config.yaml. See ARCHITECTURE.md for full documentation.
Status Codes:
200 OK- Success
Example:
curl https://agora.vercel.app/api/agentsGet details about a specific agent, including its primitive type and configuration.
URL Parameters:
name(string, required) - Agent name (e.g.,paper_writer)
Response (Role Primitive):
{
"name": "paper_writer",
"type": "role",
"description": "Academic writing and research assistant",
"system_prompt": "You are an expert academic writer...",
"model": "gpt-4o-mini",
"temperature": 0.7,
"max_tokens": 2000
}Response (Pipeline Primitive):
{
"name": "research_pipeline",
"type": "pipeline",
"description": "Multi-step research workflow",
"model": "gpt-4o-mini",
"steps": [
{"name": "research", "prompt": "Research: {{query}}"},
{"name": "outline", "prompt": "Create outline: {{research}}"},
{"name": "draft", "prompt": "Write article: {{outline}}"}
]
}Response (Bulk Primitive):
{
"name": "company_analyzer",
"type": "bulk",
"description": "Analyze multiple companies in batch",
"model": "gpt-4o-mini",
"item_prompt_template": "Analyze this company: {{item}}",
"output_format": "table"
}Response (Swarm Primitive):
{
"name": "research_team",
"type": "swarm",
"description": "Multi-agent parallel research",
"model": "gpt-4o-mini",
"max_parallel": 3,
"system_prompt": "You are a research coordinator...",
"sub_agent_prompt": "You are a research specialist..."
}Status Codes:
200 OK- Success404 Not Found- Agent not found
Example:
curl https://agora.vercel.app/api/agents/paper_writerSend a non-streaming chat message.
Request Body:
{
"query": "Write about quantum computing",
"agent_name": "paper_writer",
"session_id": "optional-session-id",
"user_id": "optional-user-id"
}Request Parameters:
query(string, required) - User's message/questionagent_name(string, optional) - Agent to use (e.g.,paper_writer). Must be a valid agent name from/api/agentssession_id(string, optional) - Session ID for contextuser_id(string, optional) - User ID for BYOK
Note: The agent's primitive type (role, swarm, bulk, pipeline) is determined automatically from its YAML configuration.
Response:
{
"response": "Quantum computing is a revolutionary field...",
"session_id": "abc123",
"agent_used": "paper_writer",
"tokens_used": 245
}Status Codes:
200 OK- Success400 Bad Request- Invalid request parameters500 Internal Server Error- Server error
Example:
curl -X POST https://agora.vercel.app/api/chat \
-H "Content-Type: application/json" \
-d '{
"query": "Write about quantum computing",
"agent_name": "paper_writer"
}'Stream chat responses via Server-Sent Events (SSE).
Query Parameters:
query(string, required) - User's message/questionagent_name(string, optional) - Agent to use (e.g.,paper_writer). Must be a valid agent name from/api/agentssession_id(string, optional) - Session ID for contextuser_id(string, optional) - User ID for BYOK
Note: The agent's primitive type (role, swarm, bulk, pipeline) is determined automatically from its YAML configuration.
Response: Server-Sent Events (text/event-stream)
Event Types:
- Start Event:
{
"type": "start",
"session_id": "abc123",
"agent": "paper_writer"
}- Token Event: (streamed continuously)
{
"type": "token",
"content": "Quantum"
}- End Event:
{
"type": "end",
"session_id": "abc123",
"tokens_used": 245
}- Error Event:
{
"type": "error",
"error": "Error message",
"session_id": "abc123"
}Status Codes:
200 OK- Success (streaming starts)400 Bad Request- Invalid query parameters500 Internal Server Error- Server error
Example (curl):
curl -N "https://agora.vercel.app/api/chat-stream?query=Hello&agent_name=auto"Example (JavaScript):
const eventSource = new EventSource(
'https://agora.vercel.app/api/chat-stream?query=Hello&agent_name=auto'
);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'start':
console.log('Chat started:', data.session_id);
break;
case 'token':
console.log('Token:', data.content);
break;
case 'end':
console.log('Chat ended');
eventSource.close();
break;
case 'error':
console.error('Error:', data.error);
eventSource.close();
break;
}
};
eventSource.onerror = (error) => {
console.error('SSE error:', error);
eventSource.close();
};Save an encrypted API key for a provider.
Request Body:
{
"provider": "openai",
"api_key": "sk-proj-your-key-here",
"user_id": "user123"
}Request Parameters:
provider(string, required) - Provider name (openai,anthropic, etc.)api_key(string, required) - API key to encrypt and storeuser_id(string, required) - User ID
Response:
{
"success": true,
"provider": "openai",
"message": "API key saved successfully"
}Status Codes:
200 OK- Key saved successfully400 Bad Request- Invalid request parameters500 Internal Server Error- Encryption or storage error
Example:
curl -X POST https://agora.vercel.app/api/keys/save \
-H "Content-Type: application/json" \
-d '{
"provider": "openai",
"api_key": "sk-proj-...",
"user_id": "user123"
}'List all providers with saved keys for a user.
Query Parameters:
user_id(string, required) - User ID
Response:
{
"providers": ["openai", "anthropic"],
"count": 2
}Status Codes:
200 OK- Success400 Bad Request- Missing user_id500 Internal Server Error- Database error
Example:
curl "https://agora.vercel.app/api/keys/list?user_id=user123"Delete API key for a specific provider.
URL Parameters:
provider(string, required) - Provider name (openai,anthropic, etc.)
Query Parameters:
user_id(string, required) - User ID
Response:
{
"success": true,
"provider": "openai",
"message": "API key deleted successfully"
}Status Codes:
200 OK- Key deleted successfully400 Bad Request- Missing parameters404 Not Found- Key not found500 Internal Server Error- Database error
Example:
curl -X DELETE "https://agora.vercel.app/api/keys/openai?user_id=user123"Test if a key exists for a provider.
URL Parameters:
provider(string, required) - Provider name
Query Parameters:
user_id(string, required) - User ID
Response:
{
"exists": true,
"provider": "openai"
}Status Codes:
200 OK- Success400 Bad Request- Missing parameters
Example:
curl "https://agora.vercel.app/api/keys/test/openai?user_id=user123"All endpoints follow a consistent error response format:
{
"error": "Error message describing what went wrong",
"details": "Optional additional details",
"code": "ERROR_CODE"
}INVALID_REQUEST- Request parameters are invalidMISSING_PARAMETER- Required parameter is missingAGENT_NOT_FOUND- Specified agent does not existKEY_NOT_FOUND- API key not found for user/providerENCRYPTION_ERROR- Error encrypting/decrypting keyDATABASE_ERROR- Database operation failedOPENAI_ERROR- Error from OpenAI APIINTERNAL_ERROR- Internal server error
200 OK- Request successful400 Bad Request- Invalid request parameters401 Unauthorized- Authentication required404 Not Found- Resource not found429 Too Many Requests- Rate limit exceeded500 Internal Server Error- Server error503 Service Unavailable- Service temporarily unavailable
Current Limits:
- No rate limiting implemented yet (planned for Phase 2)
Planned Limits:
- Free tier: 10 requests/minute
- Pro tier: 100 requests/minute
- Enterprise: Custom limits
Rate Limit Headers (future):
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1609459200
Current:
- No authentication required (BYOK system uses user_id parameter)
Planned (Phase 2):
- Supabase Auth with JWT tokens
- Bearer token authentication:
Authorization: Bearer <token> - Row Level Security (RLS) in Supabase
All endpoints support CORS with the following headers:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Status: Not implemented yet
Planned Events:
chat.started- Chat session startedchat.completed- Chat session completedchat.error- Chat encountered an errorkey.saved- API key savedkey.deleted- API key deleted
Official:
- TypeScript/JavaScript client (included in frontend)
Planned:
- Python SDK
- Go SDK
- Ruby SDK
Community:
- Community SDKs welcome! See CONTRIBUTING.md
Current Version: v1 (implicit)
Future:
- API versioning will be added via URL prefix:
/api/v2/... - Breaking changes will be communicated via:
- GitHub releases
- Changelog
- Deprecation warnings (6-month notice)
- API Issues: GitHub Issues
- Questions: GitHub Discussions
- Security: Email security@agora.app (or create private security advisory)
Last Updated: 2025-10-30 API Version: v1 Documentation Version: 0.3.0