24 KiB
Evo AI - AI Agents Platform
Evo AI is an open-source platform for creating and managing AI agents, enabling integration with different AI models and services.
🚀 Overview
The Evo AI platform allows:
- Creation and management of AI agents
- Integration with different language models
- Client and contact management
- MCP server configuration
- Custom tools management
- JWT authentication with email verification
🛠️ Technologies
- FastAPI: Web framework for building the API
- SQLAlchemy: ORM for database interaction
- PostgreSQL: Main database
- Alembic: Migration system
- Pydantic: Data validation and serialization
- Uvicorn: ASGI server
- Redis: Cache and session management
- JWT: Secure token authentication
- SendGrid: Email service for verification
📁 Project Structure
src/
├── api/ # API endpoints
├── core/ # Core business logic
├── models/ # Data models
├── schemas/ # Pydantic schemas for validation
├── utils/ # Utilities
├── config/ # Configurations
└── services/ # Business services
📋 Requirements
- Python 3.8+
- PostgreSQL
- Redis
- OpenAI API Key (or other AI provider)
- SendGrid Account (for email sending)
🔧 Installation
- Clone the repository:
git clone https://github.com/your-username/evo-ai.git
cd evo-ai
- Create a virtual environment:
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# or
.venv\Scripts\activate # Windows
- Install dependencies:
pip install -r requirements.txt
- Set up environment variables:
cp .env.example .env
# Edit the .env file with your settings
- Run migrations:
make upgrade
🔐 Authentication
The API uses JWT (JSON Web Token) authentication. To access the endpoints, you need to:
- Register a user or log in to obtain a JWT token
- Include the JWT token in the
Authorization
header of all requests in the formatBearer <token>
- Tokens expire after a configured period (default: 30 minutes)
Authentication Flow
- User Registration:
POST /api/v1/auth/register
-
Email Verification: An email will be sent containing a verification link.
-
Login:
POST /api/v1/auth/login
Returns a JWT token to be used in requests.
- Password Recovery (if needed):
POST /api/v1/auth/forgot-password
POST /api/v1/auth/reset-password
Example Usage with curl:
# Login
curl -X POST "http://localhost:8000/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"email": "your-email@example.com", "password": "your-password"}'
# Use received token
curl -X GET "http://localhost:8000/api/v1/clients/" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
Access Control
- Regular users (associated with a client) only have access to their client's resources
- Admin users have access to all resources
- Certain operations (such as creating MCP servers) are restricted to administrators only
🚀 Running the Project
make run
The API will be available at http://localhost:8000
📚 API Documentation
Authentication
Register User
POST /api/v1/auth/register
Request Body:
{
"email": "user@example.com",
"password": "securePassword123",
"name": "Company Name"
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "user@example.com",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"is_active": false,
"email_verified": false,
"is_admin": false,
"created_at": "2023-07-10T15:00:00.000Z"
}
Registers a new user and sends a verification email. The user will remain inactive until the email is verified.
Login
POST /api/v1/auth/login
Request Body:
{
"email": "user@example.com",
"password": "securePassword123"
}
Response (200 OK):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}
Authenticates the user and returns a valid JWT token for use in subsequent requests.
Verify Email
GET /api/v1/auth/verify-email/{token}
Response (200 OK):
{
"message": "Email successfully verified. Your account is now active."
}
Verifies the user's email using the token sent by email. Activates the user's account.
Resend Verification
POST /api/v1/auth/resend-verification
Request Body:
{
"email": "user@example.com"
}
Response (200 OK):
{
"message": "Verification email resent. Please check your inbox."
}
Resends the verification email for users with unverified email.
Forgot Password
POST /api/v1/auth/forgot-password
Request Body:
{
"email": "user@example.com"
}
Response (200 OK):
{
"message": "If the email exists in our database, a password reset link will be sent."
}
Sends an email with password recovery instructions if the email is registered.
Reset Password
POST /api/v1/auth/reset-password
Request Body:
{
"token": "password-reset-token-received-by-email",
"new_password": "newSecurePassword456"
}
Response (200 OK):
{
"message": "Password successfully reset."
}
Resets the user's password using the token received by email.
Clients
Create Client
POST /api/v1/clients/
Request Body:
{
"name": "Company Name"
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Company Name",
"created_at": "2023-07-10T15:00:00.000Z"
}
Creates a new client. Requires administrator permissions.
List Clients
GET /api/v1/clients/
Query Parameters:
skip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Company Name",
"created_at": "2023-07-10T15:00:00.000Z"
}
]
Lists all clients with pagination. For administrator users, returns all clients. For regular users, returns only the client they are associated with.
Get Client
GET /api/v1/clients/{client_id}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Company Name",
"created_at": "2023-07-10T15:00:00.000Z"
}
Gets a specific client. The user must have permission to access this client.
Update Client
PUT /api/v1/clients/{client_id}
Request Body:
{
"name": "New Company Name"
}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "New Company Name",
"created_at": "2023-07-10T15:00:00.000Z"
}
Updates client data. The user must have permission to access this client.
Delete Client
DELETE /api/v1/clients/{client_id}
Response (204 No Content)
Deletes a client. Requires administrator permissions.
Contacts
Create Contact
POST /api/v1/contacts/
Request Body:
{
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"ext_id": "optional-external-id",
"name": "Contact Name",
"meta": {
"phone": "+15551234567",
"category": "customer",
"notes": "Additional information"
}
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"ext_id": "optional-external-id",
"name": "Contact Name",
"meta": {
"phone": "+15551234567",
"category": "customer",
"notes": "Additional information"
}
}
Creates a new contact. The user must have permission to access the specified client.
List Contacts
GET /api/v1/contacts/{client_id}
Query Parameters:
skip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"ext_id": "optional-external-id",
"name": "Contact Name",
"meta": {
"phone": "+15551234567",
"category": "customer"
}
}
]
Lists contacts of a client. The user must have permission to access this client.
Search Contact
GET /contact/{contact_id}
Update Contact
PUT /contact/{contact_id}
Updates contact data.
Remove Contact
DELETE /contact/{contact_id}
Removes a contact.
Agents
Create Agent
POST /api/v1/agents/
Request Body:
{
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "customer-service-agent",
"description": "Agent for customer service",
"type": "llm",
"model": "claude-3-opus-20240229",
"api_key": "your-api-key-here",
"instruction": "You are a customer service assistant for company X. Always be polite and try to solve customer problems efficiently.",
"config": {
"temperature": 0.7,
"max_tokens": 1024,
"tools": ["web_search", "knowledge_base"]
}
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "customer-service-agent",
"description": "Agent for customer service",
"type": "llm",
"model": "claude-3-opus-20240229",
"api_key": "your-api-key-here",
"instruction": "You are a customer service assistant for company X. Always be polite and try to solve customer problems efficiently.",
"config": {
"temperature": 0.7,
"max_tokens": 1024,
"tools": ["web_search", "knowledge_base"]
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
Creates a new agent. The user must have permission to access the specified client.
Notes about agent types:
- For
llm
type agents, themodel
andapi_key
fields are required - For
sequential
,parallel
, orloop
type agents, the configuration must include a list ofsub_agents
List Agents
GET /api/v1/agents/{client_id}
Query Parameters:
skip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "customer-service-agent",
"description": "Agent for customer service",
"type": "llm",
"model": "claude-3-opus-20240229",
"instruction": "You are a customer service assistant...",
"config": {
"temperature": 0.7,
"max_tokens": 1024,
"tools": ["web_search", "knowledge_base"]
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
]
Lists all agents of a client. The user must have permission to access the specified client.
Get Agent
GET /api/v1/agents/{agent_id}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "customer-service-agent",
"description": "Agent for customer service",
"type": "llm",
"model": "claude-3-opus-20240229",
"instruction": "You are a customer service assistant...",
"config": {
"temperature": 0.7,
"max_tokens": 1024,
"tools": ["web_search", "knowledge_base"]
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
Gets a specific agent. The user must have permission to access this agent.
Update Agent
PUT /api/v1/agents/{agent_id}
Request Body:
{
"name": "new-customer-service-agent",
"description": "Updated agent for customer service",
"type": "llm",
"model": "claude-3-sonnet-20240229",
"instruction": "You are a customer service assistant for company X...",
"config": {
"temperature": 0.5,
"max_tokens": 2048,
"tools": ["web_search", "knowledge_base", "calculator"]
}
}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"client_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "new-customer-service-agent",
"description": "Updated agent for customer service",
"type": "llm",
"model": "claude-3-sonnet-20240229",
"instruction": "You are a customer service assistant for company X...",
"config": {
"temperature": 0.5,
"max_tokens": 2048,
"tools": ["web_search", "knowledge_base", "calculator"]
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:05:00.000Z"
}
Updates agent data. The user must have permission to access this agent.
Delete Agent
DELETE /api/v1/agents/{agent_id}
Response (204 No Content)
Deletes an agent. The user must have permission to access this agent.
MCP Servers
Create MCP Server
POST /api/v1/mcp-servers/
Request Body:
{
"name": "openai-server",
"description": "MCP server for OpenAI API access",
"config_json": {
"base_url": "https://api.openai.com/v1",
"timeout": 30
},
"environments": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}"
},
"tools": ["web_search", "knowledge_base"],
"type": "official"
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "openai-server",
"description": "MCP server for OpenAI API access",
"config_json": {
"base_url": "https://api.openai.com/v1",
"timeout": 30
},
"environments": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}"
},
"tools": ["web_search", "knowledge_base"],
"type": "official",
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
Creates a new MCP server. Requires administrator permissions.
List MCP Servers
GET /api/v1/mcp-servers/
Query Parameters:
skip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "openai-server",
"description": "MCP server for OpenAI API access",
"config_json": {
"base_url": "https://api.openai.com/v1",
"timeout": 30
},
"environments": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}"
},
"tools": ["web_search", "knowledge_base"],
"type": "official",
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
]
Lists all available MCP servers.
Get MCP Server
GET /api/v1/mcp-servers/{server_id}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "openai-server",
"description": "MCP server for OpenAI API access",
"config_json": {
"base_url": "https://api.openai.com/v1",
"timeout": 30
},
"environments": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}"
},
"tools": ["web_search", "knowledge_base"],
"type": "official",
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
Gets a specific MCP server.
Update MCP Server
PUT /api/v1/mcp-servers/{server_id}
Request Body:
{
"name": "updated-openai-server",
"description": "Updated MCP server for OpenAI API access",
"config_json": {
"base_url": "https://api.openai.com/v1",
"timeout": 60
},
"environments": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}",
"OPENAI_ORG_ID": "${OPENAI_ORG_ID}"
},
"tools": ["web_search", "knowledge_base", "image_generation"],
"type": "official"
}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "updated-openai-server",
"description": "Updated MCP server for OpenAI API access",
"config_json": {
"base_url": "https://api.openai.com/v1",
"timeout": 60
},
"environments": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}",
"OPENAI_ORG_ID": "${OPENAI_ORG_ID}"
},
"tools": ["web_search", "knowledge_base", "image_generation"],
"type": "official",
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:05:00.000Z"
}
Updates an MCP server. Requires administrator permissions.
Delete MCP Server
DELETE /api/v1/mcp-servers/{server_id}
Response (204 No Content)
Deletes an MCP server. Requires administrator permissions.
Tools
Create Tool
POST /api/v1/tools/
Request Body:
{
"name": "web_search",
"description": "Real-time web search",
"config_json": {
"api_url": "https://api.search.com",
"max_results": 5
},
"environments": {
"SEARCH_API_KEY": "${SEARCH_API_KEY}"
}
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "web_search",
"description": "Real-time web search",
"config_json": {
"api_url": "https://api.search.com",
"max_results": 5
},
"environments": {
"SEARCH_API_KEY": "${SEARCH_API_KEY}"
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
Creates a new tool. Requires administrator permissions.
List Tools
GET /api/v1/tools/
Query Parameters:
skip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "web_search",
"description": "Real-time web search",
"config_json": {
"api_url": "https://api.search.com",
"max_results": 5
},
"environments": {
"SEARCH_API_KEY": "${SEARCH_API_KEY}"
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
]
Lists all available tools.
Get Tool
GET /api/v1/tools/{tool_id}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "web_search",
"description": "Real-time web search",
"config_json": {
"api_url": "https://api.search.com",
"max_results": 5
},
"environments": {
"SEARCH_API_KEY": "${SEARCH_API_KEY}"
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:00:00.000Z"
}
Gets a specific tool.
Update Tool
PUT /api/v1/tools/{tool_id}
Request Body:
{
"name": "web_search_pro",
"description": "Real-time web search with advanced filters",
"config_json": {
"api_url": "https://api.search.com/v2",
"max_results": 10,
"filters": {
"safe_search": true,
"time_range": "week"
}
},
"environments": {
"SEARCH_API_KEY": "${SEARCH_API_KEY}"
}
}
Response (200 OK):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "web_search_pro",
"description": "Real-time web search with advanced filters",
"config_json": {
"api_url": "https://api.search.com/v2",
"max_results": 10,
"filters": {
"safe_search": true,
"time_range": "week"
}
},
"environments": {
"SEARCH_API_KEY": "${SEARCH_API_KEY}"
},
"created_at": "2023-07-10T15:00:00.000Z",
"updated_at": "2023-07-10T15:05:00.000Z"
}
Updates a tool. Requires administrator permissions.
Delete Tool
DELETE /api/v1/tools/{tool_id}
Response (204 No Content)
Deletes a tool. Requires administrator permissions.
Chat
Send Message
POST /api/v1/chat
Request Body:
{
"agent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"contact_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"message": "Hello, I need help with my order."
}
Response (200 OK):
{
"response": "Hello! Of course, I'm here to help with your order. Could you please provide your order number or more details about the issue you're experiencing?",
"status": "success",
"timestamp": "2023-07-10T15:00:00.000Z"
}
Sends a message to an agent and returns the generated response. The user must have permission to access the specified agent and contact.
Conversation History
GET /api/v1/chat/history/{contact_id}
Query Parameters:
agent_id
(optional): Filter by a specific agentstart_date
(optional): Start date in ISO 8601 formatend_date
(optional): End date in ISO 8601 formatskip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"agent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"contact_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"message": "Hello, I need help with my order.",
"response": "Hello! Of course, I'm here to help with your order. Could you please provide your order number or more details about the issue you're experiencing?",
"timestamp": "2023-07-10T15:00:00.000Z"
}
]
Retrieves the conversation history of a specific contact. The user must have permission to access the specified contact.
Administration
Audit Logs
GET /api/v1/admin/audit-logs
Query Parameters:
user_id
(optional): Filter by useraction
(optional): Filter by action typestart_date
(optional): Start date in ISO 8601 formatend_date
(optional): End date in ISO 8601 formatresource_type
(optional): Type of affected resourceskip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"action": "CREATE",
"resource_type": "AGENT",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"timestamp": "2023-07-10T15:00:00.000Z",
"ip_address": "192.168.1.1",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
"details": {
"before": null,
"after": {
"name": "customer-service-agent",
"type": "llm"
}
}
}
]
Retrieves audit logs. Requires administrator permissions.
List Administrators
GET /api/v1/admin/users
Query Parameters:
skip
(optional): Number of records to skip (default: 0)limit
(optional): Maximum number of records to return (default: 100)
Response (200 OK):
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "admin@example.com",
"name": "Administrator",
"is_active": true,
"email_verified": true,
"is_admin": true,
"created_at": "2023-07-10T15:00:00.000Z"
}
]
Lists all administrator users. Requires administrator permissions.
Create Administrator
POST /api/v1/admin/users
Request Body:
{
"email": "new_admin@example.com",
"password": "securePassword123",
"name": "New Administrator"
}
Response (201 Created):
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"email": "new_admin@example.com",
"name": "New Administrator",
"is_active": true,
"email_verified": true,
"is_admin": true,
"created_at": "2023-07-10T15:00:00.000Z"
}
Creates a new administrator user. Requires administrator permissions.
Deactivate Administrator
DELETE /api/v1/admin/users/{user_id}
Response (204 No Content)
Deactivates an administrator user. Requires administrator permissions. The user is not removed from the database, just marked as inactive.
📝 Interactive Documentation
The interactive API documentation is available at:
- Swagger UI:
http://localhost:8000/docs
- ReDoc:
http://localhost:8000/redoc
📊 Logs and Audit
- Logs are stored in the
logs/
directory with the following format:{logger_name}_{date}.log
- The system maintains audit logs for important administrative actions
- Each action is recorded with information such as user, IP, date/time, and details
🤝 Contributing
- Fork the project
- Create a feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.