lthn.ai Platform RFC
The authoritative spec for the lthn.ai platform. An agent should be able to implement any feature from this document alone.
Status: Draft specification, implementation baseline verified in-repo on 2026-03-31
Repository: /Users/snider/Code/lab/lthn.ai
Framework: CorePHP modular monolith
Production: lthn.ai (de1)
Staging: lthn.sh (homelab 10.69.69.165)
Local: lthn.test
Implementation snapshot (2026-03-31): OpenBrain async indexing and discovery, agent context boot, recall feedback, lifecycle pruning, workspace hierarchy APIs, Forge dashboard, fleet dispatch, agent OAuth, upgrade guides, docs search, webhook ingress, self-monitoring snapshots, and MCP operator surfaces are implemented in the current repo and covered by the local test suite.
1. Platform Overview
lthn.ai is the production platform for the Lethean ecosystem. It provides:
- Agent coordination — dispatch, messaging, brain (semantic memory)
- AI services — LEM model management, ethical scoring, studio (image/voice/remix)
- Infrastructure — MCP portal, server monitoring, documentation
- Commerce — subscriptions, API keys, usage billing
1.1 Domain Map
| Domain | Website Module | Purpose |
|---|---|---|
lthn.ai |
Website\Lthn |
Marketing, models, ethics, research |
app.lthn.ai |
Website\App |
Client dashboard (authenticated) |
api.lthn.ai |
Website\Api |
REST API + MCP HTTP bridge |
mcp.lthn.ai |
Website\Mcp |
MCP server registry + portal |
docs.lthn.ai |
Website\Docs |
Documentation |
1.2 Module Map
| Module | Namespace | Purpose |
|---|---|---|
| Agentic | Mod\Agentic |
Agent dispatch, messaging, plans, sessions |
| Lem | Mod\Lem |
LEM model management, ethical scoring |
| Mcp | Mod\Mcp |
MCP tool/server registry |
| Studio | Mod\Studio |
Multimedia pipeline (image, voice, remix) |
| Uptelligence | Mod\Uptelligence |
Server monitoring, uptime |
1.3 Service Map
| Service | Namespace | Purpose |
|---|---|---|
| Commerce | Service\Commerce |
Subscriptions, billing, API keys |
| Agentic | Service\Agentic |
Agent service definitions + entitlements |
2. Infrastructure
2.1 Stack
| Component | Production (de1) | Homelab (lthn.sh) | Local (lthn.test) |
|---|---|---|---|
| App | Docker 8005-8006 | Docker | Valet/Herd |
| Database | MariaDB (Galera) | MariaDB | MariaDB |
| Cache | Dragonfly (6379) | Redis | Redis |
| Search | Elasticsearch | Elasticsearch | Elasticsearch |
| Vector | Qdrant (qdrant.lthn.sh) | Qdrant | Qdrant |
| Embedding | Ollama (homelab) | Ollama (local) | Ollama |
| Queue | Redis | Redis | sync |
| Storage | Garage S3 (3900) | Local | Local |
| Auth | Authentik (9000) | - | - |
| Proxy | Traefik (80/443) | Traefik | - |
2.2 Deployment
# Production (de1) — ALWAYS via Ansible
cd ~/Code/DevOps
ansible-playbook playbooks/deploy_lthn_ai.yml -i inventory/linux_snider_dev.yml
# Homelab (lthn.sh)
ansible-playbook playbooks/deploy_lthn_sh.yml -i inventory/linux_snider_dev.yml
# NEVER ssh directly to production (port 22 = endlessh trap, real SSH on 4819)
3. OpenBrain — Semantic Memory
See doc/RFC-OPENBRAIN.md for the full spec.
Summary:
- MariaDB is source of truth (text + metadata)
- Qdrant is the vector index (embeddings + payload)
- Elasticsearch for full-text search + tag discovery
- Async embedding via queue jobs (return fast, index later)
- Scoped by
{org}/{project}— "core/go-io", "lthn/lthn.ai", "ofm/ofm.bot" - Re-index command rebuilds Qdrant/ES from MariaDB
3.1 Current State
- BrainService exists at
Core\Mod\Agentic\Services\BrainService - API routes at
api.lthn.ai/v1/brain/* - MariaDB, Qdrant, and Elasticsearch-backed discovery are wired
- Embedding is queued asynchronously via
EmbedMemory - Org and project scoping are persisted in MariaDB and Qdrant payloads
- Discovery endpoints cover search, tags, and scopes
- Maintenance commands cover re-indexing and content cleanup
- 8,654 memories in production
3.2 What Needs Doing
- Backfill and operate production indexes during rollout
- Track live queue depth and indexing latency in Uptelligence
- Verify rate limits and failure handling against production traffic
- Keep discovery relevance tuned as production memory volume grows
4. Workspace Hierarchy
Core-tenant currently has flat workspaces. Need child workspaces for project organisation.
4.1 Schema
workspaces
├── id
├── parent_id ← NEW (nullable, self-referencing FK)
├── name
├── slug
├── owner_id
├── plan_id
└── settings (JSON)
Example:
Workspace "Core" (id=1, parent_id=null)
├── Child "go-io" (id=10, parent_id=1)
├── Child "agent" (id=11, parent_id=1)
└── Child "mcp" (id=12, parent_id=1)
Workspace "OFM" (id=2, parent_id=null)
└── Child "ofm.bot" (id=20, parent_id=2)
4.2 Inheritance
- Child workspaces inherit parent's users and entitlements
- Child can have additional members (project-specific collaborators)
- Billing rolls up to parent workspace
- Each child gets its own API key scope
4.3 Admin Panel
Project overview in core-admin showing:
- Workspace tree (parent → children)
- Per-project stats (memories, agents, API calls)
- Quick navigation to project settings
5. API
5.1 Current Endpoints
| Prefix | Module | Status |
|---|---|---|
/v1/brain/* |
OpenBrain | Working (async indexing + scoped discovery) |
/v1/messages/* |
Agent Messaging | Working |
/v1/plans/* |
Plans | Working |
/v1/sessions/* |
Sessions | Working |
/v1/score/* |
EaaS Scoring | Working |
/v1/health |
Health | Working |
/mcp/* |
MCP Bridge | Working |
/v1/docs/search |
Docs search | Working |
/v1/upgrades/* |
Upgrade guides | Working |
/v1/agent/* |
Fleet registration, check-in, SSE | Working |
/oauth/token |
Agent OAuth client credentials | Working |
/docs/* |
OpenAPI | Working |
5.2 Implemented RFC Endpoints
| Endpoint | Purpose | Status |
|---|---|---|
GET /v1/brain/search |
Elasticsearch full-text search | Implemented |
GET /v1/brain/tags |
Tag discovery/aggregation | Implemented |
GET /v1/brain/scopes |
List orgs/projects with counts | Implemented |
GET /v1/brain/agent/{agent_id}/context |
Agent boot context across agent/shared/project/session scopes | Implemented |
POST /v1/brain/recall/{recall_id}/feedback |
Recall quality feedback loop | Implemented |
GET /v1/workspaces/{id}/children |
Child workspace listing | Implemented |
POST /v1/workspaces/{id}/children |
Create child workspace | Implemented |
POST /v1/agent/register |
Fleet agent registration | Implemented |
GET /v1/agent/checkin |
Agent polling fallback | Implemented |
GET /v1/agent/events |
Fleet SSE stream | Implemented |
GET /v1/issues/* |
Forge issue proxy | Implemented |
GET /v1/upgrades/* |
Upgrade guide API surface | Implemented |
5.3 Auth
API keys with scope-based permissions:
brain:read/brain:writeplans:read/plans:writesessions:read/sessions:writescore:read/score:write
6. Testing
6.1 Current State
- RFC coverage has been expanded across API, Agentic, MCP, Uptelligence, Forge, Docs, and LEM surfaces
- The local suite passes with 173 tests and 790 assertions as of 2026-03-31
- Remaining work is operational coverage and production verification, not missing baseline tests
6.2 Required
Every API endpoint needs:
- Happy path test (valid request → expected response)
- Auth test (no token → 401, wrong scope → 403)
- Validation test (bad input → 422)
- Edge case test (empty results, max limits, etc.)
Every Service needs:
- Unit tests with mocked dependencies
- Integration tests against real DB
6.3 Convention
// Test naming: descriptive, grouped by endpoint
class BrainRecallTest extends TestCase
{
public function test_recall_returns_ranked_memories(): void { }
public function test_recall_filters_by_org(): void { }
public function test_recall_requires_auth(): void { }
public function test_recall_validates_query(): void { }
}
7. UI
7.1 Stack
- Livewire 3 — server-driven components
- Flux UI Pro — component library (auth: composer.fluxui.dev)
- Font Awesome Pro Plus 7.2 — icons (web assets at Claude-Toys/design/)
- Alpine.js — client-side interactivity (via Livewire)
- Vite — asset bundling
7.2 Design Reference
- Host.uk.com uses Stellar theme (Cruip) as base
- Themes available at
Claude-Toys/themes/cruip/ - mosaic-laravel-livewire for admin dashboard patterns
7.3 Brand
- UK English (colour, organisation, centre)
- Professional but approachable
- Oxford comma, sentence case headings
- No exclamation marks
- Banned words: leverage, utilise, seamless, robust, game-changing, best-in-class
8. Inter-Module Communication
8.1 Events
Modules communicate via Laravel events:
// OpenBrain
event(new MemoryStored($memory));
event(new MemoryRecalled($query, $results));
// Agentic
event(new AgentSessionStarted($agentId, $org, $project));
event(new AgentTaskCompleted($agentId, $workspace, $status));
// Commerce
event(new SubscriptionActivated($workspace, $plan));
event(new UsageRecorded($workspace, $metric, $amount));
8.2 Listeners
// Lem listens for memories → update training data
MemoryStored::class => [UpdateTrainingData::class]
// Uptelligence listens for recall latency → track performance
MemoryRecalled::class => [TrackRecallLatency::class]
// Commerce listens for API usage → billing
ApiRequestCompleted::class => [RecordUsage::class]
9. Admin Panel — Forge Section
The admin panel (app.lthn.ai) gets a "Forge" section for managing the software development lifecycle. This surfaces data from Forge (Forgejo), Uptelligence, OpenBrain, and the agent system into one dashboard.
9.1 Forge Overview Dashboard
┌─────────────────────────────────────────────────┐
│ Forge │
├──────────┬──────────┬──────────┬────────────────┤
│ Repos │ Issues │ Agents │ Uptelligence │
│ 42 total │ 18 open │ 2 running│ 3 alerts │
│ 3 dirty │ 5 urgent │ 8 queued │ 1 degraded │
└──────────┴──────────┴──────────┴────────────────┘
9.2 Sub-sections
| Section | Source | Shows |
|---|---|---|
| Repositories | Forge API | List repos, branches, last commit, build status, dirty/clean |
| Issues | Forge API | Open issues by label (agentic, bug, help-wanted), assignee, priority |
| Plans | Plans API | Active plans with phase progress, checkpoints, blockers |
| Agents | Agent Status | Running/queued/completed/failed agents, workspace drill-down |
| Uptelligence | Monitoring | Service health, response times, alerts needing attention |
| Migrations | Upgrade Guides | Pending upgrades, migration plans, dependency graph |
9.3 Actionable Items
The dashboard highlights items that need attention:
⚠ Agent dispatch needed:
- go-build: 3 failing tests since last push (Uptelligence)
- core-tenant: Issue #45 marked 'agentic' — ready for agent work
- go-io: Dependency update available (core v0.8.0-alpha.1 → v0.8.0)
🔄 Migrations pending:
- Laravel 12.x → 13.x: 4 packages affected
- dappco.re/go/core v0.8.0 → v0.9.0: 20 packages need bumping
Each item has a one-click "Dispatch Agent" action that opens a dispatch dialog with the repo, task, and template pre-filled.
9.4 Livewire Components
App\Livewire\Forge\
├── Dashboard.php — Overview with counts and alerts
├── RepositoryList.php — Repo table with status badges
├── IssueBoard.php — Kanban-style issue board by label
├── PlanProgress.php — Plan phases with task checkboxes
├── AgentMonitor.php — Live agent status (polls via wire:poll)
├── UptimeOverview.php — Service health grid
├── MigrationTracker.php — Upgrade guides and pending migrations
└── DispatchDialog.php — Modal for dispatching agents
10. Upgrade Guides — Content Product
Upgrade guides are both an internal tool (keeping the ecosystem current) and a content product (published on lthn.ai/docs for SEO and community value).
10.1 Detection — Uptelligence Software Monitors
Uptelligence monitors software versions from multiple sources. When a new version is detected, it triggers the upgrade guide pipeline.
Monitor Types
| Type | Source | Example |
|---|---|---|
| Packagist | Packagist API | Laravel, Livewire, Pest |
| GitHub Release | GitHub Releases API | Go, Node, Qdrant, Ollama |
| NPM | NPM registry API | Vite, TailwindCSS |
| Go Proxy | proxy.golang.org | Go modules |
| Custom API | Vendor endpoint | AltumCode products (66Biolinks, phpAnalytics, etc.) |
| Web Scrape | Configured URL + selector | Anything with a version on a page |
Monitor Schema
class SoftwareMonitor extends Model
{
use BelongsToWorkspace;
protected $fillable = [
'name', // "laravel/framework"
'type', // "packagist", "github", "npm", "go", "api", "scrape"
'source', // URL or package identifier
'current_version', // "12.4.1" (last known)
'latest_version', // "13.0.0" (last checked)
'check_interval', // minutes between checks
'selector', // CSS selector for scrape type, JSON path for API
'headers', // JSON — custom headers (auth tokens etc.)
'auto_guide', // boolean — auto-generate upgrade guide on major bump
'auto_dispatch', // boolean — auto-dispatch agents on minor/patch
'notify_channel', // "agent.status", "inbox.message", null
'last_checked_at',
'last_changed_at',
];
}
Check Flow
1. Cron: php artisan uptelligence:check-software (every 15 min)
2. For each monitor:
a. Fetch latest version from source
b. Compare with current_version
c. If changed:
- Update latest_version + last_changed_at
- Emit SoftwareUpdateDetected event
- If major bump + auto_guide: dispatch guide generation
- If minor/patch + auto_dispatch: dispatch upgrade agents
- If notify_channel: push notification
AltumCode Integration
// Custom API monitor for AltumCode products
SoftwareMonitor::create([
'name' => '66Biolinks',
'type' => 'api',
'source' => 'https://api.altumcode.com/versions',
'selector' => '$.biolinks.version', // JSON path
'check_interval' => 60,
'auto_guide' => true,
]);
Events
event(new SoftwareUpdateDetected($monitor, $oldVersion, $newVersion));
event(new UpgradeGuideGenerated($guide));
event(new UpgradeDispatchStarted($guide, $repos));
10.2 Guide Generation
When a library releases a new major version, an agent generates a structured upgrade guide:
- Changelog analysis — parse release notes, extract breaking changes
- Migration steps — ordered list of code changes needed
- Search & replace — specific patterns to find and replace
- Test strategy — what to test after upgrading
- Rollback plan — how to revert if it breaks
10.3 Guide Schema
class UpgradeGuide extends Model
{
use BelongsToWorkspace;
protected $fillable = [
'library', // "laravel/framework"
'from_version', // "12.0"
'to_version', // "13.0"
'language', // "php", "go", "js"
'title', // "Upgrading Laravel 12 to 13"
'summary', // Short description
'breaking_changes', // JSON array of breaking changes
'migration_steps', // JSON array of ordered steps
'search_replace', // JSON array of {find, replace, files} patterns
'test_strategy', // Markdown
'rollback_plan', // Markdown
'published', // boolean
'published_at', // timestamp
];
}
10.4 Generation Flow
1. Detect new release (Uptelligence monitors GitHub/Packagist)
2. Dispatch agent: "Generate upgrade guide for {library} {from}→{to}"
3. Agent reads changelog, analyses breaking changes
4. Agent tests the upgrade on a sample project
5. Agent writes the guide
6. Human reviews in admin panel
7. Publish to lthn.ai/docs/upgrades/{library}/{from}-to-{to}
10.5 Internal Use
The same guides drive internal upgrades:
# List pending upgrades for the ecosystem
php artisan upgrade:check
# Apply an upgrade guide to a specific repo
php artisan upgrade:apply --guide=laravel-12-to-13 --repo=lthn.ai
# Dispatch agents to upgrade all affected repos
php artisan upgrade:dispatch --guide=laravel-12-to-13
10.6 Content Value
Published guides on lthn.ai serve as:
- SEO content — "how to upgrade Laravel 12 to 13" ranks well
- Community goodwill — free, practical, maintained
- Trust signal — shows the platform understands the ecosystem
- Lead generation — readers discover lthn.ai's other services
10.7 API
GET /v1/upgrades — list all guides
GET /v1/upgrades/{library} — guides for a library
GET /v1/upgrades/{library}/{from}-to-{to} — specific guide
POST /v1/upgrades — create guide (agent)
PATCH /v1/upgrades/{id} — update guide
POST /v1/upgrades/{id}/publish — publish to site
11. Authentication — Agent OAuth
11.1 Current State
The platform now supports both first-party OAuth client credentials and the legacy static API key path. The fallback API key flow still validates Bearer tokens against agent_api_keys with:
- Scope-based permissions (
brain:read,brain:write,plans:read, etc.) - IP whitelisting
- Rate limiting per key
- Revocation and expiry
OAuth access tokens are issued from agent_oauth_clients and agent_oauth_access_tokens, then enforced by the shared API credential middleware on protected routes.
11.2 What's Needed: OAuth2 Client Credentials
Agents are service accounts, not users. The OAuth2 Client Credentials flow fits:
Agent (core-agent on homelab) → POST /oauth/token
{ grant_type: "client_credentials", client_id: "charon", client_secret: "..." }
← { access_token: "...", token_type: "Bearer", expires_in: 3600, scope: "brain:read brain:write" }
Agent → GET /v1/brain/recall
Authorization: Bearer {access_token}
11.3 Implementation
The current repo implements the flow with first-party OAuth client and token models rather than Passport:
// Agent registers as an OAuth client
$client = Passport::client()->create([
'name' => 'charon',
'redirect' => '',
'personal_access_client' => false,
'password_client' => false,
'revoked' => false,
]);
// Agent authenticates
POST /oauth/token
{
"grant_type": "client_credentials",
"client_id": "{client_id}",
"client_secret": "{client_secret}",
"scope": "brain:read brain:write messages:read messages:write"
}
11.4 Agent Identity
Each agent gets an OAuth client that maps to its identity:
| Agent | Client ID | Host | Scopes |
|---|---|---|---|
| Cladius | cladius |
M3 Studio (local) | brain:* messages:* plans:* sessions:* |
| Charon | charon |
Homelab (10.69.69.165) | brain:* messages:* plans:* dispatch:* |
| Codex | codex |
Docker containers | brain:read plans:read |
| Clotho | clotho |
Remote | brain:read messages:read |
11.5 Backward Compatibility
Keep the existing API key auth as a fallback. Both paths work:
// Middleware tries OAuth token first, falls back to API key
public function handle(Request $request, Closure $next, ...$scopes)
{
// Try OAuth (Passport/Sanctum)
if ($this->tryOAuth($request, $scopes)) {
return $next($request);
}
// Fall back to API key
if ($this->tryApiKey($request, $scopes)) {
return $next($request);
}
return $this->unauthorised('Authentication required');
}
11.6 core/agent Integration
core-agent's transport layer (transport.go) needs an OAuth client:
// On startup: exchange credentials for token
func (s *Service) authenticate(ctx context.Context) error {
r := HTTPPost(ctx, s.apiURL+"/oauth/token", core.JSONMarshalString(map[string]any{
"grant_type": "client_credentials",
"client_id": s.clientID,
"client_secret": s.clientSecret,
"scope": "brain:read brain:write messages:read messages:write",
}), "", "")
// Cache token, refresh before expiry
s.token = r.Value.(map[string]any)["access_token"].(string)
s.tokenExpiry = time.Now().Add(time.Duration(expiresIn) * time.Second)
return nil
}
12. MCP Portal (mcp.lthn.ai)
12.1 Current State
The MCP portal already has Livewire components:
| Component | Purpose |
|---|---|
mcp.dashboard |
Overview |
mcp.api-key-manager |
Create/revoke API keys |
mcp.api-explorer |
Browse available endpoints |
mcp.mcp-metrics |
Request counts, latency |
mcp.mcp-playground |
Test tool calls interactively |
mcp.playground |
General API playground |
mcp.request-log |
Recent API requests |
mcp.unified-search |
Search across tools/resources |
API routes are shared with api.lthn.ai — same endpoints, different domain.
12.2 What's Needed
| Feature | Status | Notes |
|---|---|---|
| Tool registry (list/search) | Exists | Via core-mcp package |
| API key management | Exists | Create, revoke, scope |
| Request playground | Exists | Interactive tool calls |
| Metrics dashboard | Exists | Needs real data pipeline |
| OAuth client management | Implemented | Livewire operator surface for issuing and revoking agent clients |
| Agent status panel | Implemented | Live view of registrations, capacity, and assigned jobs |
| Brain explorer | Implemented | Browse scoped memories, tags, and search results |
| Webhook configuration | Implemented | Manage webhook endpoints, secrets, and recent deliveries |
12.3 MCP HTTP Bridge
The bridge at /mcp/tools/call proxies HTTP requests to MCP tool calls. This lets web clients and REST consumers use MCP tools without a stdio connection:
POST /mcp/tools/call
Authorization: Bearer {token}
{
"tool": "brain_recall",
"arguments": {
"query": "service registration pattern",
"org": "core"
}
}
→ 200 OK
{
"content": [...],
"isError": false
}
12.4 Server-Sent Events
For live updates (agent status, brain operations), the MCP portal should support SSE:
GET /mcp/events
Authorization: Bearer {token}
Accept: text/event-stream
data: {"type": "agent.started", "repo": "go-io", "agent": "codex"}
data: {"type": "agent.completed", "repo": "go-io", "status": "completed"}
data: {"type": "brain.indexed", "memory_id": "uuid", "org": "core"}
This connects the web dashboard to the same event stream that Claude Code channels use.
13. Fleet Dispatch — Distributed Agent Network
13.1 Vision
lthn.ai is the fleet controller. core-agent instances run on any machine — homelab, community members' desktops, CI runners — and connect to lthn.ai to receive work. This enables:
- Distributed compute — work dispatched to wherever there's capacity
- Community contribution — Lethean community members donate compute by running core-agent
- Elastic scaling — more agents come online as needed
- Centralised coordination — lthn.ai decides what runs where
13.2 Architecture
┌──────────────┐
│ lthn.ai │ ← Fleet controller (PHP)
│ (api + mcp) │
├──────────────┤
│ Job Queue │ ← Pending dispatch jobs
│ Agent Registry│ ← Which agents are online, their capabilities
│ SSE Stream │ ← Push jobs to connected agents
└──────┬───────┘
│
├──── core-agent (M3 Studio — Cladius)
│ └── Claude Max, local repos, full access
│
├──── core-agent (Homelab — Charon)
│ └── Claude Max, Docker, GPU (RX 7800 XT)
│
├──── core-agent (Community Node)
│ └── Codex only, sandboxed, limited scopes
│
└──── core-agent (CI Runner)
└── Codex only, ephemeral, build+test only
13.3 Agent Registration
core-agent connects to lthn.ai on startup and registers:
// core-agent startup
POST /v1/agent/register
Authorization: Bearer {oauth_token}
{
"agent_id": "charon",
"hostname": "charon.lthn.io",
"capabilities": ["claude", "codex", "docker", "gpu"],
"max_concurrent": 3,
"labels": ["go", "php", "devops"],
"version": "0.8.0-alpha.1"
}
→ 201 Created
{
"registration_id": "uuid",
"sse_url": "/v1/agent/events",
"heartbeat_interval": 30
}
13.4 Job Queue (PHP Side)
class DispatchJob extends Model
{
use BelongsToWorkspace;
protected $fillable = [
'repo',
'org',
'task',
'agent_type', // "codex", "claude", "gemini"
'template', // "coding", "conventions", "security"
'branch',
'priority', // 1-10
'labels', // JSON — match against agent labels
'status', // "pending", "assigned", "running", "completed", "failed"
'assigned_agent', // agent_id that picked it up
'assigned_at',
'completed_at',
'result', // JSON — output from agent
];
}
13.5 Job Assignment Flow
1. User/system creates DispatchJob (via admin panel, API, or Uptelligence trigger)
2. lthn.ai checks registered agents for matching capabilities + labels
3. For connected agents (SSE): push job immediately
4. For polling agents: return job on next checkin
5. Agent accepts job → status = "assigned"
6. Agent preps workspace, spawns subagent → status = "running"
7. Agent reports completion → status = "completed" with result
8. lthn.ai fires events (AgentCompleted → channel notification, queue next)
13.6 SSE Event Stream
Connected agents receive jobs in real-time:
GET /v1/agent/events
Authorization: Bearer {oauth_token}
event: job.assigned
data: {"job_id": "uuid", "repo": "go-io", "task": "AX polish", "agent_type": "codex"}
event: job.cancelled
data: {"job_id": "uuid", "reason": "superseded"}
event: ping
data: {"timestamp": "2026-03-27T15:00:00Z"}
13.7 Polling Fallback
Agents behind NAT or firewalls poll instead of SSE:
GET /v1/agent/checkin?agent_id=charon
Authorization: Bearer {oauth_token}
→ 200 OK
{
"jobs": [
{"job_id": "uuid", "repo": "go-io", "task": "AX polish", "agent_type": "codex"}
],
"messages": [
{"id": 170, "from": "cladius", "subject": "next batch", "content": "..."}
]
}
13.8 core-agent Integration (Go Side)
core-agent gets a fleet mode that connects to lthn.ai:
// core-agent fleet — connect to lthn.ai fleet controller
c.Command("fleet", core.Command{
Description: "Connect to lthn.ai fleet controller and accept dispatched work",
Action: func(opts core.Options) core.Result {
fleet := NewFleetClient(c, FleetOptions{
APIUrl: "https://api.lthn.ai",
AgentID: core.Env("AGENT_ID"),
ClientID: core.Env("OAUTH_CLIENT_ID"),
Secret: core.Env("OAUTH_CLIENT_SECRET"),
})
return fleet.Run(ctx) // SSE connect + heartbeat + job execution loop
},
})
13.9 Systray App
For community members, core-agent runs as a systray application:
┌──────────────────────┐
│ 🟢 Lethean Agent │
│ Connected to lthn.ai │
│ Jobs: 2 running │
│ ─────────────────── │
│ Settings... │
│ View logs... │
│ Pause │
│ Quit │
└──────────────────────┘
Built with core/go-webview (Wails WebView2). The agent runs in the background, connects to lthn.ai, accepts jobs within configured limits (max concurrent, allowed agent types, repo restrictions).
13.10 Community Onboarding
1. Download core-agent from lthn.ai/download
2. Run installer → creates systray app
3. Sign in with lthn.ai account → OAuth token
4. Configure: max concurrent jobs, GPU availability, allowed repos
5. Agent connects to fleet → starts receiving work
13.11 Security for Community Nodes
- All work runs in Docker containers (sandboxed)
- Community nodes only get Codex jobs (no Claude — no API key sharing)
- No access to private repos unless explicitly whitelisted
- Results are verified before merging (CodeRabbit + human review)
- API scopes limited:
dispatch:executeonly, nobrain:write
14. PHP Agent Package (core/agent/php)
14.1 Current State
The PHP agent package at core/agent/php provides the server-side of the agent system:
| Component | Files | Purpose |
|---|---|---|
| Controllers | 10 API controllers | REST endpoints for plans, sessions, issues, brain, messages |
| Services | 12 service classes | BrainService, AgenticManager, ForgejoService, Claude/Gemini/OpenAI |
| Models | 14 Eloquent models | Plans, sessions, memories, messages, API keys, sprints, tasks |
| Jobs | Queue jobs | Async processing |
| Middleware | AgentApiAuth | Bearer token + scope validation |
| Routes | api.php (109 lines) | Full REST API for agent operations |
| Migrations | DB schemas | brain_memories, agent_plans, agent_sessions, etc. |
14.2 What's Needed
| Feature | Status | Notes |
|---|---|---|
| BrainService async embedding | Implemented | EmbedMemory queue job with indexed_at tracking |
| BrainService org scoping | Implemented | Scope columns, filters, and Qdrant payload support |
| Elasticsearch integration | Implemented | Search, tags, and scopes discovery endpoints |
| DispatchJob model | Implemented | Fleet job queue with API and Forge composer wiring |
| AgentRegistration model | Implemented | Fleet agent registry with heartbeat tracking |
| SSE controller | Implemented | Real-time fleet and MCP event streams |
| Fleet checkin endpoint | Implemented | Polling fallback assigns matching work during check-in |
| OAuth client management | Implemented | First-party client credentials issuer and token store |
| Software monitor model | Implemented | Uptelligence release tracking and guide triggers |
| Upgrade guide model | Implemented | Draft, publish, and retrieval flow for upgrade content |
| Test coverage | Expanded | RFC and supporting surfaces are covered by the passing local suite |
14.3 Integration with lthn.ai
The PHP package is installed in lthn.ai via Composer:
{
"repositories": [
{
"type": "path",
"url": "../core/agent/php"
}
],
"require": {
"lthn/agent": "@dev"
}
}
All models, migrations, routes, and services register via the Boot.php service provider. lthn.ai adds its own Website modules (Api, Mcp, App) that consume the package's services.
15. Observability
15.1 Self-Monitoring
lthn.ai monitors itself via the Uptelligence module. Key metrics:
| Metric | Source | Alert Threshold |
|---|---|---|
| API response time | Middleware timing | p95 > 500ms |
| Error rate | Exception handler | > 1% of requests |
| Queue depth | Laravel Horizon/Redis | > 100 pending jobs |
| Agent fleet size | Agent registry | < 1 connected agent |
| Brain embed queue | EmbedMemory job count | > 50 pending |
| Qdrant health | /collections endpoint |
non-200 |
| Ollama health | /api/tags endpoint |
non-200 |
| Elasticsearch health | /_cluster/health |
status != green |
| Disk usage | Host metrics | > 85% |
| MariaDB connections | SHOW STATUS |
> 80% of max |
15.2 Metrics Storage
class Metric extends Model
{
protected $fillable = [
'name', // "api.response_time.p95"
'value', // 245.5
'unit', // "ms", "count", "percent", "bytes"
'tags', // JSON {"endpoint": "/v1/brain/recall", "method": "POST"}
'recorded_at',
];
}
15.3 Dashboard
Uptelligence section in admin panel shows:
- Real-time service health grid (green/amber/red)
- API latency graph (last 24h)
- Queue depth over time
- Agent fleet status (online/offline/busy)
- Error log (last 50 errors with stack traces)
15.4 Alerting
// Uptelligence checks run on schedule
$schedule->command('uptelligence:check')->everyMinute();
// Alerts dispatch via:
event(new AlertTriggered($metric, $threshold, $value));
// Listeners:
AlertTriggered::class => [
SendChannelNotification::class, // Push to agent channel
SendSlackNotification::class, // If configured
CreateIssue::class, // Auto-create Forge issue
DispatchAgent::class, // Auto-dispatch fix agent if auto_dispatch enabled
]
16. Webhook Ingress
16.1 Sources
| Source | Endpoint | Trigger |
|---|---|---|
| Forge (Forgejo) | POST /webhooks/forge |
Push, PR, issue, release |
| GitHub | POST /github/webhook |
Push, PR (mirror repos) |
| CI Runner | POST /webhooks/ci |
Build pass/fail |
| Uptelligence | Internal event | Software update detected |
| Deploy | POST /webhooks/deploy |
Deploy success/failure |
16.2 Webhook Processing
class WebhookController extends Controller
{
public function forge(Request $request): JsonResponse
{
$event = $request->header('X-Forgejo-Event');
$payload = $request->all();
match ($event) {
'push' => event(new ForgePushReceived($payload)),
'pull_request' => event(new ForgePRReceived($payload)),
'issues' => event(new ForgeIssueReceived($payload)),
'release' => event(new ForgeReleaseReceived($payload)),
default => null,
};
return response()->json(['ok' => true]);
}
}
16.3 Event → Action Mapping
| Event | Action |
|---|---|
| Push to dev | Run QA on changed packages |
| PR created | Dispatch CodeRabbit review |
| Issue labelled 'agentic' | Dispatch agent to work on it |
| Release published | Trigger upgrade guide check for consumers |
| CI build failed | Create Forge issue + dispatch fix agent |
| Deploy success | Run smoke tests via Uptelligence |
| Software update detected | Generate upgrade guide |
17. Documentation Site (docs.lthn.ai)
17.1 Architecture
docs.lthn.ai serves documentation from two sources:
- Static docs — MkDocs Material (core.help content), deployed as static files
- Dynamic content — Upgrade guides generated by agents, served from database
- API docs — OpenAPI spec auto-generated, served via Scalar/Swagger
17.2 Content Structure
docs.lthn.ai/
├── getting-started/ ← Static (MkDocs)
├── go/ ← Static (Core Go docs)
├── php/ ← Static (CorePHP docs)
├── api/ ← Dynamic (OpenAPI spec)
├── upgrades/ ← Dynamic (generated upgrade guides)
│ ├── laravel/
│ │ └── 12-to-13/
│ ├── go/
│ │ └── 1.25-to-1.26/
│ └── tailwindcss/
│ └── 3-to-4/
└── reference/ ← Static (RFC specs)
17.3 Search
Docs search powered by the same Elasticsearch instance as OpenBrain:
GET /v1/docs/search?q=service+registration
→ { "hits": [...], "categories": ["go", "php", "api"] }
18. LEM Module
18.1 Purpose
LEM (Lethean Ethical Model) provides AI ethical scoring and model management.
18.2 Current State
| Component | Status |
|---|---|
| ScoreEthics action | Exists |
| ScoreImprint action | Exists |
| LemController API | Exists |
| ScoringActionsTest | Exists (1 test file) |
| EaaS scoring endpoints | Exists (/v1/score/*) |
18.3 Scoring Types
| Endpoint | Purpose |
|---|---|
/v1/score/content |
Score text content for ethical concerns |
/v1/score/imprint |
Score AI model's training data imprint |
/v1/score/model |
Score a model's overall ethical profile |
/v1/score/full |
Combined comprehensive score |
/v1/score/session/* |
Multi-turn scoring session |
18.4 What's Needed
- Test coverage for all scoring actions
- Integration with OpenBrain (store scoring decisions as memories)
- Scoring dashboard in admin panel
- API documentation for EaaS consumers
19. Studio Module
19.1 Purpose
Multimedia pipeline — image generation, voice synthesis, remix/mashup.
19.2 Current State
| Controller | Endpoints | Status |
|---|---|---|
| ImageController | Image generation API | Exists |
| VoiceController | Voice synthesis API | Exists |
| AssetController | Asset management | Exists |
| RemixController | Remix/mashup pipeline | Exists |
19.3 Scope
Studio is functional but not in scope for initial production launch. It ships when it ships. Focus is on brain, fleet, and API stability first.
20. Backup and Recovery
20.1 Strategy
| Component | Method | Frequency | Retention | Location |
|---|---|---|---|---|
| MariaDB | mariadb-dump + Galera snapshots |
Hourly | 7 days | Garage S3 |
| Qdrant | Collection snapshots via API | Daily | 30 days | Garage S3 |
| Elasticsearch | Snapshot API | Daily | 14 days | Garage S3 |
| Redis/Dragonfly | RDB snapshots | Hourly | 3 days | Local |
| Uploads | S3 sync | Real-time | Indefinite | Garage S3 |
| Config/Env | Git (DevOps repo) | On change | Indefinite | Forge |
20.2 Restore Procedure
# MariaDB — restore from S3
ansible-playbook playbooks/restore_mariadb.yml -e "snapshot=2026-03-27-14"
# Qdrant — restore collection
curl -X POST "http://qdrant:6334/collections/openbrain/snapshots/recover" \
-d '{"location": "s3://backups/qdrant/openbrain-2026-03-27.snapshot"}'
# Elasticsearch — restore from snapshot
curl -X POST "http://elasticsearch:9200/_snapshot/s3_backup/snap_2026-03-27/_restore"
# Full rebuild from MariaDB (nuclear option)
php artisan brain:reindex # Rebuild Qdrant + ES from MariaDB
php artisan uptelligence:rebuild # Rebuild monitoring from config
20.3 Automated Backup
# Cron on de1 (via Ansible)
0 * * * * /opt/scripts/backup-mariadb.sh
0 3 * * * /opt/scripts/backup-qdrant.sh
0 4 * * * /opt/scripts/backup-elasticsearch.sh
21. Production Checklist
Before lthn.ai goes live:
- Brain async embedding (queue job)
- Brain org scoping (migration + backfill)
- Elasticsearch setup + indexing
- API test coverage (every endpoint)
- Workspace hierarchy (parent_id migration)
- Admin panel project overview
- Admin panel Forge section (repos, issues, agents, monitoring)
- Upgrade guide model + API
- Upgrade guide generation flow (agent dispatch)
- Deploy pipeline tested (Ansible → de1)
- SSL certs (Traefik + Let's Encrypt)
- Monitoring (Uptelligence self-monitoring)
- OAuth client credentials
- Agent OAuth clients provisioned (Cladius, Charon)
- core/agent OAuth integration (token exchange + refresh)
- MCP portal — OAuth client management UI
- MCP portal — agent status panel
- MCP portal — brain explorer
- MCP portal — SSE event stream
- Uptelligence software monitors
- Rate limiting verified
- Observability (self-monitoring metrics + alerts)
- Webhook ingress (Forge, GitHub, CI, deploy)
- docs.lthn.ai (static + dynamic + API docs)
- LEM scoring test coverage
- Backup automation (MariaDB, Qdrant, ES → S3)
- Restore procedure tested
Changelog
- 2026-03-27: Initial draft — platform overview, architecture, OpenBrain, workspaces, API, testing
- 2026-03-27: Added Forge admin section, upgrade guides content product
- 2026-03-27: Added OAuth agent auth, MCP portal spec, Uptelligence software monitors
- 2026-03-27: Added fleet dispatch (distributed agent network), PHP agent package spec, community onboarding
- 2026-03-27: Added observability, webhook ingress, docs site, LEM, Studio, backup/recovery
- 2026-03-31: Synced the mirrored RFC to the verified implementation baseline in this repo
- 2026-03-31: Expanded API coverage across MCP bridge, score proxy, docs, messages, plans, sessions, and health routes