Menu
popagent
publicLatest change 4fc0bd53b97c085d906737f5b8b55d5771472d9c - feat: make company staff specialist agents by AkurAI Build
import { storage } from "./storage";
import {
AGENT_TOOL_NAMES,
BUILD_AGENT_IDS,
BUILD_AGENT_TOOL_ALLOWLISTS,
MAX_AGENT_INSTRUCTIONS_CHARACTERS,
type AgentSettings,
type AgentSettingsInput,
type AgentToolName,
type BuildAgentId,
} from "./api-types";
import { companyAgentProfiles } from "./company-roster";
import { retryableInit } from "./retryable-init";
const AGENT_SETTINGS_COLUMNS = `id, name, description, instructions,
model,
workspace_access AS "workspaceAccess", browser_access AS "browserAccess",
delegation_enabled AS "delegationEnabled",
tools, source_urls AS "sourceUrls",
created_at::text AS "createdAt", updated_at::text AS "updatedAt"`;
const AGENT_TOOL_NAME_SET = new Set<string>(AGENT_TOOL_NAMES);
const BUILD_AGENT_ID_SET = new Set<string>(BUILD_AGENT_IDS);
const BUILD_AGENT_TOOL_SET = new Set<string>(
Object.values(BUILD_AGENT_TOOL_ALLOWLISTS).flat(),
);
const initializeAgentRoleStorageOnce = retryableInit(async () => {
await storage.init();
const seed = await Bun.file(new URL("./agent-role-seed.sql", import.meta.url)).text();
await storage.db.none(seed);
await storage.db.tx(async (db) => {
const migrationId = "2026-08-16-company-specialist-agents-v1";
if (await db.oneOrNone("SELECT id FROM popagent_data_migrations WHERE id=$1", [migrationId])) return;
for (const profile of companyAgentProfiles) {
if (!profile.established) await db.none(`
INSERT INTO popagent_agents
(id, name, description, instructions, model, source_urls, workspace_access,
browser_access, delegation_enabled, tools)
VALUES ($1, $2, $3, $4, $5, $9::jsonb, $6, $7, TRUE, $8::jsonb)
ON CONFLICT (id) DO NOTHING
`, [
profile.id, profile.name, profile.description, profile.instructions,
"codex/gpt-5.6-luna-medium", profile.workspaceAccess, profile.browserAccess,
JSON.stringify(profile.tools), JSON.stringify(profile.sourceUrls),
]);
await db.none(`
INSERT INTO popagent_agent_skills
(id, agent_id, name, description, instructions, "references", source_urls, enabled, user_invocable)
VALUES ($1, $2, $3, $4, $5, '{}'::jsonb, $6::jsonb, TRUE, FALSE)
ON CONFLICT (id) DO NOTHING
`, [
`builtin-${profile.id}-specialty`, profile.id, profile.skillName,
profile.skillDescription, profile.skillInstructions, JSON.stringify(profile.sourceUrls),
]);
}
await db.none("INSERT INTO popagent_data_migrations (id) VALUES ($1)", [migrationId]);
});
});
export function initializeAgentRoleStorage(): Promise<void> {
return initializeAgentRoleStorageOnce();
}
export class AgentSettingsStore {
readonly storage = storage;
init(): Promise<void> {
return initializeAgentRoleStorage();
}
async list(): Promise<AgentSettings[]> {
await this.init();
return this.storage.db.any<AgentSettings>(`
SELECT ${AGENT_SETTINGS_COLUMNS}
FROM popagent_agents ORDER BY name
`);
}
async get(id: string): Promise<AgentSettings | undefined> {
await this.init();
return (await this.storage.db.oneOrNone<AgentSettings>(`
SELECT ${AGENT_SETTINGS_COLUMNS}
FROM popagent_agents WHERE id = $1
`, [id])) ?? undefined;
}
async update(id: string, input: AgentSettingsInput): Promise<AgentSettings | undefined> {
if (input.instructions.length > MAX_AGENT_INSTRUCTIONS_CHARACTERS) {
throw new RangeError(`Agent instructions exceed ${MAX_AGENT_INSTRUCTIONS_CHARACTERS} characters`);
}
if (!input.name.trim() || !input.description.trim() || !input.instructions.trim()) {
throw new RangeError("Agent name, description, and instructions must not be empty");
}
if (
input.tools.some((tool) => !AGENT_TOOL_NAME_SET.has(tool))
|| new Set(input.tools).size !== input.tools.length
) {
throw new RangeError("Agent tools contain an unsupported or duplicate tool");
}
if (BUILD_AGENT_ID_SET.has(id)) {
const allowed = BUILD_AGENT_TOOL_ALLOWLISTS[id as BuildAgentId] as readonly AgentToolName[];
if (input.tools.some((tool) => !allowed.includes(tool))) {
throw new RangeError("Build agent tools exceed its role allowlist");
}
} else if (input.tools.some((tool) => BUILD_AGENT_TOOL_SET.has(tool))) {
throw new RangeError("Non-Build agents cannot use AkurAI Build tools");
}
return (await this.storage.db.oneOrNone<AgentSettings>(`
UPDATE popagent_agents
SET name = $2,
description = $3,
model = $5,
instructions = $4,
workspace_access = $6,
browser_access = $7,
delegation_enabled = $8,
tools = $9::jsonb
WHERE id = $1
RETURNING ${AGENT_SETTINGS_COLUMNS}
`, [
id,
input.name.trim(),
input.description.trim(),
input.instructions,
input.model?.trim() || null,
input.workspaceAccess,
input.browserAccess,
input.delegationEnabled,
JSON.stringify(input.tools),
])) ?? undefined;
}
}
export const agentSettings = new AgentSettingsStore();