Frona is a single application with a Rust backend and a Next.js frontend, backed by an embedded SurrealDB database.
Engine (Rust backend)
The engine is the core of the platform. It handles:
- HTTP API: built on Axum, serves REST endpoints and SSE streams
- Agent orchestration: loads agent configs, manages tool loops, coordinates delegation
- Tool execution: runs tools server-side, manages browser sessions, sandboxes CLI/Python/Node.js commands
- Authentication: JWT-based auth with cookie and header support, optional SSO via OpenID Connect
- Database: SurrealDB embedded with RocksDB storage
- Scheduling: background task runner for scheduled tasks, heartbeats, compaction, and maintenance
- Inference: multi-provider LLM abstraction with fallback and retry support (via rig-core)
- App management: agent-deployed applications with sandboxed execution and health monitoring
Key modules
| Module | Purpose |
|---|---|
api/ | HTTP routes, middleware, request/response types |
agent/ | Agent models, service, tasks, prompt loading |
app/ | Agent-deployed application lifecycle and sandboxing |
auth/ | Authentication, JWT, SSO |
call/ | Voice call management |
chat/ | Chat sessions, messages, streaming |
contact/ | Contact management |
credential/ | Vault providers, credential storage, grants |
inference/ | LLM provider abstraction, tool loop |
memory/ | Fact storage, compaction |
notification/ | User notifications |
scheduler/ | Background task execution, heartbeats |
space/ | Space context management |
storage/ | File storage, workspaces, virtual paths |
tool/ | Tool implementations, registry, sandbox |
Frontend (Next.js)
The frontend is a Next.js application using the App Router with static export. It provides:
- Chat interface with real-time streaming
- Agent management and configuration UI
- Workspace and space navigation
- File attachments and tool result rendering
- App management and approval flows
- Settings and vault management
- Authentication flows (login, register, SSO)
- Setup wizard for first-time configuration
Key libraries
- Next.js 16 with React 19 and TypeScript
- Tailwind CSS for styling
- Shiki for syntax highlighting
- SSE client for real-time message streaming
Database (SurrealDB)
SurrealDB runs embedded inside the engine process. It uses RocksDB as the storage backend, so there's no separate database server to manage.
Tables
| Table | Stores |
|---|---|
user | User accounts |
agent | Agent definitions and configuration |
chat | Chat sessions |
message | Chat messages |
task | Tasks (direct, delegated, scheduled) |
space | Spaces and their context |
memory | Memory scopes |
memory_entry | Individual memory facts |
credential | Locally stored credentials |
vault_connection | External vault provider connections |
vault_grant | Credential access grants |
vault_access_log | Credential access audit trail |
app | Deployed applications |
tool_call | Tool call records |
keypair | JWT signing keypairs (encrypted at rest) |
api_token | Personal access tokens |
oauth_identity | SSO identity links |
notification | User notifications |
contact | Contacts |
call | Voice call records |
runtime_config | Runtime configuration |
Data flow
A typical request flows like this:
- User sends a message through the frontend
- Frontend makes a POST to the engine API
- Engine loads the agent config, conversation history, and memory
- Engine sends the prompt to the configured LLM provider
- LLM response streams back. If it includes tool calls, the engine executes them in the agent's sandbox.
- Tool results feed back into the LLM for the next iteration (the tool loop)
- Final response tokens stream to the frontend via SSE
- Messages are persisted to SurrealDB
Configuration system
The engine loads configuration from a YAML file and environment variable overrides. Environment variables use the FRONA_ prefix with underscore-separated paths (e.g., FRONA_SERVER_PORT maps to server.port).
Prompts are loaded from .md files in the shared config directory, not hardcoded. This makes it easy to customize agent behavior without modifying code.