Infrastructure — Core Runtime Services

Core Runtime Services

The Infrastructure module provides the foundational runtime layer for OpenClaw: data store abstractions (SQLite and atomic JSON persistence), an in-memory caching layer with TTL-based eviction, a cron-style heartbeat scheduler, process supervision across Linux/macOS/Windows, a resilient outbound delivery pipeline, and system-level utilities including SSRF-safe networking and sandboxed filesystem operations.

3
Sub-Modules
572
TypeScript Files
~88K
Lines of Code
TS
Language

Persistence Resilience Scheduling Security

Architecture

The infrastructure layer sits beneath every other OpenClaw module. Configuration flows down from config/, while channels, agents, and commands depend on infra for I/O, scheduling, delivery, and process control. The three sub-modules (store, caching, scheduling) encapsulate the data persistence, in-memory state, and time-based execution concerns respectively.

flowchart LR
  subgraph Config["Configuration Layer"]
    CFG["OpenClawConfig"]
    ENV["Environment / .env"]
  end
  subgraph Infra["Infrastructure"]
    subgraph Store["store/"]
      JSON["Atomic JSON I/O"]
      SQLITE["node-sqlite"]
      AUTH["Device Auth Store"]
      QUEUE["Delivery Queue Storage"]
    end
    subgraph Cache["caching/"]
      MEM["In-Memory Maps"]
      TTL["TTL Eviction"]
      RATE["Rate Limiter"]
      DEDUP["Dedup Engine"]
    end
    subgraph Sched["scheduling/"]
      HB["Heartbeat Runner"]
      CRON["Active Hours Gate"]
      RESTART["Restart Controller"]
      RECOVERY["Queue Recovery"]
    end
  end
  subgraph Consumers["Consumer Modules"]
    CHAN["Channels"]
    AGENTS["Agents"]
    CMDS["Commands"]
    GW["Gateway"]
  end
  CFG --> Store
  ENV --> Store
  Store --> Cache
  Cache --> Sched
  Sched --> Consumers
  Store --> Consumers

Data Flow

A typical request flows through the infrastructure layer from configuration load through state persistence, message normalization, delivery queuing, and finally transport. The pipeline ensures atomic writes, retry on transient failures, and audit logging at each stage.

flowchart TD
  A["Config Load (io.ts)"] --> B["State Detection (state-migrations.ts)"]
  B --> C["Session Store Load"]
  C --> D["Approval Resolution (exec-approvals.ts)"]
  D --> E["Heartbeat Runner (heartbeat-runner.ts)"]
  E --> F["Message Normalization (outbound/payloads.ts)"]
  F --> G["Channel Adapter Resolution"]
  G --> H["Delivery Queue (delivery-queue-storage.ts)"]
  H --> I["Transport (APNS / Channel Plugins)"]
  I --> J["Session Cost Tracking"]
  J --> K["Update Check (update-runner.ts)"]

How Infrastructure Connects to Config & Commands

Infrastructure owns runtime I/O and scheduling. Config owns schema validation and materialization. Commands own user-facing workflows. The boundary between them is defined by typed interfaces: infra exposes loadJsonFile(), writeJsonAtomic(), acquireGatewayLock(), and scheduleGatewaySigusr1Restart(). Config calls into infra for file persistence; commands call into infra for process control and delivery.

sequenceDiagram
    participant CMD as Commands
    participant CFG as Config
    participant INFRA as Infrastructure
    participant FS as Filesystem
    CMD->>CFG: loadConfig()
    CFG->>INFRA: readJsonFile(configPath)
    INFRA->>FS: atomic read with lock
    FS-->>INFRA: JSON data
    INFRA-->>CFG: typed config object
    CFG-->>CMD: OpenClawConfig
    CMD->>INFRA: scheduleGatewaySigusr1Restart()
    INFRA->>INFRA: cooldown check (30s)
    INFRA-->>CMD: ScheduledRestart result

🚶 Step-by-Step Narrated Walkthrough

Follow a single outbound message delivery as it flows through the entire Infrastructure pipeline:

  1. Config Resolution — loadConfig() reads the YAML/JSON5 config file via atomic JSON I/O, applies environment substitution, and materializes the OpenClawConfig object.
  2. Session Lookup — The session store loads the conversation entry from disk using readJsonFile<SessionEntry>() with file locking to prevent concurrent writes.
  3. Approval Check — If the message triggers a command execution, exec-approvals.ts checks the allowlist patterns. If no match, it opens a JSONL socket to request user approval (30-minute timeout).
  4. Heartbeat Gate — The heartbeat runner checks active hours, evaluates the reason kind, and decides whether to send or skip based on channel visibility settings and interval configuration.
  5. Payload Normalization — outbound/payloads.ts converts the ReplyPayload into a NormalizedOutboundPayload, chunking text by markdown paragraphs if needed.
  6. Channel Resolution — outbound/channel-resolution.ts resolves the channel plugin adapter, validating capabilities (media support, threads, reactions).
  7. Queue Enqueue — enqueueDelivery() writes a JSON file to ${stateDir}/delivery-queue/ using atomic writes with PID-based temp files.
  8. Delivery Attempt — The delivery runner reads pending items, attempts send via the channel adapter, and on success calls ackDelivery() to remove the queue file.
  9. Retry on Failure — Transient errors trigger exponential backoff (5s → 25s → 120s → 600s). Permanent errors (bot blocked, chat not found) move the item to failed/.
  10. Cost Tracking — session-cost-usage.ts records token usage and calculates per-provider costs for the session transcript.
  11. Process Health — The gateway lock file is refreshed, system presence is broadcast via mDNS, and the update runner checks for new releases on the configured channel.

Key Types & Interfaces

TypeFilePurpose
ArchiveExtractLimitsarchive.tsSize/entry limits for secure archive extraction (zip/tar)
ExecApprovalRequestexec-approvals.tsPending approval with ID, payload, creation and expiry timestamps
ExecApprovalResolvedexec-approvals.tsResolution record: allow-once, allow-always, or deny
HeartbeatSummaryheartbeat-summary.tsResolved interval, reason, visibility, and enabled state
HeartbeatEventPayloadheartbeat-events.tsEvent record with status (sent/skipped/failed) and channel info
QueuedDeliverydelivery-queue-storage.tsQueued message with retry count, timestamps, and error tracking
RestartAttemptrestart.tsOS-level restart result (launchctl/systemd/schtasks)
ScheduledRestartrestart.tsSIGUSR1 restart with PID, delay, cooldown, and coalesce flag
GatewayLockHandlegateway-lock.tsProcess lock handle with path, config, and release function
SafeOpenResultfs-safe.tsValidated file handle with real path and stat after symlink checks
GatewayBonjourAdvertiseOptsbonjour.tsmDNS advertisement options for local network discovery
SystemPresencesystem-presence.tsHost identity with IP, version, platform, roles, and TTL

Configuration Parameters

ParameterDefaultDescription
OPENCLAW_DISABLE_BONJOURfalseDisable mDNS service advertisement on local network
DEFAULT_MAX_ARCHIVE_BYTES_ZIP256 MBMaximum compressed size for zip archive extraction
DEFAULT_MAX_ENTRIES50,000Maximum number of files and directories in an archive
DEFAULT_MAX_EXTRACTED_BYTES512 MBTotal decompressed size limit across all entries
DEFAULT_EXEC_APPROVAL_TIMEOUT_MS1,800,000Approval request timeout (30 minutes)
RESTART_COOLDOWN_MS30,000Minimum interval between gateway restarts
SIGUSR1_AUTH_GRACE_MS5,000Grace period for restart authorization tokens
MAX_DISPATCH_WRAPPER_DEPTH4Maximum nested dispatch depth to prevent infinite loops
OPENCLAW_HTTP_PROXY—HTTP proxy URL for outbound network requests
OPENCLAW_GATEWAY_CERT_PIN—TLS certificate pin (SHA-256) for gateway connections

Sub-Modules

store/

Data store abstractions and persistence layer. Atomic JSON I/O, SQLite runtime integration, device auth storage, delivery queue persistence, and safe file operations with symlink protection.

  • Atomic writes with UUID-based temp files
  • State migration detection for legacy paths
  • Sandboxed filesystem with O_NOFOLLOW

caching/

In-memory caching layer with TTL-based eviction, Symbol-based singletons for global state, fixed-window rate limiting, and deduplication utilities for heartbeat and system event payloads.

  • System presence cache (200 entries, 5-min TTL)
  • Session-scoped event queues (max 20)
  • Fixed-window rate limiter with backoff

scheduling/

Cron-style heartbeat scheduling, process supervision across three OS platforms, SIGUSR1-based graceful restarts with cooldown enforcement, and delivery queue recovery with exponential backoff.

  • Active-hours time gating for heartbeats
  • Supervisor-aware process respawn
  • Exponential backoff (5s → 600s) for retries

Code Overview

Atomic JSON Write Pattern

export async function writeJsonAtomic(
  filePath: string,
  value: unknown,
  options?: { mode?: number }
): Promise<void> {
  const tmpPath = `${filePath}.${crypto.randomUUID()}.tmp`;
  const data = JSON.stringify(value, null, 2);
  await fs.writeFile(tmpPath, data, { mode: options?.mode ?? 0o600 });
  await fs.rename(tmpPath, filePath);
}

Heartbeat Summary Resolution

export type HeartbeatSummary = {
  intervalMs: number;
  reason: HeartbeatReasonKind;
  visibility: HeartbeatVisibility;
  enabled: boolean;
};

export function resolveHeartbeatSummaryForAgent(
  agentId: string
): HeartbeatSummary {
  const enabled = isHeartbeatEnabledForAgent(agentId);
  const intervalMs = resolveHeartbeatIntervalMs(agentId, config);
  const reason = resolveHeartbeatReason(agentId);
  const visibility = resolveHeartbeatVisibility(agentId);
  return { intervalMs, reason, visibility, enabled };
}

Directory Map

Source tree for Infrastructure
src/infra/
├── outbound/                      ← Message delivery pipeline (50+ files)
│   ├── deliver.ts                 ← Delivery orchestration and chunking
│   ├── delivery-queue-storage.ts  ← Persistent queue with atomic writes
│   ├── delivery-queue-recovery.ts ← Retry with exponential backoff
│   ├── message.ts                 ← Send interface (direct & gateway)
│   ├── message-action-runner.ts   ← Interactive button/form callbacks
│   ├── target-resolver.ts         ← Recipient resolution and validation
│   ├── channel-resolution.ts      ← Plugin adapter loading
│   ├── payloads.ts                ← ReplyPayload normalization
│   └── session-context.ts         ← Session-scoped outbound context
├── net/                           ← Network security (15 files)
│   ├── fetch-guard.ts             ← SSRF-safe fetch with redirect limits
│   ├── ssrf.ts                    ← Private network blocking policy
│   ├── proxy-env.ts               ← Environment proxy configuration
│   └── hostname.ts                ← Hostname normalization
├── tls/                           ← TLS certificate handling
│   ├── gateway.ts                 ← TLS runtime config and self-signed gen
│   └── fingerprint.ts             ← SHA-256 cert fingerprinting
├── json-file.ts                   ← Synchronous JSON file I/O
├── json-files.ts                  ← Async atomic JSON with locks
├── node-sqlite.ts                 ← SQLite runtime wrapper
├── state-migrations.ts            ← Legacy state detection and migration
├── heartbeat-runner.ts            ← Periodic heartbeat orchestration
├── heartbeat-events.ts            ← Global heartbeat event bus
├── heartbeat-active-hours.ts      ← Time-based heartbeat gating
├── system-events.ts               ← Session-scoped ephemeral events
├── system-presence.ts             ← mDNS presence broadcasting
├── restart.ts                     ← SIGUSR1 restart controller
├── process-respawn.ts             ← Supervisor-aware respawn
├── gateway-lock.ts                ← PID-based single-instance lock
├── exec-approvals.ts              ← Command approval workflow
├── exec-approvals-allowlist.ts    ← Pattern matching for auto-approval
├── session-cost-usage.ts          ← Token usage and cost tracking
├── archive.ts                     ← Secure zip/tar extraction
├── fs-safe.ts                     ← Sandboxed file operations
├── retry.ts                       ← Exponential backoff retry engine
├── backoff.ts                     ← Backoff policy computation
├── errors.ts                      ← Error chain traversal and formatting
├── unhandled-rejections.ts        ← Global error classification
├── bonjour.ts                     ← mDNS service advertisement
├── push-apns.ts                   ← Apple Push Notification Service
├── device-pairing.ts              ← Device pairing and auth tokens
├── device-auth-store.ts           ← Device credential persistence
├── clawhub.ts                     ← Package registry client
└── env.ts                         ← Environment normalization