Files
oikos/archive/knowledge/infrastructure/oikos-check-lifecycle.md
dtoro 20adb89650
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled
v0.18.0: MCP entity-graph CRUD, lifecycle validation, curl -o /dev/null fix
- create_entity, set_entity_state, end_relationship MCP tools
- update_entity_attributes now triggers check derivation via EnsureEntityChecks
- shared db.EnsureEntityChecks + db.ValidateTransition hooks (HTTP + MCP parity)
- curl -o /dev/null now classified read_only (was config_mutation)
- db.ErrTransitionInvalid sentinel for HTTP error-type accuracy
- SOUL.md: capability escalation, self-grounding, exploration budget rules
- Runbook: oikos check lifecycle for agent self-knowledge
2026-08-04 08:52:08 +02:00

4.8 KiB

Oikos check lifecycle — how monitoring works

This runbook covers how Oikos health checks are derived, created, and wired so an agent (Nomos) doesn't reverse-engineer source when asked to add monitoring to an entity — the problem that stranded session 23da10db (2026-08-03).

Concepts

  • check_defs (scheduler config, table check_defs): the row the scheduler reads to know what to probe and when. One per check instance.
  • check entity (type check, slug check:<kind>:<target>:<n>): the knowledge-graph entity for that check. It carries attributes (check_type, target, port, …) and checks edges to the probed target.
  • monitoring spec on an entity type (entity_types.monitoring_spec): the default list of check kinds (e.g. [http, process] for service).
    • Per-entity override: set monitoring in the entity's attributes — "none" for zero checks, ["http"] to replace the type defaults.
  • checkdefaults.Ensure (internal/checkdefaults/defaults.go): the function that reads the monitoring spec, resolves host/port/URL from attributes + relationships, and writes check_defs rows. Idempotent.

When checks are derived

checkdefaults.Ensure runs in three situations (as of v0.17.1+):

  1. Seed/deploy ingestinternal/db/seed.go:231. Every entity gets its default checks once on initial ingest.
  2. HTTP POST /api/v1/entities (create)ensureDefaultChecks at internal/httpapi/impl.go:1012. Creating an entity via the REST API derives its checks in the same transaction.
  3. HTTP PATCH /api/v1/entities (patch)ensureDefaultChecks at internal/httpapi/impl.go:1280. Changing an entity's attributes (especially monitoring) via the REST API regenerates its checks.
  4. MCP create_entity — SAME hook. Creating an entity via the MCP tool derives checks. (Added 2026-08-03; previously MCP had no create.)
  5. MCP update_entity_attributes — SAME hook. Changing an entity's monitoring attribute via MCP now regenerates checks. (Added 2026-08-03; previously MCP updates silently skipped check derivation — the exact bug that stranded the haos session.)

Check slug grammar

check:<kind>:<target-type>:<target-name>:<n>

Examples: check:http:service:jellyfin:0, check:vm-status:vm:haos:0, check:cert-expiry:cert:house.hubris.network:0.

Adding monitoring to an entity

If the entity already exists:

update_entity_attributes(slug="service:haos", attributes={"monitoring":["http"]})

This regenerates checks via checkdefaults.Ensure. The result message tells you how many checks were derived and whether any kinds were skipped (and why).

If the entity does not exist yet (a new check, ingress, cert, etc.):

create_entity(type="check", name="HAOS http check",
  slug="check:http:service:haos:0",
  attributes={"check_type":"http:service","target":"service:haos","port":"8123"})

This creates the entity AND derives its check_defs. Same for a new ingress (type=ingress, monitoring [http]) or cert (type=cert, monitoring [cert-expiry]).

To remove monitoring: set monitoring:["none"] or transition the entity to a terminal lifecycle state (set_entity_statedeprecated/destroyed).

Caveats

  • A service without a url attribute AND without a probe_unit gets no process check (the http check covers liveness; the process check would be redundant without an opt-in probe_unit). The skip is logged.
  • A service whose address comes from a hosts edge may produce no checks on initial create because the edge doesn't exist yet — the next inventory ingest (or a later update_entity_attributes after the edge is created) fills it in.
  • A not found error from update_entity_attributes means the entity doesn't exist — use create_entity instead.
  • check_defs has target columns (target_id, target_type). A check entity needs a checks relationship (create_relationship(source=check:…, target=service:…, type="checks")) so the scheduler can resolve what to probe. create_entity derives the check_def; create_relationship links the check entity to its target in the graph.
  • internal/checkdefaults/defaults.goEnsure, Target, LogResult
  • internal/httpapi/default_checks.goensureDefaultChecks (HTTP hook)
  • internal/db/checks.godb.EnsureEntityChecks (shared hook)
  • internal/db/seed.go — seed-time check derivation
  • internal/mcp/tools.gocreate_entity, update_entity_attributes

Revision history

  • 2026-08-03: Created after session 23da10db stranded for lack of entity- creation tool and unawareness of check-derivation triggers. Covers the MCP create_entity + update_entity_attributes regen paths added same day.