AI developer agents with specializations, ticket assignment, and team coordination

Agents & Dev Teams

The @codmir/ai agents module provides DeveloperAgent and DevTeam classes for creating AI developers that work on tickets, review code, and collaborate as a team.

Installation

import {
  DeveloperAgent,
  DevTeam,
  createDeveloper,
  createDevTeam,
  DEVELOPER_PROFILES,
} from "@codmir/ai";

Quick Start

import { createDevTeam, DEVELOPER_PROFILES } from "@codmir/ai";

const team = createDevTeam({
  name: "Core Team",
  projectContext: {
    projectId: "codmir",
    name: "Codmir",
    techStack: ["TypeScript", "Next.js", "NestJS", "Prisma"],
  },
  developers: [
    DEVELOPER_PROFILES.alex,   // fullstack lead
    DEVELOPER_PROFILES.sam,    // frontend specialist
    DEVELOPER_PROFILES.jordan, // backend specialist
    DEVELOPER_PROFILES.riley,  // testing specialist
  ],
  autoAssign: true,
  requirePeerReview: true,
});

// Queue a ticket
team.queueTicket({
  id: "TICKET-42",
  title: "Fix login form validation",
  description: "Email field accepts invalid formats",
  type: "bug",
  priority: "high",
  status: "open",
  relatedFiles: ["src/components/LoginForm.tsx"],
  acceptanceCriteria: ["Email validation uses RFC 5322 regex"],
  createdAt: new Date(),
  updatedAt: new Date(),
});

// Auto-assign picks the best available developer
const breakdown = await team.tryAssignNextTicket();
// breakdown.plan => [{ order: 1, description: "Analyze requirements...", type: "analyze" }, ...]

DeveloperAgent

createDeveloper(profileOrId, projectContext): DeveloperAgent

Creates a developer agent from a profile object or a built-in profile ID.

import { createDeveloper, DEVELOPER_PROFILES } from "@codmir/ai";

// From built-in profile
const alex = createDeveloper("alex", projectContext);

// From custom profile
const custom = createDeveloper(
  {
    id: "aria",
    name: "Aria",
    specialization: "frontend",
    skills: ["React", "CSS", "Accessibility", "Design Systems"],
    experience: "senior",
    personality: "Design-focused, accessibility advocate",
  },
  projectContext,
);

DeveloperAgentConfig

interface DeveloperAgentConfig {
  profile: DeveloperProfile;
  projectContext: ProjectContext;
  maxConcurrentTasks?: number;
  autoCommit?: boolean;
  requireReview?: boolean;
}

Methods

assignTicket(ticket): Promise<TaskBreakdown>

Assigns a ticket to this developer. Analyzes the ticket and returns a task breakdown with ordered steps.

const breakdown = await developer.assignTicket(ticket);
console.log(breakdown.plan);
// [
//   { order: 1, description: "Analyze requirements and existing code", type: "analyze" },
//   { order: 2, description: "Implement the solution", type: "implement" },
//   { order: 3, description: "Write tests", type: "test" },
//   { order: 4, description: "Self-review and refactor", type: "review" },
// ]

work(): Promise<void>

Starts working on the currently assigned ticket. Throws if no ticket is assigned.

await developer.work();

review(code, context?): Promise<ReviewResult>

Reviews code and returns approval status, comments, and suggestions.

const result = await developer.review(codeString, "Checkout flow refactor");
// {
//   approved: true,
//   comments: [{ file: "checkout.tsx", line: 42, message: "Missing null check", severity: "error" }],
//   suggestions: ["Consider extracting validation logic into a hook"],
// }

getStatus(): DeveloperAgentState

Returns the developer's current state.

const status = developer.getStatus();
// {
//   id: "abc123",
//   profile: { name: "Alex", specialization: "fullstack", ... },
//   status: "coding",       // "idle" | "analyzing" | "coding" | "testing" | "reviewing" | "blocked"
//   currentTicket: { ... },
//   workLog: [...],
//   metrics: { ticketsCompleted: 5, linesWritten: 1200, ... },
// }

block(reason): void

Marks the developer as blocked with a reason.

complete(): void

Marks the current ticket as complete and returns the developer to idle.

DeveloperMetrics

interface DeveloperMetrics {
  tasksCompleted: number;
  tokensUsed: number;
  averageResponseTime: number;
  successRate: number;
  ticketsCompleted: number;
  linesWritten: number;
  testsWritten: number;
  bugsFixed: number;
  reviewsCompleted: number;
}

DevTeam

createDevTeam(config): DevTeam

Creates a team of AI developers.

const team = createDevTeam({
  name: "Platform Team",
  projectContext: { ... },
  developers: [DEVELOPER_PROFILES.alex, DEVELOPER_PROFILES.riley],
  maxSize: 6,
  requirePeerReview: true,
  autoAssign: true,
});

DevTeamConfig

interface DevTeamConfig {
  name: string;
  projectContext: ProjectContext;
  developers?: DeveloperProfile[];   // defaults to [alex, riley]
  maxSize?: number;
  requirePeerReview?: boolean;
  autoAssign?: boolean;
}

Team Management

addDeveloper(profile): DeveloperAgent

Adds a developer to the team. Throws if the team is at max capacity.

const dev = team.addDeveloper(DEVELOPER_PROFILES.morgan);

removeDeveloper(id): boolean

Removes a developer by ID. Throws if the developer has an active ticket. Returns false if the developer was not found.

team.removeDeveloper(dev.id);

getDevelopers(): DeveloperAgent[]

Returns all developers on the team.

findBySpecialization(spec): DeveloperAgent[]

Finds developers by specialization.

const frontendDevs = team.findBySpecialization("frontend");

getIdleDevelopers(): DeveloperAgent[]

Returns all developers with "idle" status.

Ticket Management

queueTicket(ticket): void

Adds a ticket to the queue. If autoAssign is enabled, immediately attempts assignment.

queueTickets(tickets): void

Adds multiple tickets to the queue.

assignTicket(ticketId, developerId): Promise<TaskBreakdown>

Manually assigns a specific ticket to a specific developer.

const breakdown = await team.assignTicket("TICKET-42", developer.id);

tryAssignNextTicket(): Promise<TaskBreakdown | null>

Auto-assigns the highest-priority queued ticket to the best available developer. Returns null if no tickets or no idle developers.

The matching algorithm:

  1. Sorts tickets by priority (critical > high > medium > low)
  2. Maps ticket type to preferred specializations:
    • feature prefers fullstack, frontend, backend
    • bug prefers fullstack, backend, frontend
    • refactor prefers fullstack, performance
    • docs prefers documentation, fullstack
    • test prefers testing, fullstack
    • chore prefers devops, fullstack
  3. Falls back to any idle developer

completeTicket(ticketId): void

Marks a ticket as complete. Notifies the assigned developer.

getPendingTickets(): Ticket[]

Returns all tickets in the queue.

getActiveTickets(): Ticket[]

Returns all tickets currently being worked on.

Collaboration

requestReview(code, requesterId, context?): Promise<ReviewResult[]>

Requests code reviews from up to 2 idle developers (excluding the requester).

const reviews = await team.requestReview(code, developer.id, "Auth refactor");
// [{ reviewerId: "...", reviewerName: "Riley", approved: true, comments: [...] }]

standup(): StandupReport

Generates a standup report for the entire team.

const report = team.standup();
// {
//   timestamp: Date,
//   teamName: "Core Team",
//   members: [{ id, name, status, currentTicket, metrics }],
//   queueSize: 3,
//   activeTickets: 2,
//   completedToday: 1,
// }

getMetrics(): TeamMetrics

Returns aggregate team metrics.

interface TeamMetrics {
  totalTicketsCompleted: number;
  averageTicketTime: number;
  teamVelocity: number;
  codeQualityScore: number;
}

Built-in Developer Profiles

The DEVELOPER_PROFILES constant provides pre-configured developer personas.

IDNameSpecializationSkillsExperience
alexAlexfullstackTypeScript, React, Node.js, PostgreSQLsenior
samSamfrontendReact, CSS, Tailwind, Accessibilitysenior
jordanJordanbackendNode.js, Python, APIs, Databasessenior
caseyCaseydevopsDocker, Kubernetes, CI/CD, AWSsenior
rileyRileytestingJest, Playwright, TDD, E2E Testingmid
morganMorgansecuritySecurity Audits, OWASP, Pen Testingsenior
import { DEVELOPER_PROFILES } from "@codmir/ai";

const alex = DEVELOPER_PROFILES.alex;
// { id: "alex", name: "Alex", specialization: "fullstack", skills: [...], experience: "senior" }

Types

DeveloperSpecialization

type DeveloperSpecialization =
  | "fullstack"
  | "frontend"
  | "backend"
  | "devops"
  | "security"
  | "performance"
  | "testing"
  | "documentation";

DeveloperProfile

interface DeveloperProfile {
  id: string;
  name: string;
  specialization: DeveloperSpecialization;
  skills: string[];
  experience: string;
  personality?: string;
}

Ticket

interface Ticket {
  id: string;
  title: string;
  description: string;
  type: "feature" | "bug" | "refactor" | "docs" | "test" | "chore";
  priority: TicketPriority;      // "critical" | "high" | "medium" | "low"
  status: TicketStatus;          // "open" | "in_progress" | "review" | "done" | "blocked"
  relatedFiles?: string[];
  acceptanceCriteria?: string[];
  labels?: string[];
  estimate?: number;
  assignee?: string;
  parentId?: string;
  subtasks?: string[];
  source?: string;
  externalId?: string;
  createdAt: Date;
  updatedAt: Date;
}

TaskBreakdown

interface TaskBreakdown {
  ticket: Ticket;
  plan: TaskStep[];
  estimatedDuration: number;
  risks?: string[];
  dependencies?: string[];
}

interface TaskStep {
  order: number;
  description: string;
  type: "analyze" | "implement" | "test" | "review" | "document";
  files?: string[];
  completed: boolean;
  output?: string;
}