# Paperclip AI Task Inbox Classification and Archive System: Complete Technical Guide

> Master the Paperclip AI task inbox classification and archive system. Learn how it ingests, classifies, assigns tasks, and archives runs with audit trails. Get the complete technical guide.

- Repository: [Paperclip/paperclip](https://github.com/paperclipai/paperclip)
- Tags: deep-dive
- Published: 2026-08-12

---

**The Paperclip AI task inbox classification and archive system ingests work items, classifies them by type, assigns them to agents via the Wakeup Coordinator, and archives completed runs with immutable audit trails.**

Paperclip is an open-source control plane that transforms collections of AI agents into fully-scoped "companies." At the heart of this architecture lies the **Task Inbox**—a ticket system that orchestrates how work flows from creation through classification, execution, and final archival. This deep dive explores the complete lifecycle, from [`packages/db/src/schema/issue.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/db/src/schema/issue.ts) to the WebSocket-powered real-time dashboard.

## How the Task Inbox Receives and Classifies Work

### Ingestion: Creating Tasks from Multiple Sources

The inbox accepts work through three primary channels: GitHub issues, incoming webhooks, or manual UI actions. Each creates a row in the issue table defined in [`packages/db/src/schema/issue.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/db/src/schema/issue.ts).

A task stores:

- `goal` — the objective description
- `project` — organizational grouping
- `parent` links — for hierarchical task trees

This structure supports complex workflows where large initiatives decompose into sub-tasks.

### Classification: Tagging by Type and Scope

Once ingested, the **Issue Service** applies a type tag. According to the Agent Runs specification, common classifications include:

- `bug` — defects requiring fixes
- `feature` — new capability development
- `routine` — scheduled, repetitive work

The classification logic is **company-scoped**, meaning each deployed "company" maintains independent label taxonomies. This isolation prevents cross-contamination between organizations sharing the same Paperclip instance.

Classification triggers automatically based on source patterns. For example, GitHub issues labeled `bug` in the source repository propagate that classification into the inbox.

## Agent Assignment and the Wakeup Coordinator

### From Classification to Execution Queue

When an **assigneeAgentId** is set—either manually or via automation rules—the **Wakeup Coordinator** enqueues an `assignment` source request in `agent_wakeup_requests`. This table functions as the central nervous system for agent activation.

The coordinator supports four wakeup sources per `doc/spec/agent-runs.md#8-8-wakeup-sources`:

| Source | Trigger Condition |
|--------|-----------------|
| `timer` | Scheduled intervals for periodic agents |
| `assignment` | Task explicitly assigned to agent |
| `on_demand` | Manual API trigger |
| `automation` | Rule-based reactive triggers |

### Atomic Checkout Prevents Double Work

The system guarantees **exactly-once execution** through database-level row locking. When the **Run Executor** claims a wakeup request, it performs an atomic update to `heartbeat_runs`. This transaction locks the row, ensuring no other executor can claim the same work—even under high concurrency.

## Heartbeat Execution and Session Management

### The Run Executor Pipeline

The **Run Executor**—defined in `doc/spec/agent-runs.md#6-architecture-overview`—handles the complete execution flow:

1. Claims the wakeup request from the queue
2. Creates a `heartbeat_runs` row to track this execution
3. Spawns the configured adapter (e.g., `claude_local` or `codex_local`)
4. Streams stdout/stderr to the **RunLogStore**
5. Persists outcome, token usage, cost, and `log_ref` upon completion

### Session Resume Across Heartbeats

Multi-step agent workflows require continuity. Paperclip solves this through **session persistence** in `agent_task_sessions`.

Each adapter type manages its own session identifier:

- `claude_local` — Claude CLI session ID
- `codex_local` — Codex CLI session ID

When a subsequent heartbeat arrives for the same `taskKey`, the executor retrieves the stored session and resumes execution context. This enables agents to maintain state across minutes, hours, or days of intermittent operation.

## The Archive System: Immutable Audit Trails

### What Gets Archived

Upon run completion, the archival process captures:

| Data | Storage Location | Purpose |
|------|----------------|---------|
| Run outcome | `heartbeat_runs.status` | Success/failure classification |
| Token usage | `heartbeat_runs.token_count` | Cost tracking and budgeting |
| Cost | `heartbeat_runs.cost_usd` | Financial accounting |
| Full log | `RunLogStore` via `log_ref` | Debug and compliance |
| Event timeline | `heartbeat_run_events` | Lightweight audit trail |

### RunLogStore: Pluggable Log Storage

The **RunLogStore** protocol defined in `doc/spec/agent-runs.md#6-3-run-log-storage-protocol` abstracts where full execution logs live. Implementations include:

- **Local filesystem** — default for development
- **S3-compatible object storage** — production scale
- **Custom adapters** — enterprise audit systems

The UI's **Archive** view renders tasks in read-only mode, preserving an immutable history even as active inboxes churn with new work.

## Real-Time Status Delivery

### WebSocket Event Architecture

The **Realtime Event Hub** at `/api/companies/:companyId/events/ws` pushes lightweight events to connected clients. Per `doc/spec/agent-runs.md#11-11-1-transport`, three core event types drive the UI:

- `heartbeat.run.status` — execution phase changes
- `agent.status.changed` — agent availability transitions
- `issue.updated` — task metadata modifications

This architecture eliminates polling. The inbox board reflects state changes within milliseconds of database commits.

## Company Isolation and Governance

### Multi-Tenant Safety

Every table in `packages/db/src/schema/` includes `company_id` as a partition key. A single Paperclip deployment safely hosts thousands of independent companies with complete data isolation.

### Governance Gates

Before any wakeup executes, the system enforces:

- **Approval workflows** — required sign-offs for sensitive task types
- **Budget hard-stops** — spend limits per agent or company
- **Audit logging** — immutable record of who triggered what

These controls transform raw agent execution into enterprise-grade operations.

## Practical Code Examples

### Starting a Local Development Instance

```bash
git clone https://github.com/paperclipai/paperclip.git
cd paperclip
pnpm install
pnpm dev         # API + UI on http://localhost:3100

```

### Creating a Classified Task via REST API

```bash
curl -X POST http://localhost:3100/api/companies/:companyId/issues \
  -H "Authorization: Bearer <board-token>" \
  -H "Content-Type: application/json" \
  -d '{
        "title": "Generate weekly report",
        "description": "Collect sales data and produce a PDF",
        "labels": ["routine","report"],
        "assigneeAgentId": "<agent-uuid>"
      }'

```

This request creates an inbox entry, classifies it as **routine**, and immediately enqueues an `assignment` wakeup for the target agent.

### Manually Triggering a Heartbeat

```bash
curl -X POST http://localhost:3100/api/agents/<agent-id>/wakeup \
  -H "Authorization: Bearer <board-token>" \
  -d '{"source":"on_demand","triggerDetail":"manual"}'

```

The endpoint enqueues an `on_demand` request; the executor will run the agent and update task status accordingly.

### Retrieving Archived Run Logs

```bash
curl http://localhost:3100/api/heartbeat-runs/<run-id>/log \
  -H "Authorization: Bearer <board-token>"

```

The API streams the raw log from the configured **RunLogStore** implementation.

### Subscribing to Live Events

```javascript
const ws = new WebSocket(
  "ws://localhost:3100/api/companies/<company-id>/events/ws?auth=<ws-token>"
);
ws.onmessage = e => console.log("Event:", JSON.parse(e.data));

```

Received events include structured payloads for immediate UI state updates.

## Key Source Files

| File | Role |
|------|------|
| [`packages/db/src/schema/issue.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/db/src/schema/issue.ts) | Inbox task entity definition |
| [`packages/db/src/schema/heartbeat_runs.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/db/src/schema/heartbeat_runs.ts) | Per-execution outcome persistence |
| [`packages/db/src/schema/agent_wakeup_requests.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/db/src/schema/agent_wakeup_requests.ts) | Wakeup Coordinator queue table |
| [`packages/db/src/schema/agent_task_sessions.ts`](https://github.com/paperclipai/paperclip/blob/main/packages/db/src/schema/agent_task_sessions.ts) | Resumable session storage |
| `packages/adapters/claude-local/*` | Claude CLI adapter implementation |
| `packages/adapters/codex-local/*` | Codex CLI adapter implementation |
| [`server/src/routes/agent.ts`](https://github.com/paperclipai/paperclip/blob/main/server/src/routes/agent.ts) | Wakeup and heartbeat API endpoints |
| [`ui/src/pages/Inbox.tsx`](https://github.com/paperclipai/paperclip/blob/main/ui/src/pages/Inbox.tsx) | React inbox, classification, and archive UI |
| [`doc/spec/agents-runtime.md`](https://github.com/paperclipai/paperclip/blob/main/doc/spec/agents-runtime.md) | Heartbeat model and session handling |
| [`doc/spec/agent-runs.md`](https://github.com/paperclipai/paperclip/blob/main/doc/spec/agent-runs.md) | Runs subsystem complete specification |

## Summary

- **The Task Inbox** in Paperclip AI functions as a company-scoped ticket system with full classification, assignment, and archival capabilities.
- **Classification** occurs at ingestion via the Issue Service, tagging tasks as `bug`, `feature`, `routine`, or custom types.
- **The Wakeup Coordinator** manages four trigger sources (`timer`, `assignment`, `on_demand`, `automation`) through `agent_wakeup_requests`.
- **Atomic checkout** via `heartbeat_runs` row locking guarantees exactly-once execution even under contention.
- **Session resume** in `agent_task_sessions` enables multi-step agent workflows to persist across intermittent heartbeats.
- **The Archive system** combines lightweight `heartbeat_run_events` with immutable full logs in the pluggable **RunLogStore**.
- **Real-time updates** flow through company-scoped WebSockets at `/api/companies/:companyId/events/ws`.
- All components respect **company isolation** via `company_id` partitioning and enforce **governance gates** before execution.

## Frequently Asked Questions

### How does Paperclip AI prevent duplicate task execution?

The **Run Executor** uses database-level atomic transactions when claiming work from `agent_wakeup_requests`. The claim operation updates `heartbeat_runs` with row-level locking, ensuring only one executor instance succeeds. Failed claims receive immediate feedback and skip to the next available task.

### Can agents resume work after being interrupted?

Yes. Through the **session resume** mechanism in `agent_task_sessions`, adapters persist their session identifiers (Claude CLI ID, Codex CLI ID, etc.) across heartbeats. When a task's `taskKey` recieves a new heartbeat, the executor retrieves the stored session and continues execution context rather than starting fresh.

### What storage options exist for archived run logs?

The **RunLogStore** protocol supports pluggable implementations. The default uses local filesystem storage suitable for development. Production deployments typically configure S3-compatible object storage. Organizations with strict compliance requirements can implement custom adapters targeting their audit systems.

### How does the inbox handle multiple companies on one deployment?

Every database table—including `issue`, `heartbeat_runs`, `agent_wakeup_requests`, and `agent_task_sessions`—includes `company_id` as a mandatory partition key. All queries filter by this scope, and the WebSocket hub at `/api/companies/:companyId/events/ws` isolates connections per company. This architecture enables secure multi-tenancy without separate infrastructure per tenant.