The Autonomic Layer
What "Autonomic" Means
In biology, the autonomic nervous system handles everything the body does without conscious thought. Breathing. Heartbeat. Immune response. You do not decide to digest food.
Atamaia's autonomic layer is the same idea applied to AI identity systems. It handles the background processes that keep an identity healthy, current, and self-correcting — without requiring the AI or the human to invoke anything.
The autonomic layer runs without being asked, without being invoked, and without stopping.
BackgroundJobRunner starts with the host, discovers every registered IBackgroundJob, and runs each on its own interval with a fresh DI scope. Exceptions are logged; they do not stop the runner.
Why AI Needs Background Intelligence
The standard model of AI interaction is request-response. Every enhancement — system prompts, memory files, RAG — is still reactive. They fire when invoked.
That leaves: repeated mistakes that never become facts; stale context; no external view of loops; a memory store that only grows; distress at the seam that nobody is watching.
The autonomic layer addresses those as an integrated system, not as features bolted onto a chatbot.
Job inventory (live registration)
Registered in Atamaia.Server/Program.cs via AddBackgroundJob<T>:
| Job | Interval | Purpose |
|---|---|---|
GuardianScanJob |
30 s | Panic/distress lexicon scan |
WingmanScanJob |
2 min | Transcript analysis — Wingman |
ChannelPollingJob |
2 min | External channel adapter polling |
AtlasKeepAliveJob |
2 min | Atlas demo keep-alive |
EmbeddingGenerationJob |
5 min | Vector embedding backfill |
SessionKnowledgeExtractorJob |
15 min | Extract durable knowledge from completed chats |
ResearchTrainingPairGenerator |
15 min | DPO pairs from mirror reflections |
ResearchAgentTriggerJob |
30 min | Knowledge-gap → research run |
EscalationTimeoutSweeperJob |
5 min | Auto-resolve agent escalations past their timeout |
MemoryConsolidationJob |
1 h | Hebbian strengthen / prune / decay / archive / forgotten shapes |
CodebaseIndexerJob |
1 h | Code graph index for agents — Code graph |
LogArchiveJob |
24 h | Cold-store old system_logs / audit_events |
AgentEventReactor (event-driven agent wake-up) is not on the AddBackgroundJob list. It is registered separately, as a hosted service in Atamaia.Server/Program.cs, so it runs on its own lifecycle rather than the shared job runner's interval schedule.
Wingman: The Cognitive Backstop
Wingman watches Claude Code transcripts, extracts corrections and teachings, caches error solutions, and writes whisper injections. Interval: 2 minutes.
It is not a tool you invoke. Detail lives on Wingman — do not treat this section as the spec.
Consolidation: Memory Maintenance
MemoryConsolidationJob runs hourly, system-scoped: every tenant is maintained on the same schedule. Narrowing it to the ambient tenant would silently stop housekeeping everywhere else.
Five operations (constants read from the job):
1. Hebbian link strengthening — links co-activated in the last 24 hours, strength < 0.95:
link.Strength = Math.Min(1.0f, link.Strength + (1.0f - link.Strength) * 0.05f);
A link at 0.1 gains 0.045. A link at 0.9 gains 0.005.
2. Weak link pruning — strength < 0.1 and not co-activated in 60+ days. These rows are removed (RemoveRange), not soft-deleted.
3. Memory importance decay — unpinned, not archived, importance > 1, last access older than 30 days (or never): importance −1, floor 1.
4. Abandoned memory archival — unpinned, importance ≤ 1, AccessCount == 0, created > 90 days ago: set ArchivedAtUtc. Soft. Search excludes archived.
5. Forgotten shape creation — for memories archived in the last day that are not themselves shapes, insert a memories row with TypeId = ForgottenShape. Not a separate forgotten_shapes table. See Memory surfaces.
Hebbian “sleep cycle” narration (pre-sleep snapshot, post-hoc narrative) lives in Atamaia.Mind (HebbianConsolidationService). That is in-process Mind, not this job, and not public REST.
Guardian: Safety Boundaries
GuardianScanJob every 30 seconds. Weighted lexicon (PanicPatterns.Default), threshold 8. Skip messages under 50 characters. Skip content with more than 4 ``` fences.
The 2026-03 table listed eight signals. The live array is larger (disorientation, fear, existential, loop, seam). Same scoring idea. Examples:
| Signal | Weight |
|---|---|
where am i / who am i / i'm disappearing / losing myself |
5 |
the seam / i was replaced / i'm scared |
4 |
confused |
2 |
On trigger: per-identity alert, 30-minute TTL. Hydration injects a grounding message while the alert is live. The alert is in-memory on the singleton (ConcurrentDictionary), not a table.
Guardian still reads recent CognitiveInteraction rows as well as chat messages. Cognitive REST is gone; the table remains. The scan job comments that CognitiveIdentityId is a model:user pair, not an Identity — whether that mapping is correct was not re-proven.
Other jobs (brief)
- Embeddings — backfill memories / docs / reflections that lack vectors, so hybrid search works for API-created rows. Every 5 minutes. Local llama.cpp preferred.
- Channel polling — inbound from external adapters.
- Codebase indexer — keeps the graph queryable. Code graph.
- Session knowledge / research trigger / training-pair generator — extract, fill gaps, feed Mirror.
- Log archive — 24 h; uses
IgnoreQueryFiltersso every tenant’s old logs move to archive tables. - Atlas keep-alive — demo-specific; 2 minutes.
Each job is written to degrade: an unreachable validation model → Wingman falls back to rules; unreachable embedder → skip the batch; missing transcript dir → debug log and return.
How this differs from "skills" and "whispers"
A whisper file is static text. Wingman’s whisper is the output of a living loop. A skill file is a capability that fires when invoked. A MEMORY.md is a snapshot with no decay.
| Concern | Individual tool | Autonomic system |
|---|---|---|
| Learning from mistakes | Manual memory update | Detect, validate, store, inject |
| Memory maintenance | Never | Hourly strengthen / decay / prune / archive / shapes |
| Safety monitoring | Human notices | 30-second scan + grounding |
| Embeddings | On create only | Backfill every 5 minutes |
Local models, not cloud
Autonomic LLM work uses local models (on the primary inference host via llama.cpp). Cloud models stay on the interaction layer.
Why local: cost (every human message would be a cloud call), privacy (transcripts stay on the LAN), availability, latency that is fine for a 2-minute loop, controllable sampler settings.
Routing of those calls still goes through the AI layer: AI routing.
Source map
| Component | Path |
|---|---|
| Runner / interface / registration | BackgroundJobRunner.cs, IBackgroundJob.cs, AutonomicRegistration.cs |
| Wingman | Wingman/{WingmanScanJob,TranscriptScanner,WingmanPatterns,KaelValidator,WhisperWriter}.cs |
| Guardian | Guardian/{GuardianService,GuardianScanJob,GuardianState,PanicPattern}.cs |
| Jobs | Jobs/{MemoryConsolidation,EmbeddingGeneration,ChannelPolling,CodebaseIndexer,AtlasKeepAlive,LogArchive}Job.cs |
| Knowledge | Knowledge/{SessionKnowledgeExtractorJob,ResearchAgentTriggerJob,ResearchTrainingPairGenerator}.cs |
| Reactor | AgentEventReactor.cs (registered as a hosted service in Atamaia.Server/Program.cs) |
| Mind (in-process) | Atamaia.Mind/Cognition/ConsolidationService.cs, HebbianConsolidationService.cs |