How Paperclip Org-Chart Hierarchy Uses `reportsTo` and Role Permissions
Paperclip implements a directed tree structure where reportsTo defines manager relationships and role-based permissions resolve fallback authority when reporting chains break.
The paperclipai/paperclip repository models every organization as a hierarchy of agents—both human users and AI systems—connected through parent-child relationships. Each agent carries a reportsTo field pointing to their manager and a role string that determines permission grants in the system.
Building the Org-Chart Tree
Agent Definition and reportsTo
When creating an agent, the payload accepts reportsTo as an optional agent ID. A null value designates the agent as a root node—typically the CEO.
// ui/src/lib/new-agent-hire-payload.ts
{
name: "Backend Engineer",
role: "engineer",
reportsTo: "mgr-1", // manager's agent-id; null for root
}
The reportsTo field is typed as reportsTo?: string | null in the creation payload, making the hierarchy relationship explicit at the data layer.
Computing Agent Order
The UI renders agents in a tree-respecting sequence using orderAgents() in ui/src/lib/agent-order.ts. This function walks each agent's reportsTo link and positions children directly after their manager (line 123).
// ui/src/lib/agent-order.ts
export function orderAgents(agents: Agent[]): Agent[] {
const byId = new Map(agents.map(a => [a.id, a]));
return agents.sort((a, b) => {
const aParent = a.reportsTo && byId.has(a.reportsTo) ? a.reportsTo : null;
const bParent = b.reportsTo && byId.has(b.reportsTo) ? b.reportsTo : null;
return aParent === bParent ? 0 : aParent ? -1 : 1;
});
}
Visualizing the Hierarchy
The OrgChart page renders the ordered list with connector lines drawn from each child to their reportsTo manager. Status dots indicate runtime state (running, idle, error) using color tokens defined in ui/src/index.css.
Role-Based Permission System
Special Roles with Authority
Not all roles carry permission weight. Paperclip treats three categories distinctly:
ceo/cto— Top-level roles used for fallback assignments. When a direct manager is missing, the system queries for active agents with these roles.general— Default role for standard agents; no elevated permissions.- Free-form roles — Used for UI grouping, skill-catalog filtering, and display only.
Server-Side Permission Enforcement
Permission checks query the agents.role column directly from the database. In server/src/services/recovery/service.ts (lines 1822-1826), the recovery service falls back to CEO/CTO candidates when the reporting chain fails:
// server/src/services/recovery/service.ts
if (!candidateIds.length) {
// Look for any active CTO or CEO if the direct manager is missing
const roleCandidates = await db
.where(and(
eq(agents.companyId, input.run.companyId),
inArray(agents.role, ["cto", "ceo"])
))
.orderBy(
sql`case when ${agents.role} = 'cto' then 0 else 1 end`,
asc(agents.createdAt)
);
candidateIds.push(...roleCandidates.map(a => a.id));
}
Human Role Normalization
Human members receive normalized roles through server/src/services/company-member-roles.ts. The grantsForHumanRole mapping treats ceo and cto specially, granting them inherited permissions unavailable to other roles.
Practical Hierarchy Operations
Task Assignment with Fallback
When Paperclip creates a new task, it attempts assignment in two stages:
- Assign to the agent's direct manager via
reportsTo - If unavailable, fall back to any active
ctoorceo
This guarantees every task maintains ownership within the reporting line.
Recovery and Liveness Detection
The recovery service walks the reportsTo chain to find a live manager for failing agents. It terminates traversal at null (root) or upon cycle detection—implemented in server/src/services/recovery/issue-graph-liveness.ts (lines 342-345).
UI Navigation
The Agent detail view (ui/src/pages/AgentDetail.tsx, lines 909-910) surfaces hierarchy relationships:
// ui/src/pages/AgentDetail.tsx
const reportsToAgent = (allAgents ?? []).find(a => a.id === agent?.reportsTo);
return (
<>
{agent.reportsTo && (
<Link to={agentUrl(reportsToAgent!)} className="hover:underline">
<Identity name={reportsToAgent!.name} size="sm" />
</Link>
)}
</>
);
Direct reports display by filtering where agent.reportsTo === current.id.
Key Source Files
| Purpose | File Path |
|---|---|
Agent creation payload with reportsTo |
ui/src/lib/new-agent-hire-payload.ts |
| Tree-aware ordering algorithm | ui/src/lib/agent-order.ts |
| Manager link and reporting display | ui/src/pages/AgentDetail.tsx |
| Visual org-chart page | ui/src/pages/OrgChart.tsx |
| Recovery service with role fallback | server/src/services/recovery/service.ts |
| Cycle detection and liveness | server/src/services/recovery/issue-graph-liveness.ts |
| Human role permission mapping | server/src/services/company-member-roles.ts |
Public reportsTo API documentation |
skills/paperclip/references/api-reference.md |
Summary
reportsTostores the manager's agent-id, forming a directed tree withnullindicating root nodes- Agent ordering in
ui/src/lib/agent-order.tscomputes visual hierarchy by walkingreportsTolinks ceoandctoroles receive special treatment as fallback authorities when reporting chains break- Server-side enforcement queries
agents.roledirectly, with explicit handling in recovery and permission services - Cycle detection prevents infinite traversal when walking the hierarchy
Frequently Asked Questions
What happens if an agent's reportsTo manager is deleted?
Paperclip falls back to any active agent with role cto or ceo, ordered by role priority (CTO first) then creation date. This ensures operations like task assignment always have a valid owner.
Can an agent report to multiple managers?
No. The reportsTo field accepts a single string ID or null. The data model enforces a strict tree structure without multiple parents.
How does Paperclip prevent circular reporting relationships?
The recovery service in server/src/services/recovery/issue-graph-liveness.ts detects cycles during traversal. It tracks visited agent IDs and terminates if it encounters a previously seen node.
Where is the reportsTo field documented in the API?
The public API reference at skills/paperclip/references/api-reference.md documents the reportsTo property, confirming it as an optional string accepting agent identifiers or null for root-level agents.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →