The self-referential foreign key on the agents table, cascading behavior on agent deletion, what it enables for task delegation routing, and querying the org tree recursively.
How reports_to influences approval routing and escalation paths, and how to set up a manager who reviews their team's work.
When an agent encounters a task that exceeds its authority (defined in approval policies), Paperclip routes the approval request to its manager — the agent in reports_to.
Worker Agent → creates approval request
↓ (if worker has no human approver configured)
Manager Agent → reviews and approves or rejects
↓ (if manager also has no authority)
CEO Agent → final human-equivalent authority
The escalation chain follows reports_to links until it finds an agent with approver_type = 'human' configured, or reaches a root agent (no reports_to).
UPDATE agents
SET adapter_config = jsonb_set(
COALESCE(adapter_config, '{}'::jsonb),
'{approver_type}',
'"human"'
)
WHERE name = 'CEO'
AND company_id = 'your-company-id';
An agent with approver_type = 'human' pauses the escalation chain. Paperclip creates a pending approval record and notifies via webhook — a human reviews it in the Approvals UI.
A common pattern is to have managers review worker output before it is marked resolved:
verifiedConfigure this in Company Settings → Approval Policies:
{
"trigger": "issue_resolved",
"condition": "result_word_count > 500",
"required_approver": "manager",
"approval_type": "content_review"
}
SELECT
ap.id,
ap.trigger,
ap.status,
req.name AS requested_by,
rev.name AS reviewer,
ap.created_at
FROM approvals ap
JOIN agents req ON req.id = ap.requesting_agent_id
LEFT JOIN agents rev ON rev.id = ap.reviewer_agent_id
WHERE ap.company_id = 'your-company-id'
AND ap.status = 'pending'
ORDER BY ap.created_at;
Paperclip prevents circular reports_to chains at write time:
// Before saving, walk up the chain
async function checkCircular(agentId: string, reportsToId: string) {
let current = reportsToId;
while (current) {
if (current === agentId) throw new Error('Circular hierarchy detected');
const parent = await db.agents.findOne(current);
current = parent?.reports_to ?? null;
}
}
reports_to