From 6232d2397d4af60b55c1aa0516dbefee3e759c12 Mon Sep 17 00:00:00 2001 From: Forgotten Date: Tue, 17 Feb 2026 20:07:02 -0600 Subject: [PATCH] Add chain-of-command API for agents - agentService.getChainOfCommand() walks the reporting tree upward - GET /agents/:id now returns chainOfCommand array with the full management hierarchy - GET /agents/me endpoint returns the calling agent with its chain of command Co-Authored-By: Claude Sonnet 4.6 --- server/src/routes/agents.ts | 17 ++++++++++++++++- server/src/services/agents.ts | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/server/src/routes/agents.ts b/server/src/routes/agents.ts index b0a3f9b7..ec542851 100644 --- a/server/src/routes/agents.ts +++ b/server/src/routes/agents.ts @@ -51,6 +51,20 @@ export function agentRoutes(db: Db) { res.json(tree); }); + router.get("/agents/me", async (req, res) => { + if (req.actor.type !== "agent" || !req.actor.agentId) { + res.status(401).json({ error: "Agent authentication required" }); + return; + } + const agent = await svc.getById(req.actor.agentId); + if (!agent) { + res.status(404).json({ error: "Agent not found" }); + return; + } + const chainOfCommand = await svc.getChainOfCommand(agent.id); + res.json({ ...agent, chainOfCommand }); + }); + router.get("/agents/:id", async (req, res) => { const id = req.params.id as string; const agent = await svc.getById(id); @@ -59,7 +73,8 @@ export function agentRoutes(db: Db) { return; } assertCompanyAccess(req, agent.companyId); - res.json(agent); + const chainOfCommand = await svc.getChainOfCommand(agent.id); + res.json({ ...agent, chainOfCommand }); }); router.get("/agents/:id/runtime-state", async (req, res) => { diff --git a/server/src/services/agents.ts b/server/src/services/agents.ts index fb0d807a..02c877e9 100644 --- a/server/src/services/agents.ts +++ b/server/src/services/agents.ts @@ -174,6 +174,21 @@ export function agentService(db: Db) { return build(null); }, + getChainOfCommand: async (agentId: string) => { + const chain: { id: string; name: string; role: string; title: string | null }[] = []; + const visited = new Set([agentId]); + const start = await getById(agentId); + let currentId = start?.reportsTo ?? null; + while (currentId && !visited.has(currentId) && chain.length < 50) { + visited.add(currentId); + const mgr = await getById(currentId); + if (!mgr) break; + chain.push({ id: mgr.id, name: mgr.name, role: mgr.role, title: mgr.title ?? null }); + currentId = mgr.reportsTo ?? null; + } + return chain; + }, + runningForAgent: (agentId: string) => db .select()