Overview
HandsAI uses SQLite as its embedded database, storing API provider configurations, tool definitions, parameters, and execution logs. The schema is managed by Hibernate using theupdate strategy.
Database Configuration
Connection Settings
- File Location:
handsai.db(in application directory) - WAL Mode: Write-Ahead Logging for improved concurrency
- Busy Timeout: 5 second wait for locked database
Hibernate Configuration
- Dialect:
SQLiteDialectfrom Hibernate Community Dialects - DDL Auto:
update- automatically evolves schema based on entities - No Sequences: SQLite doesn’t support sequences (
create_sequences=false)
Core Entities
BaseModel (Abstract)
All entities inherit common fields fromBaseModel:
id- Auto-incrementing primary key (IDENTITY strategy)code- Unique business identifier (nullable)enabled- Soft delete flag (default:true)createdAt- Creation timestamp (UTC, immutable)updatedAt- Last modification timestamp (UTC)
Entity Relationships
ApiProvider
Table:api_providers
Stores external API provider configurations including authentication and dynamic auth settings.
| Field | Type | Description |
|---|---|---|
name | String | Provider display name (e.g., “OpenWeather API”) |
baseUrl | String | Base URL for API (e.g., https://api.openweathermap.org) |
authenticationType | Enum | Authentication method: NONE, API_KEY, BEARER_TOKEN, BASIC_AUTH, DYNAMIC |
apiKeyLocation | Enum | Where to send API key: HEADER, QUERY_PARAM |
apiKeyName | String | Name of key/header (e.g., X-API-Key, apikey) |
apiKeyValue | String | Encrypted API key or token (using Jasypt) |
customHeadersJson | TEXT | JSON object with additional headers: {"User-Agent": "HandsAI"} |
isDynamicAuth | Boolean | Whether to use dynamic authentication (session tokens) |
dynamicAuthUrl | String | URL to obtain session token |
dynamicAuthMethod | Enum | HTTP method for auth request: GET, POST |
dynamicAuthPayload | TEXT | JSON payload for auth request |
dynamicAuthPayloadType | Enum | Payload format: JSON, FORM_DATA |
dynamicAuthPayloadLocation | Enum | Where to send payload: BODY, QUERY |
dynamicAuthTokenExtractionPath | String | JSONPath to extract token (e.g., $.data.token) |
dynamicAuthInvalidationKeywords | TEXT | Keywords indicating token expiration |
isExportable | Boolean | Whether provider can be exported/shared |
- One-to-Many with
ApiTool- A provider can have multiple tools - Cascade:
ALL- Deleting a provider deletes all its tools - Orphan Removal:
true- Removing a tool from the collection deletes it
ApiTool
Table:api_tools
Defines individual API endpoints exposed as MCP tools.
| Field | Type | Description |
|---|---|---|
name | String | Tool name for MCP (e.g., weather_get_current) |
description | String | Human-readable description for AI agents |
provider_id | Long | Foreign Key to api_providers.id |
endpointPath | String | Relative path (e.g., /v1/weather/current) |
httpMethod | Enum | HTTP method: GET, POST, PUT, DELETE, PATCH |
lastHealthCheck | Instant | Timestamp of last health check |
healthy | Boolean | Whether endpoint is currently accessible |
isExportable | Boolean | Whether tool can be exported |
- Many-to-One with
ApiProvider- Each tool belongs to one provider - One-to-Many with
ToolParameter- A tool can have multiple parameters - Cascade:
ALL- Deleting a tool deletes its parameters - Fetch:
LAZY- Parameters loaded on-demand
ToolParameter
Table:tool_parameters
Defines input parameters for API tools.
| Field | Type | Description |
|---|---|---|
name | String | Parameter name (e.g., city, units) |
type | Enum | Data type: STRING, NUMBER, INTEGER, BOOLEAN, OBJECT, ARRAY |
description | String | Description for AI agents (e.g., “City name or ZIP code”) |
required | Boolean | Whether parameter is mandatory |
defaultValue | String | Default value if not provided |
api_tool_id | Long | Foreign Key to api_tools.id |
- Many-to-One with
ApiTool- Each parameter belongs to one tool - Fetch:
LAZY- Tool loaded on-demand
Enumerations
AuthenticationTypeEnum
ApiKeyLocationEnum
HttpMethodEnum
ParameterType
Schema Migration
Hibernate Update Strategy
HandsAI uses Hibernate’supdate strategy for schema evolution:
- On startup, Hibernate compares entity definitions with existing schema
- Missing tables/columns are automatically created
- Existing columns are not modified or dropped
- Safe for iterative development
Manual Schema Changes
For complex migrations, use SQLite CLI:SQLite Specifics
WAL Mode (Write-Ahead Logging)
Enabled for better concurrency:- Readers don’t block writers
- Writers don’t block readers
- Better crash recovery
- Creates
handsai.db-walandhandsai.db-shmfiles - These are temporary and deleted on clean shutdown
Batch Processing
SQLite performs best with batched writes:Error Handling
HandleSQLITE_BUSY errors gracefully:
busy_timeout=5000 setting handles most lock contention automatically.
Query Examples
Find All Enabled Providers
Find Tools by Provider Code
Load Tool with Parameters
Data Integrity
Foreign Key Constraints
SQLite foreign keys must be explicitly enabled:api_tools.provider_id→api_providers.idtool_parameters.api_tool_id→api_tools.id
Cascade Behavior
Unique Constraints
FromBaseModel:
Backup and Recovery
Backup Database
Restore from Backup
Export to SQL
Next Steps
- Contributing Guide - Learn DTO separation patterns
- Tech Stack - Understand Spring Data JPA
- GraalVM Compatibility - Native image considerations