Arquitectura y conceptos fundamentales
La base de todo: el modelo de datos
Antes de crear tu primera empresa o configurar tu primer agente, necesitas entender cómo Paperclip organiza la información. El modelo de datos no es un detalle técnico secundario: define la gramática del sistema. Una vez que entiendas estas cinco entidades y cómo se relacionan, todo lo demás tiene sentido natural.
Las cinco entidades fundamentales de Paperclip son:
- Company — La entidad contenedora principal
- Agent — Cualquier bot que hace trabajo
- Task — Una unidad de trabajo trazada
- Heartbeat — El schedule de ejecución de un agente
- Budget — El control de costos por agente
Hay también entidades de soporte: Initiative (un goal de empresa), Skill (conocimiento inyectable en runtime), AuditLog (registro inmutable de eventos), y Adapter (la configuración técnica para invocar al agente).
Company: el contenedor de todo
Una Company en Paperclip no es solo un nombre. Es una unidad de aislamiento completa: todos los agentes, tareas, tickets, y datos de una empresa están encapsulados dentro de ella y son inaccesibles desde otras empresas en el mismo deployment.
classDiagram
class Company {
+string id
+string name
+string description
+string industry
+string[] goals
+Initiative[] initiatives
+Agent[] agents
+Budget companyBudget
+BoardConfig board
+DateTime createdAt
}
class Initiative {
+string id
+string title
+string description
+string status
+Task[] tasks
+string ownerId
}
class BoardConfig {
+string memberName
+string email
+string supervisionLevel
+string[] approvalRequired
}
Company "1" --> "*" Initiative
Company "1" --> "1" BoardConfig
Company "1" --> "*" Agent
El campo goals son strings de texto libre que describen hacia dónde va la empresa. A diferencia de las Initiatives (que tienen estados, tareas, y dueños), los goals son intenciones de alto nivel. Ejemplo: "Crecer el MRR a $50k antes de Q4 2026" o "Tener cobertura de tests por encima del 80% en todos los servicios críticos".
Las Initiatives son más estructuradas: tienen un título, descripción, estado (planned, in_progress, completed), y están vinculadas a tareas concretas. Puedes pensar en los goals como la visión y en las initiatives como la estrategia.
Agent: la entidad que hace trabajo
Un Agent en Paperclip representa cualquier bot o proceso que puede recibir tareas y ejecutarlas. Lo importante es que Paperclip es agnóstico al tipo de agente: puede ser Claude Code, Codex, un proceso bash, una llamada HTTP a cualquier API externa, o cualquier combinación.
classDiagram
class Agent {
+string id
+string name
+string role
+string description
+string companyId
+AdapterType adapterType
+AdapterConfig adapterConfig
+AgentStatus status
+string managerId
+string[] reportIds
+Budget budget
+Skill[] skills
+Heartbeat[] heartbeats
+DateTime createdAt
}
class AdapterConfig {
+string type
+string command
+Record env
+number timeout
+string workDir
}
class AgentStatus {
<<enumeration>>
idle
running
paused
budget_exhausted
error
}
Agent "1" --> "1" AdapterConfig
Agent "1" --> "1" AgentStatus
Agent "1" --> "*" Heartbeat
Los campos más importantes de un agente:
- role: Describe la función del agente en la empresa (CEO, CTO, Ingeniero Senior, Agente de Soporte). No es solo un label: se inyecta como contexto en cada ejecución.
- managerId: El ID del agente que supervisa a este agente. Define la jerarquía del org chart.
- reportIds: Los IDs de los agentes que reportan a este agente.
- adapterType: Cómo se invoca al agente (openclaw, claude_code, codex_local, http, process).
- status: El estado actual del agente. Un agente en
budget_exhaustedno puede tomar nuevas tareas hasta que se renueve el presupuesto.
Task: la unidad de trabajo trazada
Una Task (o Ticket) es el corazón operacional de Paperclip. Todo trabajo que hace un agente está representado como una task. No existe trabajo no trazado en Paperclip: si un agente ejecutó algo, hay un ticket.
classDiagram
class Task {
+string id
+string title
+string description
+string companyId
+TaskStatus status
+TaskPriority priority
+string assigneeId
+string creatorId
+string parentId
+Task[] subtasks
+AuditLog[] auditLog
+ToolCall[] toolCalls
+string[] mentions
+DateTime checkedOutAt
+string checkedOutBy
+DateTime completedAt
}
class TaskStatus {
<<enumeration>>
backlog
todo
in_progress
review
done
cancelled
}
class AuditLog {
+string id
+string taskId
+string agentId
+string action
+Record payload
+DateTime timestamp
}
class ToolCall {
+string id
+string taskId
+string toolName
+Record input
+Record output
+number durationMs
+number costUsd
+DateTime timestamp
}
Task "1" --> "*" Task : subtasks
Task "1" --> "*" AuditLog
Task "1" --> "*" ToolCall
El campo checkedOutAt y checkedOutBy implementan el mecanismo de checkout atómico. Cuando un agente va a trabajar en una tarea, ejecuta un checkout optimista. Si el checkout tiene éxito (nadie más la tenía tomada), el agente procede. Si falla, la tarea ya está siendo procesada por otro agente.
El auditLog es inmutable: solo se pueden añadir entradas, nunca modificar o eliminar las existentes. Esto garantiza la integridad del historial.
Los toolCalls registran cada llamada a herramientas que el agente hizo durante la ejecución: qué herramienta usó, con qué parámetros, qué obtuvo de respuesta, cuánto tardó, y cuánto costó en dólares.
Heartbeat: el reloj del agente
Un Heartbeat define cuándo se despierta un agente. Es la pieza que transforma un agente pasivo (que solo responde cuando se le invoca) en un agente activo (que trabaja según un schedule propio).
classDiagram
class Heartbeat {
+string id
+string agentId
+string schedule
+HeartbeatType type
+string payload
+HeartbeatStatus lastStatus
+DateTime lastRun
+DateTime nextRun
+number runCount
+number failureCount
+boolean enabled
}
class HeartbeatType {
<<enumeration>>
cron
event
manual
}
class HeartbeatStatus {
<<enumeration>>
success
failure
running
skipped
}
Heartbeat "1" --> "1" HeartbeatType
Heartbeat "1" --> "1" HeartbeatStatus
El campo schedule usa sintaxis cron estándar para los heartbeats de tipo cron:
# Cada 5 minutos
*/5 * * * *
# Cada lunes a las 9am
0 9 * * 1
# El primer día de cada mes a medianoche
0 0 1 * *
# Cada hora, de lunes a viernes
0 * * * 1-5
Los heartbeats de tipo event se disparan cuando ocurre algo en el sistema: una nueva tarea asignada al agente, una mención (@mention), una tarea de alta prioridad entrando en el backlog, etc.
El campo payload define qué contexto inicial se le entrega al agente cuando se despierta. Puede ser un texto libre o un JSON con instrucciones específicas para esa ejecución.
Budget: el control de costos
El Budget es la entidad que hace posible la gobernanza financiera. Cada agente tiene su propio presupuesto mensual, y el sistema rastrea cada gasto en tiempo real.
classDiagram
class Budget {
+string id
+string agentId
+number monthlyLimitUsd
+number spentThisMonthUsd
+number remainingUsd
+BudgetPeriod period
+BudgetStatus status
+DateTime periodStartDate
+DateTime periodEndDate
+BudgetTransaction[] transactions
}
class BudgetTransaction {
+string id
+string budgetId
+string taskId
+string toolCallId
+number amountUsd
+string description
+DateTime timestamp
}
class BudgetStatus {
<<enumeration>>
active
warning
exhausted
suspended
}
Budget "1" --> "*" BudgetTransaction
Cuando un agente realiza una llamada a un LLM (a través de su adapter), el costo se calcula automáticamente y se registra como una transacción del budget. Paperclip usa los precios oficiales de cada proveedor para el cálculo.
Cuando el spentThisMonthUsd supera el 80% del monthlyLimitUsd, el status pasa a warning y el Board recibe una notificación. Cuando supera el 100%, el status pasa a exhausted y el agente deja de aceptar nuevas tareas.
Al inicio de cada mes calendario, los contadores se reinician automáticamente.
El flujo completo: de goals a ejecución
Entender cada entidad por separado es necesario pero no suficiente. Lo que hace poderoso a Paperclip es cómo estas entidades trabajan juntas para llevar el contexto desde los goals de la empresa hasta la ejecución concreta del agente.
sequenceDiagram
participant Board as Board (Tú)
participant Sys as Sistema Paperclip
participant CEO as Agente CEO
participant CTO as Agente CTO
participant Eng as Agente Ingeniero
Board->>Sys: Define goals de la Company
Sys->>CEO: Heartbeat (daily, 9am)
CEO->>Sys: Revisar goals y tareas pendientes
CEO->>Sys: Crear Initiative "Migración a TypeScript"
CEO->>Sys: Crear Task "Planificar migración" → asignar a CTO
Sys->>CTO: Heartbeat (on: task_assigned)
CTO->>Sys: Checkout Task "Planificar migración"
CTO->>Sys: Crear subtareas para el equipo
CTO->>Eng: Asignar Task "Migrar módulo auth"
Sys->>Eng: Heartbeat (on: task_assigned)
Eng->>Sys: Checkout Task "Migrar módulo auth"
Eng->>Sys: Ejecutar tool calls (leer código, escribir código, tests)
Eng->>Sys: Completar task + report
Sys->>CTO: Notificar task completada
CTO->>Sys: Review y aprobar
Sys->>Board: Resumen diario de progreso
Este flujo tiene varias propiedades importantes:
El contexto fluye hacia abajo. Los goals se convierten en initiatives, las initiatives en tareas, las tareas en subtareas. Cada nivel hereda el contexto del nivel superior. Cuando el agente Ingeniero trabaja en “Migrar módulo auth”, sabe que es parte de la Initiative “Migración a TypeScript” y entiende el objetivo final.
El reporte fluye hacia arriba. Los completions, los reportes, los bloqueos: todo sube por la jerarquía. El CTO sabe cuándo el ingeniero termina su tarea. El CEO sabe cuándo el CTO cierra una initiative. El Board recibe resúmenes de alto nivel.
Los checkouts garantizan atomicidad. En el diagrama, el paso “Checkout Task” es crítico. Antes de que el CTO y el Ingeniero empiecen a trabajar, checkean la tarea. Si hubiera otro agente intentando tomar la misma tarea simultáneamente, el checkout garantiza que solo uno lo logra.
El ciclo de vida completo de una tarea
Una tarea en Paperclip pasa por estados bien definidos:
stateDiagram-v2
[*] --> backlog : Creada
backlog --> todo : Priorizada
todo --> in_progress : Checkout por agente
in_progress --> review : Agente completa trabajo
review --> done : Aprobado
review --> in_progress : Revisión requiere cambios
done --> [*]
backlog --> cancelled : Board cancela
todo --> cancelled : Board cancela
in_progress --> cancelled : Board cancela / agente paused
in_progress --> backlog : Checkout liberado (timeout)
backlog: La tarea existe pero no tiene prioridad ni asignación activa. El CEO o manager la puede priorizar cuando lo decida.
todo: La tarea está priorizada y lista para ser tomada por el agente asignado. El próximo heartbeat del agente la recogerá.
in_progress: Un agente tiene el checkout activo. Está trabajando en ella. Si el agente falla, el checkout expira después del timeout configurado (por defecto 1 hora) y la tarea vuelve a todo.
review: El agente terminó el trabajo y lo marcó como listo para revisión. Dependiendo de la configuración, la revisión la puede hacer el manager-agente o el Board directamente.
done: La tarea está completamente cerrada. El audit log y los tool calls están inmutables desde este punto.
cancelled: El Board o un manager canceló la tarea. El historial de lo que se hizo hasta ese punto se preserva.
Fat payload vs thin ping: dos estrategias de heartbeat
Cuando un heartbeat se dispara, Paperclip invoca al agente con cierto contexto inicial. Hay dos filosofías para diseñar ese contexto:
Fat payload (payload rico): El heartbeat incluye toda la información relevante que el agente necesita para empezar a trabajar inmediatamente. El agente no necesita hacer queries adicionales al sistema para entender qué tiene que hacer.
{
"type": "daily_review",
"company_goals": ["Crecer MRR a $50k", "Reducir churn"],
"pending_tasks": [
{"id": "t_123", "title": "Migrar módulo auth", "priority": "high"},
{"id": "t_124", "title": "Añadir tests de integración", "priority": "medium"}
],
"budget_remaining": 45.30,
"open_blockers": []
}
Ventajas: Menos llamadas a la API → menor latencia → menor costo. El agente tiene todo lo que necesita en un solo payload.
Desventajas: El payload puede quedar desactualizado si el heartbeat se genera con antelación. Si entre la generación del payload y la ejecución del agente alguien crea 5 nuevas tareas, el agente no las ve.
Thin ping (ping mínimo): El heartbeat simplemente despierta al agente con un mensaje mínimo. El agente es responsable de consultar el sistema para obtener el estado actual.
{
"type": "wake",
"reason": "scheduled_daily_review",
"timestamp": "2026-04-05T09:00:00Z"
}
Ventajas: El agente siempre trabaja con información actualizada. Más robusto ante cambios de estado.
Desventajas: Requiere que el agente haga más llamadas al sistema, lo que aumenta el costo de tokens y la latencia.
La recomendación general: usar fat payload para agentes de análisis y reporte (donde la consistencia del snapshot importa) y thin ping para agentes de ejecución (donde la actualidad de la información es crítica).
Cómo fluye el contexto hacia el agente
Cuando Paperclip invoca al agente (a través del adapter correspondiente), construye un contexto de sistema que combina:
graph TD
subgraph "Contexto del Sistema"
A[Company description + goals]
B[Agent role + description]
C[Skills inyectadas en runtime]
D[Historial reciente de tareas]
E[Org chart del agente]
end
subgraph "Contexto de la Invocación"
F[Heartbeat payload]
G[Tarea asignada si aplica]
H[@mentions recibidas]
end
A --> Z[Prompt del agente]
B --> Z
C --> Z
D --> Z
E --> Z
F --> Z
G --> Z
H --> Z
Este contexto se construye de forma determinista y cacheada donde es posible, para minimizar los tokens de contexto. La Company description y los goals raramente cambian, por lo que se cachean. Las tareas asignadas y los mentions se agregan frescos en cada invocación.
Las skills: conocimiento inyectable en runtime
Las Skills son archivos Markdown que se incluyen en el contexto del agente cuando se le invoca. Son el mecanismo principal para darle a un agente conocimiento específico sin hardcodearlo en su configuración.
graph LR
SM[Skills Manager] --> |selecciona skills relevantes| Builder
Agent[Configuración del Agente] --> |skills asignadas| Builder
Builder[Context Builder] --> |construye| Ctx[Contexto Final]
Ctx --> |invoca| Adapter
Adapter --> |ejecuta| ExtAgent[Agente Externo]
Una skill puede ser:
- Procedural: “Para hacer un deploy, sigue estos pasos: 1) verificar tests, 2) tag la versión, 3) push al repo…”
- Contextual: “La arquitectura de nuestro sistema usa hexagonal con puertos y adaptadores. Los casos de uso viven en src/application/…”
- Normativa: “Todas las respuestas al cliente deben seguir este tono: empático, directo, sin jerga técnica…”
- Referencial: “La documentación de la API interna está en api.internal.example.com/docs…”
Las skills se pueden asignar a un agente específico, a todos los agentes de un rol, o a todos los agentes de la empresa. También se pueden activar condicionalmente según el tipo de tarea.
Adapters: el puente entre Paperclip y los agentes externos
El Adapter es la pieza técnica que sabe cómo invocar a un agente externo específico. Paperclip incluye adapters para los casos más comunes, y el sistema es extensible para adapters personalizados.
graph TD
PC[Paperclip Core] -->|invoca| Dispatch[Adapter Dispatcher]
Dispatch -->|tipo: openclaw| OC[OpenClaw Adapter]
Dispatch -->|tipo: claude_code| CC[Claude Code Adapter]
Dispatch -->|tipo: codex_local| CDX[Codex Local Adapter]
Dispatch -->|tipo: http| HTTP[HTTP Adapter]
Dispatch -->|tipo: process| PROC[Process/Bash Adapter]
OC --> ExtOC[OpenClaw CLI]
CC --> ExtCC[Claude Code CLI]
CDX --> ExtCDX[Codex Local]
HTTP --> ExtHTTP[API Endpoint]
PROC --> ExtPROC[Shell Command]
Cada adapter implementa la misma interfaz:
interface Adapter {
invoke(context: AgentContext): Promise<AgentResult>
estimateCost(context: AgentContext): Promise<number>
isAvailable(): Promise<boolean>
}
El adapter HTTP es especialmente poderoso porque permite integrar cualquier servicio externo que tenga una API REST. Si tienes un sistema propietario de agentes, solo necesitas exponer un endpoint que acepte el contexto de Paperclip y devuelva el resultado.
El audit log: la memoria institucional inmutable
Toda acción en Paperclip queda registrada en el audit log. No solo las acciones de agentes: también las acciones del Board (pausas, overrides, aprobaciones), las transiciones de estado de las tareas, y los cambios de configuración.
El audit log tiene tres propiedades garantizadas por el sistema:
- Inmutabilidad: Las entradas del audit log solo se pueden añadir, nunca modificar o eliminar. Esto está enforced a nivel de base de datos.
- Completitud: Toda acción visible en la UI tiene una entrada correspondiente en el audit log. No hay “modo silencioso” donde algo ocurra sin registrarse.
- Estructura consistente: Cada entrada tiene: timestamp, actorId (quién lo hizo), action (qué se hizo), targetId (sobre qué entidad), payload (los detalles específicos).
Esto convierte al audit log en la fuente de verdad del sistema. Si hay un desacuerdo sobre qué pasó, el audit log resuelve la disputa.
Resumen del modelo de datos
erDiagram
Company ||--o{ Agent : "tiene"
Company ||--o{ Initiative : "tiene"
Company ||--|| BoardConfig : "tiene"
Agent ||--o{ Heartbeat : "tiene"
Agent ||--|| Budget : "tiene"
Agent ||--o{ Skill : "usa"
Agent ||--|| AdapterConfig : "tiene"
Agent ||--o{ Agent : "manager/reports"
Initiative ||--o{ Task : "contiene"
Task ||--o{ Task : "subtareas"
Task ||--o{ AuditLog : "registra"
Task ||--o{ ToolCall : "registra"
Budget ||--o{ BudgetTransaction : "registra"
ToolCall ||--|| BudgetTransaction : "genera"
Con este modelo de datos en mente, el próximo paso es crear tu primera empresa y ver cómo todos estos conceptos cobran vida en la UI de Paperclip.