# Paperclip Heartbeat System Configuration Options: Complete Guide

> Explore Paperclip heartbeat system configuration options. Learn to enable the scheduler, set intervals, control concurrency, and track runtime state for agents and UI.

- Repository: [Paperclip/paperclip](https://github.com/paperclipai/paperclip)
- Tags: how-to-guide
- Published: 2026-08-18

---

**Paperclip's heartbeat system is configured through a typed JSON schema with options for enabling the scheduler, setting the wake-up interval, controlling concurrent runs, and tracking runtime state across agents and the UI.**

The heartbeat system in [paperclipai/paperclip](https://github.com/paperclipai/paperclip) drives periodic "wake-up" cycles that keep agents responsive and the internal scheduler healthy. Operators control this behavior through instance-level configuration options defined in the shared type system and exposed via API and UI. This guide covers every configuration field, its purpose, and how to modify it programmatically.

## Core Configuration Options

The heartbeat configuration lives on the **instance level** and synchronizes across the server, UI, and adapter utilities. All options are defined in [`packages/shared/src/types/heartbeat.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/shared/src/types/heartbeat.ts) and [`packages/shared/src/types/instance.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/shared/src/types/instance.ts).

### Static Configuration (Editable)

These settings persist and control baseline behavior:

| Option | Type | Default | Purpose |
|--------|------|---------|---------|
| `heartbeatEnabled` | `boolean` | `false` | Master toggle for the entire heartbeat scheduler. When `false`, no timer-driven runs queue. |
| `intervalSec` | `number` | `900` (15 min) | Seconds between automatic heartbeat runs. Lower values increase agent responsiveness at higher resource cost. |
| `schedulerActive` | `boolean` | `true` | Allows the UI to pause scheduling without disabling the system entirely. Distinguishes capability from current state. |
| `maxConcurrentRuns` | `number` | `2` | Internal ceiling on simultaneous heartbeat runs per company. Prevents cascade failures when runs stall. |

### Runtime State (System-Managed)

These fields track live execution and appear in API responses:

| Option | Type | Description |
|--------|------|-------------|
| `lastHeartbeatAt` | `Date \| null` | Timestamp of the most recent successful run. The UI displays this as a health indicator; the watchdog uses it to detect stalls. |
| `heartbeatRunId` | `string \| null` | Unique identifier attached to all logs, cost records, and task updates for attribution. |
| `runLivenessState` | `"queued" \| "running" \| "completed" \| "failed"` | Lifecycle state rendered as progress bars and status pills in the UI. |
| `heartbeatRunOutputSilence` | `object` | Tracks silent periods with `suspicionThresholdMs` and `criticalThresholdMs` thresholds. Surfaces warnings when no stdout/stderr appears. |
| `heartbeatInvocationSource` | `"timer" \| "manual" \| "api"` | Origin of the run: automatic timer, admin action, or external API. |
| `triggerDetail` | `object` | **WakeupTriggerDetail** payload containing the triggering issue and reason, propagated through the run-graph for tracing. |

## Where Configuration Lives

Paperclip's type-safe architecture ensures consistency across components:

- **[`packages/shared/src/types/heartbeat.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/shared/src/types/heartbeat.ts)** — Defines `HeartbeatRun`, `HeartbeatRunEvent`, and `InstanceSchedulerHeartbeatAgent` interfaces
- **[`packages/shared/src/types/instance.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/shared/src/types/instance.ts)** — Contains the `runtimeConfig.heartbeat` sub-object with editable fields
- **[`packages/shared/src/validators/runtime-config.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/shared/src/validators/runtime-config.ts)** — Validates incoming JSON against the schema

## Reading and Modifying Configuration

### Retrieve Current Settings

```typescript
import { heartbeatsApi } from '@/api/heartbeats';

const companyId = 'c123';
const agents = await heartbeatsApi.listInstanceSchedulerAgents();
const scheduler = agents.find(a => a.companyId === companyId);

console.log('Heartbeat enabled?', scheduler?.heartbeatEnabled);
console.log('Run interval (sec)', scheduler?.intervalSec);
console.log('Last successful run', scheduler?.lastHeartbeatAt);

```

The `listInstanceSchedulerAgents()` method returns all scheduler agents visible to the authenticated session, filtered by permissions.

### Enable and Tune the Scheduler

```typescript
await heartbeatsApi.updateInstanceSchedulerAgent(
  scheduler!.id,
  {
    heartbeatEnabled: true,
    intervalSec: 600,      // 10-minute wake-up cycle
    schedulerActive: true
  }
);

```

Changes take effect immediately. The server reconfigures its timer without requiring restart. Validation in [`runtime-config.ts`](https://github.com/paperclipai/paperclip/blob/main/runtime-config.ts) rejects invalid combinations (e.g., negative intervals).

### Inspect Live Run State

```typescript
const runs = await heartbeatsApi.liveRunsForCompany(companyId);
const activeRun = runs.find(r => r.status === 'running');

if (activeRun) {
  console.log('Run ID:', activeRun.heartbeatRunId);
  console.log('Liveness:', activeRun.runLivenessState);
  console.log('Invoked via:', activeRun.heartbeatInvocationSource);
  
  if (activeRun.heartbeatRunOutputSilence) {
    console.log('Silence warnings:', activeRun.heartbeatRunOutputSilence.level);
  }
}

```

The `liveRunsForCompany()` endpoint returns full runtime state including silence detection data used for operational monitoring.

## Triggering Runs Manually

For testing or ad-hoc agent activation, bypass the timer:

```typescript
await heartbeatsApi.triggerRun({
  companyId,
  issueId: 'PAP-101',      // Optional: focus on specific issue
  source: 'manual',         // 'timer' | 'manual' | 'api'
  triggerDetail: {
    reason: 'deployment-verification',
    requestedBy: 'admin-007'
  }
});

```

Manual triggers respect `maxConcurrentRuns` and populate the same `heartbeatRunId` tracking as automatic runs.

## UI Administration

Administrators configure heartbeat settings in **[`ui/src/pages/InstanceSettings.tsx`](https://github.com/paperclipai/paperclip/blob/main/ui/src/pages/InstanceSettings.tsx)**, which:

- Reads current values via `heartbeatsApi.listInstanceSchedulerAgents()`
- Renders status pills from `runLivenessState`
- Writes changes through `updateInstanceSchedulerAgent()`
- Displays `lastHeartbeatAt` as relative health indicators

The UI separates `heartbeatEnabled` (system capability) from `schedulerActive` (operational state), allowing emergency pauses without configuration loss.

## Summary

- **Enablement control**: `heartbeatEnabled` is the master switch; `schedulerActive` allows runtime pausing
- **Frequency tuning**: `intervalSec` sets wake-up cadence in seconds (default 900)
- **Resource protection**: `maxConcurrentRuns` caps parallel execution at 2
- **Observability**: Runtime fields (`heartbeatRunId`, `runLivenessState`, `heartbeatRunOutputSilence`) provide full traceability
- **Type safety**: All options validated in [`packages/shared/src/validators/runtime-config.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/shared/src/validators/runtime-config.ts)

## Frequently Asked Questions

### What happens when heartbeatEnabled is set to false?

The scheduler stops queuing timer-driven runs entirely. Existing runs complete, but no new automatic cycles begin. Manual triggers via `triggerRun()` still function, allowing ad-hoc agent execution without re-enabling the system.

### How does maxConcurrentRuns protect against resource exhaustion?

When a heartbeat run stalls (infinite loop, blocked I/O), additional timer ticks would normally queue overlapping runs. `maxConcurrentRuns: 2` prevents more than two simultaneous runs per company, containing the blast radius until the watchdog detects the stall via `lastHeartbeatAt` age.

### Can I change the interval without restarting Paperclip?

Yes. The `updateInstanceSchedulerAgent()` API applies `intervalSec` changes immediately. The server recalculates the next wake-up time from the current moment, not the previous schedule. This is implemented in the server-side scheduler without process restart.

### What is the difference between heartbeatRunOutputSilence and runLivenessState?

`runLivenessState` tracks coarse execution phase (`queued` → `running` → `completed`/`failed`). `heartbeatRunOutputSilence` monitors fine-grained I/O health during the `running` phase, detecting when agents produce no output for configured thresholds. A run can be `running` while flagged for silence, triggering UI warnings before eventual failure.