cambium ▸ docs/specs/spec-signal-protocol.md
updated 2026-03-27

Spec — Cambium Signal Protocol

Document Status

Draft V1

Purpose

This spec defines the nervous system of Cambium: how layers, agents, and subsystems communicate through structured signals rather than flat event logs.

The event backbone in the Core+Hypha PRD defines the infrastructure. This spec defines the biology on top of it — signal types, propagation rules, cascade chains, decay, and receptor contracts.

Without this, Cambium is a modular monolith with good logging. With this, it is an organism that responds, adapts, and coordinates through biochemical-grade communication.


Core Concept: Signals vs Events

An event is a record of something that happened. It is emitted, stored, and queryable.

A signal is an event that carries intent and triggers response. It has: - a type that maps to a biological communication class - a source (which layer or agent emitted it) - a affinity (which receptor types should bind to it) - a intensity (how urgent or severe) - a decay rate (how quickly it loses relevance) - a cascade potential (can it trigger secondary signals)

Every signal is also an event. Not every event is a signal.


Signal Classes

Signals are organized into biological communication classes.

1. Autonomic Signals

The heartbeat and vital signs of the platform.

Biological analog: Autonomic nervous system — involuntary, continuous, life-sustaining.

Examples: - pulse.heartbeat — periodic liveness check from each subsystem - pulse.subsystem_alive — response to heartbeat probe - pulse.subsystem_degraded — subsystem responding but unhealthy - pulse.subsystem_dead — no response within timeout - pulse.rhythm_irregular — heartbeat interval variance exceeds threshold

Properties: - Emitted on fixed intervals (configurable per subsystem, default 10s) - Never decay — absence of pulse IS the signal - Mandatory for all registered subsystems and agents - Monitored by Homeostasis layer

2. Stress Signals

System health and resource pressure.

Biological analog: Cortisol, adrenaline — hormonal stress response.

Examples: - stress.latency_spike — execution latency exceeds threshold - stress.queue_pressure — work queue depth exceeds threshold - stress.token_burn — token consumption rate exceeds budget - stress.error_rate — error frequency exceeds threshold - stress.context_pressure — context window utilization high - stress.resource_exhaustion — memory, CPU, or connection pool pressure

Properties: - Emitted by Health layer based on metric thresholds - Consumed by Hypha (for throttling/rerouting), Loom (for display), Immune (for pattern detection) - Decay: 5-minute half-life by default (configurable) - Can cascade: sustained stress → immune anomaly

3. Immune Signals

Anomaly detection and trust events.

Biological analog: Cytokines, interferons — immune cell communication.

Examples: - immune.anomaly_detected — behavioral pattern flagged - immune.quarantine_requested — recommendation to isolate a run or agent - immune.quarantine_enforced — isolation applied - immune.trust_degraded — agent or integration trust score reduced - immune.pattern_violation — execution deviates from expected pattern - immune.escalation_required — severity exceeds auto-response threshold

Properties: - Emitted by Immune layer - Consumed by Quorum (for governance escalation), Hypha (for pause/block), Loom (for visibility), Health (for stress correlation) - Decay: 30-minute half-life (configurable, severe signals persist longer) - Can cascade: immune escalation → quorum gate

4. Governance Signals

Approval, decision, and policy events.

Biological analog: Quorum sensing molecules (autoinducers) — collective threshold signaling.

Examples: - governance.approval_required — action gated pending review - governance.approval_granted — threshold met, proceed - governance.approval_denied — action rejected - governance.escalation_triggered — severity pushed to higher review - governance.policy_activated — policy bound to action - governance.override_applied — operator override with audit

Properties: - Emitted by Quorum layer - Consumed by Hypha (for gate/resume), Loom (for approval UI), Audit (for records) - No decay — governance decisions are permanent records - Can cascade: denial → reroute signal to Hypha

5. Coordination Signals

Work routing, agent availability, and stigmergic markers.

Biological analog: Pheromones, chemotaxis gradients — environmental coordination.

Examples: - coord.work_available — task ready for assignment - coord.agent_ready — agent available for work - coord.agent_busy — agent at capacity - coord.path_hot — execution path seeing heavy traffic - coord.path_cold — execution path underutilized - coord.resource_depleted — resource exhausted at this node - coord.resource_abundant — surplus available - coord.marker_placed — stigmergic marker deposited - coord.marker_decayed — stigmergic marker expired

Properties: - Emitted by agents, Hypha, and the stigmergic environment - Consumed by Hypha (for routing), agents (for self-selection), Loom (for topology display) - Decay: configurable per marker type, default 2-minute half-life - Can cascade: resource depletion → stress signal

6. Lifecycle Signals

Agent and workflow lifecycle transitions.

Biological analog: Growth factors, apoptosis signals — cell lifecycle regulation.

Examples: - lifecycle.agent_genesis — new agent instantiated from template - lifecycle.agent_activated — agent online and ready - lifecycle.agent_hibernating — agent dormant, preserving state - lifecycle.agent_decommissioned — agent removed from active pool - lifecycle.agent_composted — learnings extracted and fed back - lifecycle.workflow_created — new workflow definition - lifecycle.run_started — execution begun - lifecycle.run_completed — execution finished - lifecycle.checkpoint_created — seed layer snapshot

Properties: - Emitted by Genesis system, Hypha, Seed layer - Consumed by all layers as needed - No decay — lifecycle transitions are permanent records

7. Recovery Signals

Checkpoint, replay, and restoration events.

Biological analog: Wound healing cascade — hemostasis, inflammation, proliferation, remodeling.

Examples: - recovery.checkpoint_available — valid recovery point exists - recovery.replay_initiated — replay from checkpoint started - recovery.resume_initiated — run resuming from pause - recovery.rollback_initiated — reverting to prior state - recovery.restoration_complete — recovery finished - recovery.restoration_failed — recovery attempt unsuccessful

Properties: - Emitted by Seed layer - Consumed by Hypha (for execution), Loom (for operator visibility), Audit (for records) - No decay - Can cascade: restoration failure → immune anomaly


Signal Structure

Every signal follows this contract:

interface Signal {
  // Identity
  id: string;                    // unique signal ID
  type: string;                  // e.g., "stress.latency_spike"
  class: SignalClass;            // autonomic | stress | immune | governance | coordination | lifecycle | recovery

  // Source
  source_layer: string;          // which layer emitted (hypha, health, immune, quorum, seed, agent, stigmergy)
  source_id: string;             // specific emitter ID

  // Context
  workspace_id: string;
  workflow_run_id?: string;
  task_execution_id?: string;
  agent_id?: string;

  // Signal properties
  intensity: number;             // 0.0 - 1.0 (severity/urgency)
  decay_rate: number;            // half-life in seconds (0 = permanent)
  cascade_potential: boolean;    // can this trigger secondary signals
  payload: Record<string, any>; // type-specific data

  // Receptor targeting
  affinity: string[];            // receptor types that should bind (e.g., ["hypha.router", "loom.display", "quorum.gate"])

  // Timestamps
  emitted_at: string;            // ISO timestamp
  expires_at?: string;           // computed from decay_rate
}

Receptor Model

Each layer and agent declares its receptors — signal types it binds to and how it responds.

interface Receptor {
  id: string;
  owner: string;                 // layer or agent ID
  binds_to: string[];            // signal type patterns (e.g., "stress.*", "immune.escalation_required")
  response: ReceptorResponse;    // what happens on binding
  threshold?: number;            // minimum intensity to trigger (0.0 - 1.0)
  cooldown?: number;             // minimum ms between responses
}

interface ReceptorResponse {
  action: string;                // e.g., "throttle", "pause", "display", "escalate", "log"
  config: Record<string, any>;  // action-specific parameters
  emit_signal?: string;          // optional: cascade by emitting a new signal
}

Default Receptor Bindings

Layer Binds To Response
Hypha governance.approval_granted Resume gated execution
Hypha governance.approval_denied Reroute to fallback or fail
Hypha stress.* (intensity > 0.7) Throttle execution rate
Hypha immune.quarantine_enforced Pause affected runs
Hypha coord.agent_ready Consider for task dispatch
Hypha recovery.replay_initiated Execute from checkpoint
Health stress.* Update health state model
Health pulse.* Update liveness state
Health coord.resource_depleted Emit stress signal if systemic
Immune stress.* (sustained) Evaluate for anomaly pattern
Immune lifecycle.agent_genesis Monitor new agent behavior
Immune governance.override_applied Flag for review
Quorum immune.escalation_required Create approval gate
Quorum stress.* (intensity > 0.9) Emergency governance check
Seed lifecycle.run_started Evaluate checkpoint policy
Seed immune.quarantine_enforced Create emergency checkpoint
Loom * (all signals) Display in operator console

Cascade Chains

These are the hardwired critical paths — signals that MUST propagate regardless of subscription state.

Chain 1: Stress Escalation

stress.* (sustained > 5min) → immune.anomaly_detected → [if severity > 0.8] → governance.escalation_required → quorum gate

Chain 2: Immune Emergency

immune.quarantine_requested → [auto-approve if severity > 0.9] → immune.quarantine_enforced → hypha.pause + seed.emergency_checkpoint

Chain 3: Liveness Failure

pulse.subsystem_dead → stress.resource_exhaustion → immune.anomaly_detected → [if critical subsystem] → governance.escalation_required

Chain 4: Recovery Failure

recovery.restoration_failed → immune.anomaly_detected → stress.error_rate → [if repeated] → governance.escalation_required

Chain 5: Agent Distress

coord.resource_depleted (from agent) → stress.resource_exhaustion → health.state_change → hypha.reroute

Signal Propagation Model

Primary: Subscribe-Based

Secondary: Hardwired Cascades

Signal Bus Implementation


Heartbeat Protocol

The heartbeat is a first-class autonomic function, not a health metric.

How It Works

  1. A Pulse Monitor (part of Cambium Core) sends pulse.heartbeat probes to all registered subsystems and agents on a fixed interval
  2. Each subsystem/agent responds with pulse.subsystem_alive or pulse.subsystem_degraded
  3. No response within timeout → pulse.subsystem_dead emitted
  4. Irregular response intervals → pulse.rhythm_irregular emitted
  5. Health layer consumes pulse signals as primary liveness input

Configuration

interface HeartbeatConfig {
  interval_ms: number;           // default: 10000 (10s)
  timeout_ms: number;            // default: 5000 (5s)
  irregular_threshold_ms: number; // default: 3000 (3s variance)
  max_missed_before_dead: number; // default: 3
}

Subsystem Registration

Every layer and agent must register with the Pulse Monitor on startup and respond to heartbeat probes. This is not optional. An unregistered subsystem is invisible to the organism.


Signal Decay Model

Signals decay over time to prevent stale information from driving decisions.

effective_intensity = original_intensity * (0.5 ^ (elapsed_seconds / half_life_seconds))

Open Questions

  1. Should signal intensity be computed or declared by the emitter?
  2. What is the maximum cascade depth before circuit-breaking?
  3. Should agents be able to define custom signal types, or only emit from the predefined taxonomy?
  4. How should conflicting signals from multiple sources be resolved (e.g., two health assessments disagree)?