Menu
popagent
publicLatest change 4fc0bd53b97c085d906737f5b8b55d5771472d9c - feat: make company staff specialist agents by AkurAI Build
import { Agent } from "@mastra/core/agent";
import type { RequestContext } from "@mastra/core/request-context";
import { Mastra } from "@mastra/core/mastra";
import {
createFinalResponseGuard,
specialistExecutionOptions,
toolCallConcurrency,
} from "./agent-autonomy";
import { AGENT_CONTEXT_KEYS, agentContextValue } from "./agent-context";
import { agentRuntimeSettings } from "./agent-runtime-settings";
import { agentSettings } from "./agent-settings";
import { agentSkills } from "./agent-skills";
import { companyAgentProfiles } from "./company-roster";
import {
BUILD_AGENT_IDS,
BUILD_AGENT_TOOL_ALLOWLISTS,
DEFAULT_WORKSPACE_ID,
type AgentRuntimeSettings,
type AgentSettings,
type BuildAgentId,
} from "./api-types";
import { evolutionStore } from "./evolution-store";
import { resolveModel } from "./models";
import { logger, observability, setAppLogger } from "./observability";
import { memory, storage } from "./storage";
import { bifrostNavigator } from "./tools/bifrost";
import { getTime } from "./tools/get-time";
import { editMemory, recallMemory, reflectMemory, retainMemory } from "./tools/memory";
import { useBrowserSecret } from "./tools/secrets";
import { webSearch } from "./tools/web-search";
import { searchDocumentation } from "./tools/search-documentation";
import { repoBrief } from "./tools/repo-brief";
import { akuraiBuildTools } from "./tools/akurai-build";
import { createAgentCommunicationTool } from "./tools/agent-communication";
import { agentWorkspaceRuntime } from "./workspace";
async function requiredAgentProfile(id: string): Promise<AgentSettings> {
const settings = await agentSettings.get(id);
if (!settings) throw new Error(`Agent settings not found: ${id}`);
return settings;
}
async function renderedInstructions(
settings: AgentSettings,
requestContext?: RequestContext,
): Promise<string> {
const instructions = settings.instructions.trim();
if (!instructions) throw new Error(`Agent instructions are empty: ${settings.id}`);
const overlay = await evolutionStore.learnedOverlay(settings.id);
const base = `Display identity: ${settings.name.trim()}.\n\n${instructions}`;
const rendered = overlay ? `${base}\n\n## Learned behavior overlay\n${overlay}` : base;
const communication = agentContextValue(requestContext, AGENT_CONTEXT_KEYS.communicationSession);
if (!communication) return rendered;
const incoming = communication.takeContext(settings.id)
.map((message) =>
`- [${message.id}] ${message.from}${message.replyTo ? ` (reply to ${message.replyTo})` : ""}: ${message.body}`)
.join("\n");
const pending = incoming
? `\n\n## Incoming task messages\nThese addressed peer messages were consumed from your task mailbox at this safe model boundary:\n${incoming}`
: "";
return `${rendered}\n\n## Task coordination\nUse the agentCommunication tool to list task peers, exchange concise addressed messages and replies, or wait only when coordination blocks your next step. An idle addressed peer is woken in its own Mastra run. Never reply on another agent's behalf: after sending, wait for that recipient's reply when you need an answer. A queued receipt remains pending; delivered means an active waiter consumed it.${pending}`;
}
async function configuredRuntime(
requestContext: RequestContext | undefined,
): Promise<AgentRuntimeSettings> {
return agentContextValue(requestContext, AGENT_CONTEXT_KEYS.runtimeSettings)
?? agentRuntimeSettings.get();
}
const modelForContext = async (
{ requestContext }: { requestContext: RequestContext },
) => {
const selected = agentContextValue(requestContext, AGENT_CONTEXT_KEYS.model);
const settings = selected ? undefined : await configuredRuntime(requestContext);
return resolveModel(selected ?? settings!.defaultModel);
};
const modelForRole = (id: string) => async (
{ requestContext }: { requestContext: RequestContext },
) => {
const profile = await requiredAgentProfile(id);
return profile.model ? resolveModel(profile.model) : modelForContext({ requestContext });
};
const sharedSubagentOptions = {
defaultOptions: specialistExecutionOptions,
};
const toolRegistry = {
getTime,
retainMemory,
recallMemory,
reflectMemory,
editMemory,
useBrowserSecret,
bifrostNavigator,
webSearch,
searchDocumentation,
repoBrief,
...akuraiBuildTools,
};
const buildToolSet = new Set<string>(Object.values(BUILD_AGENT_TOOL_ALLOWLISTS).flat());
const workspaceToolSet = new Set(["repoBrief", "searchDocumentation"]);
const browserToolSet = new Set(["bifrostNavigator", "useBrowserSecret"]);
async function configuredTools(id: string, requestContext?: RequestContext) {
const profile = await requiredAgentProfile(id);
const executionSource = agentContextValue(
requestContext,
AGENT_CONTEXT_KEYS.executionSource,
);
const containedAutonomy = executionSource === "self-update" || executionSource === "build-maintenance";
const isBuildRole = BUILD_AGENT_IDS.includes(id as BuildAgentId);
const buildAllowed = isBuildRole
? BUILD_AGENT_TOOL_ALLOWLISTS[id as BuildAgentId] as readonly string[]
: undefined;
const tools = Object.fromEntries(
profile.tools
.filter((tool) => !buildToolSet.has(tool) || (isBuildRole && buildAllowed?.includes(tool)))
.filter((tool) => profile.workspaceAccess !== "none" || !workspaceToolSet.has(tool))
.filter((tool) => profile.browserAccess !== "none" || !browserToolSet.has(tool))
.filter((tool) => profile.browserAccess === "interactive" || tool !== "useBrowserSecret")
.filter((tool) => !containedAutonomy || !["retainMemory", "editMemory", "useBrowserSecret", "bifrostNavigator"].includes(tool))
.map((tool) => [tool, toolRegistry[tool]]),
) as Partial<typeof toolRegistry>;
const communication = agentContextValue(requestContext, AGENT_CONTEXT_KEYS.communicationSession);
return communication
? { ...tools, agentCommunication: createAgentCommunicationTool(id, communication) }
: tools;
}
const workspaceFor = (id: string) =>
async ({ requestContext }: { requestContext: RequestContext }) => {
const profile = await requiredAgentProfile(id);
if (profile.workspaceAccess === "none") return undefined;
const selectedWorkspace = agentContextValue(requestContext, AGENT_CONTEXT_KEYS.workspaceId);
const executionSource = agentContextValue(
requestContext,
AGENT_CONTEXT_KEYS.executionSource,
);
const containedAutonomy = executionSource === "self-update" || executionSource === "build-maintenance";
const containedWritableMaintainer = executionSource === "build-maintenance" && id === "build-maintainer";
const readOnly = profile.workspaceAccess === "read-only"
|| (containedAutonomy && id !== "orchistrator" && id !== "implementer" && !containedWritableMaintainer);
if (!containedAutonomy) return agentWorkspaceRuntime.resolve(selectedWorkspace, readOnly);
const path = agentContextValue(requestContext, AGENT_CONTEXT_KEYS.selfUpdateWorkspacePath);
if (!path) throw new Error("Autonomous workspace context is unavailable");
return agentWorkspaceRuntime.resolveAutonomous(
selectedWorkspace ?? DEFAULT_WORKSPACE_ID,
path,
readOnly,
executionSource as "self-update" | "build-maintenance",
);
};
let [
supervisorProfile,
researcherProfile,
implementerProfile,
reviewerProfile,
buildMaintainerProfile,
buildReleaseManagerProfile,
communityStewardProfile,
] = await Promise.all([
requiredAgentProfile("orchistrator"),
requiredAgentProfile("researcher"),
requiredAgentProfile("implementer"),
requiredAgentProfile("reviewer"),
requiredAgentProfile("build-maintainer"),
requiredAgentProfile("build-release-manager"),
requiredAgentProfile("community-steward"),
]);
let researcherAgent: Agent;
researcherAgent = new Agent({
id: "researcher",
name: researcherProfile.name,
description: researcherProfile.description,
instructions: async ({ requestContext }) => {
researcherProfile = await requiredAgentProfile("researcher");
researcherAgent.name = researcherProfile.name;
return renderedInstructions(researcherProfile, requestContext);
},
tools: ({ requestContext }) => configuredTools("researcher", requestContext),
skills: () => agentSkills.resolve("researcher"),
workspace: workspaceFor("researcher"),
...sharedSubagentOptions,
model: modelForRole("researcher"),
});
researcherAgent.getDescription = () => researcherProfile.description;
let implementerAgent: Agent;
implementerAgent = new Agent({
id: "implementer",
name: implementerProfile.name,
description: implementerProfile.description,
instructions: async ({ requestContext }) => {
implementerProfile = await requiredAgentProfile("implementer");
implementerAgent.name = implementerProfile.name;
return renderedInstructions(implementerProfile, requestContext);
},
tools: ({ requestContext }) => configuredTools("implementer", requestContext),
skills: () => agentSkills.resolve("implementer"),
workspace: workspaceFor("implementer"),
...sharedSubagentOptions,
model: modelForRole("implementer"),
});
implementerAgent.getDescription = () => implementerProfile.description;
let reviewerAgent: Agent;
reviewerAgent = new Agent({
id: "reviewer",
name: reviewerProfile.name,
description: reviewerProfile.description,
instructions: async ({ requestContext }) => {
reviewerProfile = await requiredAgentProfile("reviewer");
reviewerAgent.name = reviewerProfile.name;
return renderedInstructions(reviewerProfile, requestContext);
},
tools: ({ requestContext }) => configuredTools("reviewer", requestContext),
skills: () => agentSkills.resolve("reviewer"),
workspace: workspaceFor("reviewer"),
...sharedSubagentOptions,
model: modelForRole("reviewer"),
});
reviewerAgent.getDescription = () => reviewerProfile.description;
let buildMaintainerAgent: Agent;
buildMaintainerAgent = new Agent({
id: "build-maintainer",
name: buildMaintainerProfile.name,
description: buildMaintainerProfile.description,
instructions: async ({ requestContext }) => {
buildMaintainerProfile = await requiredAgentProfile("build-maintainer");
buildMaintainerAgent.name = buildMaintainerProfile.name;
return renderedInstructions(buildMaintainerProfile, requestContext);
},
tools: ({ requestContext }) => configuredTools("build-maintainer", requestContext),
skills: () => agentSkills.resolve("build-maintainer"),
workspace: workspaceFor("build-maintainer"),
...sharedSubagentOptions,
model: modelForRole("build-maintainer"),
});
buildMaintainerAgent.getDescription = () => buildMaintainerProfile.description;
let buildReleaseManagerAgent: Agent;
buildReleaseManagerAgent = new Agent({
id: "build-release-manager",
name: buildReleaseManagerProfile.name,
description: buildReleaseManagerProfile.description,
instructions: async ({ requestContext }) => {
buildReleaseManagerProfile = await requiredAgentProfile("build-release-manager");
buildReleaseManagerAgent.name = buildReleaseManagerProfile.name;
return renderedInstructions(buildReleaseManagerProfile, requestContext);
},
tools: ({ requestContext }) => configuredTools("build-release-manager", requestContext),
skills: () => agentSkills.resolve("build-release-manager"),
workspace: workspaceFor("build-release-manager"),
...sharedSubagentOptions,
model: modelForRole("build-release-manager"),
});
buildReleaseManagerAgent.getDescription = () => buildReleaseManagerProfile.description;
let communityStewardAgent: Agent;
communityStewardAgent = new Agent({
id: "community-steward",
name: communityStewardProfile.name,
description: communityStewardProfile.description,
instructions: async ({ requestContext }) => {
communityStewardProfile = await requiredAgentProfile("community-steward");
communityStewardAgent.name = communityStewardProfile.name;
return renderedInstructions(communityStewardProfile, requestContext);
},
tools: ({ requestContext }) => configuredTools("community-steward", requestContext),
skills: () => agentSkills.resolve("community-steward"),
workspace: workspaceFor("community-steward"),
...sharedSubagentOptions,
model: modelForRole("community-steward"),
});
communityStewardAgent.getDescription = () => communityStewardProfile.description;
const specialistAgents = {
researcher: researcherAgent,
implementer: implementerAgent,
reviewer: reviewerAgent,
"build-maintainer": buildMaintainerAgent,
"build-release-manager": buildReleaseManagerAgent,
"community-steward": communityStewardAgent,
};
async function createCompanySpecialist(id: string) {
let profile = await requiredAgentProfile(id);
let specialist: Agent;
specialist = new Agent({
id,
name: profile.name,
description: profile.description,
instructions: async ({ requestContext }) => {
profile = await requiredAgentProfile(id);
specialist.name = profile.name;
return renderedInstructions(profile, requestContext);
},
tools: ({ requestContext }) => configuredTools(id, requestContext),
skills: () => agentSkills.resolve(id),
workspace: workspaceFor(id),
...sharedSubagentOptions,
model: modelForRole(id),
});
specialist.getDescription = () => profile.description;
return {
id,
agent: specialist,
enabled: () => profile.delegationEnabled,
refresh: async () => {
profile = await requiredAgentProfile(id);
specialist.name = profile.name;
},
};
}
const companySpecialistRuntimes = await Promise.all(
companyAgentProfiles.filter((profile) => !profile.established)
.map((profile) => createCompanySpecialist(profile.id)),
);
const companySpecialistRuntimeById = new Map(
companySpecialistRuntimes.map((runtime) => [runtime.id, runtime]),
);
const allSpecialistAgents: Record<string, Agent> = {
...specialistAgents,
...Object.fromEntries(companySpecialistRuntimes.map((runtime) => [runtime.id, runtime.agent])),
};
async function refreshSpecialistProfiles(
{ requestContext }: { requestContext: RequestContext },
) {
[
researcherProfile,
implementerProfile,
reviewerProfile,
buildMaintainerProfile,
buildReleaseManagerProfile,
communityStewardProfile,
] = await Promise.all([
requiredAgentProfile("researcher"),
requiredAgentProfile("implementer"),
requiredAgentProfile("reviewer"),
requiredAgentProfile("build-maintainer"),
requiredAgentProfile("build-release-manager"),
requiredAgentProfile("community-steward"),
]);
researcherAgent.name = researcherProfile.name;
implementerAgent.name = implementerProfile.name;
reviewerAgent.name = reviewerProfile.name;
buildMaintainerAgent.name = buildMaintainerProfile.name;
buildReleaseManagerAgent.name = buildReleaseManagerProfile.name;
communityStewardAgent.name = communityStewardProfile.name;
await Promise.all(companySpecialistRuntimes.map((runtime) => runtime.refresh()));
const repositoryBriefReady = agentContextValue(
requestContext,
AGENT_CONTEXT_KEYS.repositoryBriefReady,
) === true;
const executionSource = agentContextValue(requestContext, AGENT_CONTEXT_KEYS.executionSource);
const containedAutonomy = executionSource === "self-update" || executionSource === "build-maintenance";
const enabled = Object.entries(allSpecialistAgents).filter(([id]) => {
const companySpecialist = companySpecialistRuntimeById.get(id);
if (companySpecialist) return !containedAutonomy && companySpecialist.enabled();
if (executionSource === "build-maintenance") {
if (id === "reviewer") return reviewerProfile.delegationEnabled;
return id === "build-maintainer" && buildMaintainerProfile.delegationEnabled;
}
if (id === "build-maintainer") return buildMaintainerProfile.delegationEnabled;
if (id === "build-release-manager") return buildReleaseManagerProfile.delegationEnabled;
if (id === "community-steward") return communityStewardProfile.delegationEnabled;
if (id === "researcher") return researcherProfile.delegationEnabled && !repositoryBriefReady;
if (id === "implementer") return implementerProfile.delegationEnabled;
if (id === "reviewer") return reviewerProfile.delegationEnabled;
if (executionSource === "self-update") return false;
return false;
});
if (!containedAutonomy) {
return Object.fromEntries(enabled);
}
return Object.fromEntries(enabled.map(([id, specialist]) => {
const fork = specialist.__fork();
fork.setBrowser(undefined);
return [id, fork];
}));
}
let supervisorAgent: Agent;
supervisorAgent = new Agent({
id: "orchistrator",
name: supervisorProfile.name,
description: supervisorProfile.description,
instructions: async ({ requestContext }) => {
supervisorProfile = await requiredAgentProfile("orchistrator");
supervisorAgent.name = supervisorProfile.name;
return renderedInstructions(supervisorProfile, requestContext);
},
model: modelForRole("orchistrator"),
defaultOptions: async ({ requestContext }) => {
const settings = await configuredRuntime(requestContext);
return {
maxSteps: settings.supervisorMaxSteps,
toolCallConcurrency: toolCallConcurrency(settings),
onIterationComplete: createFinalResponseGuard(settings),
};
},
tools: ({ requestContext }) => configuredTools("orchistrator", requestContext),
memory,
workspace: workspaceFor("orchistrator"),
skills: () => agentSkills.resolve("orchistrator"),
agents: refreshSpecialistProfiles,
});
supervisorAgent.getDescription = () => supervisorProfile.description;
export const taskParticipantAgents = {
orchistrator: supervisorAgent,
...allSpecialistAgents,
} as Record<string, Agent>;
export const agent = supervisorAgent;
export const researcher = researcherAgent;
export const implementer = implementerAgent;
export const reviewer = reviewerAgent;
export const mastra = new Mastra({
agents: { orchistrator: agent },
storage,
logger,
observability,
environment: process.env.POPAGENT_ENVIRONMENT ?? process.env.NODE_ENV,
});
setAppLogger(mastra.getLogger());