Bluewoo HRMS
AI Development GuideFeature Specifications

AI Chat Specification

Complete specification for the AI Chat/Copilot system

AI Chat Specification

The AI Chat is a conversational interface that understands and executes HRMS features. Every feature must register its AI capabilities so users can interact naturally.

Core Philosophy

The AI Chat should understand the full software. When a user says "Create an onboarding flow for Frontend Developers", the AI knows this feature exists and can execute it.

Key Principles:

  • Every feature is AI-accessible from day one
  • Actions require user confirmation before execution
  • Results are shown with visual widgets and links
  • Errors are clear and actionable

Response Model: Phase 09 uses synchronous JSON responses. The AI service waits for all tool execution to complete before responding. Streaming (SSE) is a future enhancement for Phase 10+.

AI-Native Architecture

The AI Chat is designed as a sidebar-first, AI-native interface where the AI assistant is always accessible via a floating button. The design follows enterprise SaaS patterns with a clean white content area and colored sidebar navigation.

AIProvider Context

// components/ai/AIProvider.tsx

interface AIContextType {
  // Chat state
  mode: 'minimized' | 'panel' | 'fullscreen';
  setMode: (mode: AIContextType['mode']) => void;
  messages: ChatMessage[];
  isTyping: boolean;

  // Actions AI can perform
  navigate: (path: string, params?: Record<string, string>) => void;
  openForm: (formId: string, prefillData?: Record<string, any>) => void;
  showConfirmation: (message: string, onConfirm: () => void) => void;

  // User actions
  sendMessage: (content: string) => void;
  clearChat: () => void;
}

// Usage: Wrap entire app
<AIProvider>
  <App />
  <AIFloatingButton />   {/* Always rendered */}
  <AIChatPanel />        {/* Renders based on mode */}
</AIProvider>

AI Chat Modes

The AI Chat has three distinct modes that adapt to the sidebar-based layout:

MODE: MINIMIZED (Default)
┌─────────────────────────────────────┐
│                                     │
│         Any Page Content            │
│                                     │
│                               ┌────┐│
│                               │ ✨ ││ ← Floating AI Button
│                               └────┘│
├─────────────────────────────────────┤
│ 🏠    👥    📅    📄    •••        │ ← Mobile Nav
└─────────────────────────────────────┘

MODE: PANEL (Mobile - Bottom Sheet)
┌─────────────────────────────────────┐
│         Page Content (dimmed)       │
├─────────────────────────────────────┤
│ AI Assistant              [⬜] [✕] │ ← Fullscreen & Close
├─────────────────────────────────────┤
│                                     │
│ 👤 Show my time off balance         │
│                                     │
│ ✨ Here's your current balance:     │
│ ┌─────────────────────────────────┐│
│ │ 🏖️ Vacation    12 days left     ││
│ │ 🏥 Sick        8 days left      ││
│ │ 👤 Personal    4 days left      ││
│ │                                 ││
│ │ [Request Time Off →]            ││
│ └─────────────────────────────────┘│
│                                     │
├─────────────────────────────────────┤
│ [Ask anything...]              [➤] │
└─────────────────────────────────────┘

MODE: PANEL (Desktop - Side Panel)
┌─────────────────────────────┬───────────────────┐
│                             │ AI Assistant  [✕] │
│                             ├───────────────────┤
│       Page Content          │                   │
│                             │  Chat messages    │
│                             │                   │
│                             │                   │
│                             ├───────────────────┤
│                             │ [Input...]    [➤] │
└─────────────────────────────┴───────────────────┘

MODE: FULLSCREEN (Immersive)
┌─────────────────────────────────────────────────┐
│ ← Back           AI Assistant           [⬜→┐] │
├─────────────────────────────────────────────────┤
│                                                 │
│  👤 Add a new employee named Sarah Chen,        │
│     she's an Engineering Manager                │
│                                                 │
│  ✨ I'll help you add Sarah. Here's what I've   │
│     prepared:                                   │
│                                                 │
│  ┌─────────────────────────────────────────┐   │
│  │ 📝 NEW EMPLOYEE                          │   │
│  │                                          │   │
│  │ Name: Sarah Chen                         │   │
│  │ Title: Engineering Manager               │   │
│  │ Department: Engineering (suggested)      │   │
│  │                                          │   │
│  │ [Open Form with Details →]               │   │
│  │                                          │   │
│  │ Or tell me more to add additional info   │   │
│  └─────────────────────────────────────────┘   │
│                                                 │
├─────────────────────────────────────────────────┤
│ [📅 Request PTO] [👤 Find Employee] [📊 Stats] │ ← Quick Actions
├─────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────┐ │
│ │ Type a message...                       [➤] │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘

AI Action Card Types

The AI responds with interactive cards, not just text:

// Types of AI response cards

type AIActionCard =
  | {
      type: 'employee_card';
      employee: Employee;
      actions: Array<'view' | 'edit' | 'message'>;
    }
  | {
      type: 'balance_card';
      balances: TimeOffBalance[];
      actions: Array<'request'>;
    }
  | {
      type: 'navigation_card';
      title: string;
      description: string;
      destination: string;
      params?: Record<string, string>;
    }
  | {
      type: 'form_prefill_card';
      formType: 'employee' | 'timeoff' | 'document';
      prefillData: Record<string, any>;
      actions: Array<'open_form' | 'edit_details'>;
    }
  | {
      type: 'confirmation_card';
      title: string;
      message: string;
      confirmLabel: string;
      cancelLabel: string;
      onConfirm: () => void;
    }
  | {
      type: 'list_card';
      title: string;
      items: Array<{ label: string; value: string; icon?: string }>;
    };

AI Floating Button

// components/ai/AIFloatingButton.tsx

const AIFloatingButton = () => {
  const { mode, setMode } = useAI();

  if (mode !== 'minimized') return null;

  return (
    <motion.button
      initial={{ scale: 0 }}
      animate={{ scale: 1 }}
      whileHover={{ scale: 1.1 }}
      whileTap={{ scale: 0.95 }}
      onClick={() => setMode('panel')}
      className="
        fixed z-50

        /* Mobile: centered above bottom nav */
        bottom-20 right-4
        md:bottom-6 md:right-6

        /* Size and shape */
        w-14 h-14 rounded-full

        /* Vibrant gradient - MUST stand out */
        bg-gradient-to-br from-violet-500 via-purple-500 to-fuchsia-500

        /* Glow effect */
        shadow-lg shadow-violet-500/30

        /* Content */
        flex items-center justify-center
        text-white

        /* Subtle pulse animation */
        animate-pulse-subtle
      "
    >
      <Sparkles className="w-6 h-6" />
    </motion.button>
  );
};

Typing Indicator Component

The typing indicator shows animated dots while the AI is "thinking" or generating a response.

// components/ai/TypingIndicator.tsx
import { motion } from 'framer-motion';

const TypingIndicator = () => {
  return (
    <div className="flex items-center gap-1 px-4 py-3">
      {/* AI Avatar */}
      <div className="
        w-8 h-8 rounded-full
        bg-gradient-to-br from-violet-500 via-purple-500 to-fuchsia-500
        flex items-center justify-center
        mr-2
      ">
        <Sparkles className="w-4 h-4 text-white" />
      </div>

      {/* Typing dots container */}
      <div className="
        flex items-center gap-1
        px-4 py-2
        bg-gray-100 dark:bg-gray-800
        rounded-2xl rounded-bl-md
      ">
        {[0, 1, 2].map((index) => (
          <motion.div
            key={index}
            className="w-2 h-2 rounded-full bg-gray-400 dark:bg-gray-500"
            animate={{
              y: [0, -4, 0],
            }}
            transition={{
              duration: 0.6,
              repeat: Infinity,
              delay: index * 0.15,
              ease: 'easeInOut',
            }}
          />
        ))}
      </div>
    </div>
  );
};

// Alternative: CSS-only typing indicator (no Framer Motion)
const TypingIndicatorCSS = () => (
  <div className="flex items-center gap-1 px-4 py-3">
    <div className="
      w-8 h-8 rounded-full
      bg-gradient-to-br from-violet-500 via-purple-500 to-fuchsia-500
      flex items-center justify-center mr-2
    ">
      <Sparkles className="w-4 h-4 text-white" />
    </div>
    <div className="
      flex items-center gap-1 px-4 py-2
      bg-gray-100 dark:bg-gray-800 rounded-2xl rounded-bl-md
    ">
      <span className="w-2 h-2 rounded-full bg-gray-400 animate-typing-dot" style={{ animationDelay: '0ms' }} />
      <span className="w-2 h-2 rounded-full bg-gray-400 animate-typing-dot" style={{ animationDelay: '150ms' }} />
      <span className="w-2 h-2 rounded-full bg-gray-400 animate-typing-dot" style={{ animationDelay: '300ms' }} />
    </div>
  </div>
);

// Add to tailwind.config.js:
// animation: { 'typing-dot': 'typing-dot 1.4s infinite' }
// keyframes: { 'typing-dot': { '0%, 60%, 100%': { transform: 'translateY(0)' }, '30%': { transform: 'translateY(-4px)' } } }

Quick Actions Component

Quick action chips shown in fullscreen chat mode for common tasks.

// components/ai/QuickActions.tsx

interface QuickAction {
  icon: React.ComponentType<{ className?: string }>;
  label: string;
  action: string; // Message to send to AI
}

const defaultQuickActions: QuickAction[] = [
  { icon: Calendar, label: 'Request PTO', action: 'I want to request time off' },
  { icon: Users, label: 'Find Employee', action: 'Help me find an employee' },
  { icon: BarChart3, label: 'View Stats', action: 'Show me dashboard stats' },
  { icon: FileText, label: 'Find Policy', action: 'Search for a policy document' },
];

const QuickActions = ({ onSelect }: { onSelect: (action: string) => void }) => {
  return (
    <div className="
      flex gap-2 overflow-x-auto
      px-4 py-2
      scrollbar-hide
    ">
      {defaultQuickActions.map((action) => (
        <button
          key={action.label}
          onClick={() => onSelect(action.action)}
          className="
            flex items-center gap-2
            px-3 py-2
            bg-gray-100 dark:bg-gray-800
            hover:bg-gray-200 dark:hover:bg-gray-700
            rounded-full
            whitespace-nowrap
            text-sm font-medium
            text-gray-700 dark:text-gray-300
            transition-colors
            min-h-[36px]
          "
        >
          <action.icon className="w-4 h-4" />
          {action.label}
        </button>
      ))}
    </div>
  );
};

Chat Message Component

// components/ai/ChatMessage.tsx

interface ChatMessageProps {
  role: 'user' | 'assistant';
  content: string;
  timestamp?: Date;
  actionCard?: AIActionCard;
}

const ChatMessage = ({ role, content, timestamp, actionCard }: ChatMessageProps) => {
  const isUser = role === 'user';

  return (
    <div className={cn(
      "flex gap-3 px-4",
      isUser ? "flex-row-reverse" : "flex-row"
    )}>
      {/* Avatar */}
      {!isUser && (
        <div className="
          w-8 h-8 rounded-full flex-shrink-0
          bg-gradient-to-br from-violet-500 via-purple-500 to-fuchsia-500
          flex items-center justify-center
        ">
          <Sparkles className="w-4 h-4 text-white" />
        </div>
      )}

      {/* Message bubble */}
      <div className={cn(
        "max-w-[80%] space-y-2",
        isUser && "items-end"
      )}>
        <div className={cn(
          "px-4 py-2 rounded-2xl",
          isUser
            ? "bg-violet-500 text-white rounded-br-md"
            : "bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white rounded-bl-md"
        )}>
          <p className="text-sm whitespace-pre-wrap">{content}</p>
        </div>

        {/* Action Card (if present) */}
        {actionCard && (
          <ActionCard card={actionCard} />
        )}

        {/* Timestamp */}
        {timestamp && (
          <p className={cn(
            "text-xs text-gray-400",
            isUser ? "text-right" : "text-left"
          )}>
            {format(timestamp, 'h:mm a')}
          </p>
        )}
      </div>
    </div>
  );
};

Chat UI Components

Message Types

TypeDescriptionWhen Used
User MessageText input from userUser sends request
AI ResponseText + optional widgetsAI responds
Confirmation CardAction preview with confirm/cancelBefore write operations
Progress WidgetReal-time progress indicatorDuring async operations
Result CardSuccess/error with linksAfter action completes
Escalation PromptOption to contact human HRWhen AI cannot help

Widget Specifications

Action Confirmation Card

Shows before any write operation. User must confirm.

┌─────────────────────────────────────────────┐
│ Create Onboarding Workflow                  │
│                                             │
│ Title: Frontend Developer Onboarding        │
│ Department: Engineering                     │
│ Tasks: 12 items                             │
│ Assigned to: John Doe                       │
│                                             │
│ [Cancel]                    [Confirm]       │
└─────────────────────────────────────────────┘

React Component Structure:

interface ConfirmationCardProps {
  title: string
  icon: 'create' | 'update' | 'delete' | 'transfer'
  fields: Array<{ label: string; value: string }>
  onConfirm: () => void
  onCancel: () => void
}

Progress Widget

Shows during long-running operations.

┌─────────────────────────────────────────────┐
│ Creating workflow...                        │
│ ████████████████░░░░░░░░░░░░░░ 60%         │
│                                             │
│ [ok] Template loaded                        │
│ [ok] Tasks created (12/12)                  │
│ [..] Assigning to employee...               │
│ [ ] Sending notification                    │
└─────────────────────────────────────────────┘

React Component Structure:

interface ProgressWidgetProps {
  title: string
  progress: number // 0-100
  steps: Array<{
    label: string
    status: 'pending' | 'in_progress' | 'completed' | 'error'
  }>
}

Result Card (Success)

Shows after successful action with link to resource.

┌─────────────────────────────────────────────┐
│ [ok] Workflow Created                       │
│                                             │
│ "Frontend Developer Onboarding"             │
│ 12 tasks | Assigned to John Doe             │
│                                             │
│ [View Workflow]                             │
└─────────────────────────────────────────────┘

Result Card (Error)

Shows when action fails with recovery options.

┌─────────────────────────────────────────────┐
│ [x] Action Failed                           │
│                                             │
│ Could not create workflow:                  │
│ "You don't have permission to create        │
│  workflows for the Engineering department"  │
│                                             │
│ [Try Again]  [Contact HR Admin]             │
└─────────────────────────────────────────────┘

Info Card

Shows read-only information.

┌─────────────────────────────────────────────┐
│ Leave Balance                               │
│                                             │
│ Vacation: 15 days remaining                 │
│ Sick Leave: 10 days remaining               │
│ Personal: 3 days remaining                  │
│                                             │
│ [View Full Details]                         │
└─────────────────────────────────────────────┘

Action Execution Flow

Read Operations (No Confirmation)

User: "How many vacation days do I have?"


AI parses intent → timeoff_check_balance tool


AI calls API → GET /api/v1/time-off/balance


AI shows Info Card with balance

Write Operations (Requires Confirmation)

User: "Submit a leave request for next Monday"


AI parses intent → timeoff_submit tool


AI shows Confirmation Card

  ├── User clicks [Cancel] → AI: "No problem, request cancelled."

  └── User clicks [Confirm]


      AI calls API → POST /api/v1/time-off


      AI shows Progress Widget (if async)


      AI shows Result Card with link

Error Handling Flow

API returns error

  ├── 400 Bad Request → Show error message, suggest fix

  ├── 403 Forbidden → Show permission error, suggest contact admin

  ├── 404 Not Found → Show "resource not found" message

  ├── 429 Rate Limited → Show "too many requests", suggest wait

  └── 500 Server Error → Show generic error, offer retry

All AI Chat Tools

Employee Management Tools

employee_create

Creates a new employee profile.

{
  type: 'function',
  function: {
    name: 'employee_create',
    description: 'Create a new employee profile in the system',
    parameters: {
      type: 'object',
      properties: {
        firstName: { type: 'string', description: 'Employee first name' },
        lastName: { type: 'string', description: 'Employee last name' },
        email: { type: 'string', description: 'Work email address' },
        jobTitle: { type: 'string', description: 'Job title' },
        departmentId: { type: 'string', description: 'Department ID' },
        managerId: { type: 'string', description: 'Manager employee ID' },
        startDate: { type: 'string', format: 'date', description: 'Employment start date' },
      },
      required: ['firstName', 'lastName', 'email', 'jobTitle'],
    },
  },
}

Example prompts:

  • "Add a new employee named John Smith"
  • "Create employee profile for jane@company.com"
  • "Hire a new developer starting next Monday"

Confirmation card fields:

  • Name, Email, Job Title, Department, Manager, Start Date

Searches employees by various criteria.

{
  type: 'function',
  function: {
    name: 'employee_search',
    description: 'Search for employees by name, department, role, or tags',
    parameters: {
      type: 'object',
      properties: {
        query: { type: 'string', description: 'Search query (name, email, etc.)' },
        departmentId: { type: 'string', description: 'Filter by department' },
        roleId: { type: 'string', description: 'Filter by role' },
        tags: { type: 'array', items: { type: 'string' }, description: 'Filter by tags' },
        status: { type: 'string', enum: ['active', 'inactive', 'all'] },
      },
    },
  },
}

Example prompts:

  • "Find all engineers in the product team"
  • "Search for employees tagged as 'remote'"
  • "Who works in the Marketing department?"

Result: List of matching employees with links


employee_transfer

Transfers an employee to a new department or manager.

{
  type: 'function',
  function: {
    name: 'employee_transfer',
    description: 'Transfer an employee to a different department or manager',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'Employee to transfer' },
        newDepartmentId: { type: 'string', description: 'New department ID' },
        newManagerId: { type: 'string', description: 'New manager ID' },
        effectiveDate: { type: 'string', format: 'date', description: 'Transfer effective date' },
      },
      required: ['employeeId'],
    },
  },
}

Example prompts:

  • "Transfer John to the Engineering department"
  • "Move Sarah to report to Mike"
  • "Change department for employee #123"

employee_terminate

Initiates employee termination/offboarding.

{
  type: 'function',
  function: {
    name: 'employee_terminate',
    description: 'Initiate employee termination and offboarding process',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'Employee ID to terminate' },
        lastDay: { type: 'string', format: 'date', description: 'Last working day' },
        reason: { type: 'string', enum: ['resignation', 'termination', 'retirement', 'other'] },
        notes: { type: 'string', description: 'Additional notes' },
      },
      required: ['employeeId', 'lastDay', 'reason'],
    },
  },
}

Example prompts:

  • "Start offboarding for John Smith"
  • "Process resignation for employee leaving March 15"

employee_tag

Adds or removes tags from an employee.

{
  type: 'function',
  function: {
    name: 'employee_tag',
    description: 'Add or remove tags from an employee',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'Employee ID' },
        action: { type: 'string', enum: ['add', 'remove'] },
        tags: { type: 'array', items: { type: 'string' }, description: 'Tags to add/remove' },
      },
      required: ['employeeId', 'action', 'tags'],
    },
  },
}

Example prompts:

  • "Tag John as a senior engineer"
  • "Add 'remote' tag to Sarah"
  • "Remove 'contractor' tag from Mike"

Time-Off Tools

timeoff_submit

Submits a new time-off request.

{
  type: 'function',
  function: {
    name: 'timeoff_submit',
    description: 'Submit a time-off/leave request',
    parameters: {
      type: 'object',
      properties: {
        type: { type: 'string', enum: ['vacation', 'sick', 'personal', 'other'] },
        startDate: { type: 'string', format: 'date', description: 'Start date' },
        endDate: { type: 'string', format: 'date', description: 'End date' },
        reason: { type: 'string', description: 'Optional reason' },
        halfDay: { type: 'boolean', description: 'Half day request' },
      },
      required: ['type', 'startDate', 'endDate'],
    },
  },
}

Example prompts:

  • "Submit a vacation request for next Monday"
  • "Request sick leave for today"
  • "Book time off from Dec 20 to Jan 2"

Confirmation card fields:

  • Type, Start Date, End Date, Duration, Reason

timeoff_check_balance

Checks remaining time-off balance.

{
  type: 'function',
  function: {
    name: 'timeoff_check_balance',
    description: 'Check time-off balance for current user or team member',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'Employee ID (optional, defaults to self)' },
        type: { type: 'string', enum: ['vacation', 'sick', 'personal', 'all'] },
      },
    },
  },
}

Example prompts:

  • "How many vacation days do I have left?"
  • "Check my leave balance"
  • "What's my sick leave balance?"

Result: Info card with balance breakdown


timeoff_approve

Approves or rejects a time-off request (manager only).

{
  type: 'function',
  function: {
    name: 'timeoff_approve',
    description: 'Approve or reject a pending time-off request',
    parameters: {
      type: 'object',
      properties: {
        requestId: { type: 'string', description: 'Time-off request ID' },
        action: { type: 'string', enum: ['approve', 'reject'] },
        comment: { type: 'string', description: 'Optional comment' },
      },
      required: ['requestId', 'action'],
    },
  },
}

Example prompts:

  • "Approve John's vacation request"
  • "Reject the leave request from Sarah"

timeoff_team_calendar

Shows team availability and scheduled time-off.

{
  type: 'function',
  function: {
    name: 'timeoff_team_calendar',
    description: 'View team time-off calendar and availability',
    parameters: {
      type: 'object',
      properties: {
        startDate: { type: 'string', format: 'date' },
        endDate: { type: 'string', format: 'date' },
        teamId: { type: 'string', description: 'Team ID (optional)' },
        departmentId: { type: 'string', description: 'Department ID (optional)' },
      },
    },
  },
}

Example prompts:

  • "Who's out this week?"
  • "Show team calendar for December"
  • "Check availability for next Monday"

timeoff_cancel

Cancels a pending time-off request.

{
  type: 'function',
  function: {
    name: 'timeoff_cancel',
    description: 'Cancel a pending time-off request',
    parameters: {
      type: 'object',
      properties: {
        requestId: { type: 'string', description: 'Request ID to cancel' },
      },
      required: ['requestId'],
    },
  },
}

Example prompts:

  • "Cancel my vacation request"
  • "Withdraw my leave request for next week"

Workflow Tools

workflow_create

Creates a new workflow template.

{
  type: 'function',
  function: {
    name: 'workflow_create',
    description: 'Create a new workflow template (onboarding, offboarding, etc.)',
    parameters: {
      type: 'object',
      properties: {
        name: { type: 'string', description: 'Workflow name' },
        type: { type: 'string', enum: ['onboarding', 'offboarding', 'custom'] },
        departmentId: { type: 'string', description: 'Department for template' },
        roleFilter: { type: 'string', description: 'Role this applies to' },
        tasks: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              title: { type: 'string' },
              description: { type: 'string' },
              assigneeType: { type: 'string', enum: ['manager', 'hr', 'it', 'employee'] },
              dueOffset: { type: 'number', description: 'Days from start' },
            },
          },
        },
      },
      required: ['name', 'type'],
    },
  },
}

Example prompts:

  • "Create an onboarding flow for Frontend Developers"
  • "Set up onboarding checklist for new engineers"
  • "Create offboarding workflow for departing employees"

Confirmation card fields:

  • Name, Type, Department, Number of tasks

workflow_track

Tracks progress of an active workflow instance.

{
  type: 'function',
  function: {
    name: 'workflow_track',
    description: 'Check progress of an active workflow',
    parameters: {
      type: 'object',
      properties: {
        workflowInstanceId: { type: 'string', description: 'Workflow instance ID' },
        employeeId: { type: 'string', description: 'Employee ID to check workflows for' },
      },
    },
  },
}

Example prompts:

  • "How is John's onboarding going?"
  • "Check onboarding progress for new hires"
  • "Show workflow status for Sarah"

workflow_complete_task

Marks a workflow task as complete.

{
  type: 'function',
  function: {
    name: 'workflow_complete_task',
    description: 'Mark a workflow task as completed',
    parameters: {
      type: 'object',
      properties: {
        taskId: { type: 'string', description: 'Task ID to complete' },
        notes: { type: 'string', description: 'Completion notes' },
      },
      required: ['taskId'],
    },
  },
}

Example prompts:

  • "Mark the laptop setup task as done"
  • "Complete the IT equipment task for John"

onboarding_initiate

Starts onboarding for a new employee.

{
  type: 'function',
  function: {
    name: 'onboarding_initiate',
    description: 'Start onboarding process for a new employee',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'New employee ID' },
        templateId: { type: 'string', description: 'Workflow template to use' },
        startDate: { type: 'string', format: 'date' },
      },
      required: ['employeeId'],
    },
  },
}

Example prompts:

  • "Start onboarding for John Smith"
  • "Initialize new hire process for employee #123"

offboarding_initiate

Starts offboarding for a departing employee.

{
  type: 'function',
  function: {
    name: 'offboarding_initiate',
    description: 'Start offboarding process for a departing employee',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'Departing employee ID' },
        lastDay: { type: 'string', format: 'date' },
        templateId: { type: 'string', description: 'Offboarding template to use' },
      },
      required: ['employeeId', 'lastDay'],
    },
  },
}

Example prompts:

  • "Start offboarding for Sarah"
  • "Initiate exit process for employee leaving Friday"

Document Tools

Semantic search across documents using RAG.

{
  type: 'function',
  function: {
    name: 'document_search',
    description: 'Search documents using natural language',
    parameters: {
      type: 'object',
      properties: {
        query: { type: 'string', description: 'Natural language search query' },
        category: { type: 'string', enum: ['policy', 'handbook', 'benefits', 'all'] },
        limit: { type: 'number', description: 'Max results to return' },
      },
      required: ['query'],
    },
  },
}

Example prompts:

  • "Find the remote work policy"
  • "Search for vacation policy documents"
  • "What documents mention parental leave?"

document_ask

Ask questions about document content (Q&A with RAG).

{
  type: 'function',
  function: {
    name: 'document_ask',
    description: 'Ask a question and get an answer from HR documents',
    parameters: {
      type: 'object',
      properties: {
        question: { type: 'string', description: 'Question to answer' },
      },
      required: ['question'],
    },
  },
}

Example prompts:

  • "What's our parental leave policy?"
  • "How do I submit an expense report?"
  • "What are the company holidays this year?"

document_upload

Uploads a new document.

{
  type: 'function',
  function: {
    name: 'document_upload',
    description: 'Upload a new document to the system',
    parameters: {
      type: 'object',
      properties: {
        name: { type: 'string', description: 'Document name' },
        category: { type: 'string', enum: ['policy', 'handbook', 'form', 'other'] },
        visibility: { type: 'string', enum: ['private', 'team', 'company'] },
        tags: { type: 'array', items: { type: 'string' } },
      },
      required: ['name'],
    },
  },
}

Note: File upload requires separate file picker UI.


Dashboard Tools

dashboard_metrics

Retrieves key metrics and KPIs.

{
  type: 'function',
  function: {
    name: 'dashboard_metrics',
    description: 'Get dashboard metrics and KPIs',
    parameters: {
      type: 'object',
      properties: {
        scope: { type: 'string', enum: ['company', 'department', 'team'] },
        departmentId: { type: 'string' },
        metrics: {
          type: 'array',
          items: {
            type: 'string',
            enum: ['headcount', 'turnover', 'time_off', 'onboarding', 'engagement'],
          },
        },
      },
    },
  },
}

Example prompts:

  • "What's our current headcount?"
  • "Show me turnover metrics"
  • "Get department breakdown"

dashboard_insights

Generates AI insights from data.

{
  type: 'function',
  function: {
    name: 'dashboard_insights',
    description: 'Generate AI-powered insights from HR data',
    parameters: {
      type: 'object',
      properties: {
        focus: {
          type: 'string',
          enum: ['trends', 'anomalies', 'recommendations', 'all'],
        },
        timeRange: { type: 'string', enum: ['week', 'month', 'quarter', 'year'] },
      },
    },
  },
}

Example prompts:

  • "What are the trends in time-off usage?"
  • "Any unusual patterns this month?"
  • "Give me HR insights for Q4"

dashboard_pending_approvals

Lists pending items requiring action.

{
  type: 'function',
  function: {
    name: 'dashboard_pending_approvals',
    description: 'Get list of pending approvals and action items',
    parameters: {
      type: 'object',
      properties: {
        type: {
          type: 'string',
          enum: ['time_off', 'documents', 'workflows', 'all'],
        },
      },
    },
  },
}

Example prompts:

  • "What's pending my approval?"
  • "Show my action items"
  • "Any leave requests to approve?"

Organization Tools

org_explain

Generates narrative summary of org structure.

{
  type: 'function',
  function: {
    name: 'org_explain',
    description: 'Generate narrative summary of employee org structure',
    parameters: {
      type: 'object',
      properties: {
        employeeId: { type: 'string', description: 'Employee ID to explain' },
      },
      required: ['employeeId'],
    },
  },
}

Example prompts:

  • "Explain John's reporting structure"
  • "Who does Sarah report to?"
  • "Show me the org structure for employee #123"

org_validate

Validates org structure for issues.

{
  type: 'function',
  function: {
    name: 'org_validate',
    description: 'Validate organizational structure for issues',
    parameters: {
      type: 'object',
      properties: {
        checkCircular: { type: 'boolean', default: true },
        checkOrphans: { type: 'boolean', default: true },
        checkOverextended: { type: 'boolean', default: true },
        maxReportsThreshold: { type: 'number', default: 15 },
      },
    },
  },
}

Example prompts:

  • "Check for org structure issues"
  • "Validate the organization"
  • "Are there any orphaned employees?"

org_generate_structure

Generates suggested org structure from description.

{
  type: 'function',
  function: {
    name: 'org_generate_structure',
    description: 'Generate initial org structure from description',
    parameters: {
      type: 'object',
      properties: {
        description: { type: 'string', description: 'Description of company/team' },
        teamSize: { type: 'number' },
        style: { type: 'string', enum: ['hierarchical', 'flat', 'matrix', 'squads'] },
      },
      required: ['description'],
    },
  },
}

Example prompts:

  • "Suggest an org structure for a 20-person startup"
  • "Generate team structure for engineering"

System Prompt Pattern

The AI Chat uses a system prompt that includes:

const systemPrompt = `
You are an HR assistant for ${tenantName}.

## Your Capabilities
You can help users with:
- Employee management (create, search, transfer, terminate)
- Time-off requests (submit, check balance, approve, view calendar)
- Workflows (create onboarding/offboarding, track progress)
- Document search (find policies, answer questions)
- Dashboard (view metrics, insights, pending approvals)
- Organization (explain structure, validate, generate)

## Rules
1. For write operations, ALWAYS show a confirmation card first
2. Respect user permissions - only show actions they can perform
3. When searching, show relevant results with links
4. For errors, explain what went wrong and suggest solutions
5. If you can't help, offer to escalate to human HR

## Context
Current user: ${userName} (${userRole})
Tenant: ${tenantName}
Date: ${currentDate}

## Available Tools
${toolDefinitions}
`

Feature Registration Checklist

When adding a new feature to HRMS, ensure AI Chat integration:

1. Define AI Tool

// In packages/hrms-ai/src/tools/{feature}-tools.ts
export const FEATURE_TOOLS = [
  {
    type: 'function',
    function: {
      name: 'feature_action',
      description: 'Clear description of what this does',
      parameters: {
        type: 'object',
        properties: { /* ... */ },
        required: ['requiredField'],
      },
    },
  },
]

2. Implement Tool Handler

// In packages/hrms-ai/src/handlers/{feature}-handler.ts
export async function handleFeatureAction(
  params: FeatureActionParams,
  context: AIContext
): Promise<ToolResult> {
  // 1. Validate permissions
  if (!context.user.can('feature:action')) {
    return { error: 'Permission denied', code: 'FORBIDDEN' }
  }

  // 2. Validate input
  const validated = featureSchema.parse(params)

  // 3. Execute action
  const result = await featureService.performAction(validated, context.tenantId)

  // 4. Return result for widget
  return {
    success: true,
    data: result,
    widget: {
      type: 'result',
      title: 'Action Completed',
      fields: [
        { label: 'Name', value: result.name },
        { label: 'ID', value: result.id },
      ],
      link: `/features/${result.id}`,
    },
  }
}

3. Define Chat Widgets

// Widget templates for this feature
export const FEATURE_WIDGETS = {
  confirmation: {
    title: 'Create Feature',
    fields: ['name', 'description', 'type'],
  },
  progress: {
    steps: ['Validating', 'Creating', 'Notifying'],
  },
  result: {
    title: 'Feature Created',
    fields: ['name', 'id', 'createdAt'],
    linkTemplate: '/features/{id}',
  },
  error: {
    messages: {
      FORBIDDEN: 'You do not have permission to perform this action',
      NOT_FOUND: 'The requested resource was not found',
      VALIDATION: 'Please check your input and try again',
    },
  },
}

4. Update System Prompt

Add feature context to the system prompt:

// In packages/hrms-ai/src/prompts/system.ts
export const FEATURE_CONTEXT = `
## Feature Management
You can help users create and manage features:
- Create new features with 'feature_create'
- Search features with 'feature_search'
- Update features with 'feature_update'
- Delete features with 'feature_delete'
`

5. Register in Tool Registry

// In packages/hrms-ai/src/tools/registry.ts
import { FEATURE_TOOLS, handleFeatureAction } from './feature-tools'

export const TOOL_REGISTRY = {
  // ... existing tools
  feature_action: handleFeatureAction,
}

export const ALL_TOOLS = [
  // ... existing tools
  ...FEATURE_TOOLS,
]

6. Add Permission Checks

// Ensure feature permissions are checked
const FEATURE_PERMISSIONS = {
  feature_create: 'feature:create',
  feature_update: 'feature:update',
  feature_delete: 'feature:delete',
  feature_search: 'feature:read',
}

7. Add Audit Logging

// Log all AI-initiated actions
await auditLog.create({
  action: 'feature_create',
  actor: context.userId,
  actorType: 'ai_chat',
  resource: 'feature',
  resourceId: result.id,
  tenantId: context.tenantId,
  metadata: { params },
})

Security Considerations

Permission Enforcement

  • Every tool checks user permissions before execution
  • Tools only return data the user has access to
  • Write operations require explicit confirmation

Tenant Isolation

  • All queries include tenantId from context
  • AI cannot access cross-tenant data
  • System prompt includes tenant context

Audit Trail

  • All AI Chat actions are logged
  • Logs include: user, action, params, result, timestamp
  • Failed attempts are also logged

Rate Limiting

  • 100 requests per 15 minutes per user
  • Separate limits for read vs write operations
  • Progressive backoff for repeated failures

Error Messages

Error CodeUser MessageRecovery Action
FORBIDDEN"You don't have permission to {action}"Contact admin
NOT_FOUND"Couldn't find {resource}"Check ID/name
VALIDATION"Please check: {details}"Fix input
RATE_LIMITED"Too many requests. Please wait."Wait and retry
SERVER_ERROR"Something went wrong"Try again
CONFLICT"{resource} already exists"Use different name

Tag Tools

tag_create

Creates a new tag in a category.

{
  type: 'function',
  function: {
    name: 'tag_create',
    description: 'Create a new tag in a category',
    parameters: {
      type: 'object',
      properties: {
        categoryId: { type: 'string', description: 'Tag category ID' },
        name: { type: 'string', description: 'Tag name' },
        color: { type: 'string', description: 'Tag color (hex)' },
        description: { type: 'string', description: 'Tag description' },
      },
      required: ['categoryId', 'name'],
    },
  },
}

Example prompts:

  • "Create a 'Senior' tag in the skills category"
  • "Add a new tag called 'Remote Worker'"
  • "Create tag for Python skills"

Confirmation card fields:

  • Category, Tag Name, Color, Description

tag_category_create

Creates a new tag category.

{
  type: 'function',
  function: {
    name: 'tag_category_create',
    description: 'Create a new tag category',
    parameters: {
      type: 'object',
      properties: {
        name: { type: 'string', description: 'Category name (e.g., skills, status, department)' },
        assetTypes: {
          type: 'array',
          items: { type: 'string', enum: ['employee', 'document', 'goal'] },
          description: 'Entity types this category applies to',
        },
        color: { type: 'string', description: 'Default color for tags in this category (hex)' },
      },
      required: ['name', 'assetTypes'],
    },
  },
}

Example prompts:

  • "Create a new tag category for programming languages"
  • "Add a skills category for employee tags"
  • "Set up document classification tags"

tag_assign

Assigns a tag to an employee or document.

{
  type: 'function',
  function: {
    name: 'tag_assign',
    description: 'Assign a tag to an employee, document, or goal',
    parameters: {
      type: 'object',
      properties: {
        tagId: { type: 'string', description: 'Tag ID to assign' },
        entityType: { type: 'string', enum: ['employee', 'document', 'goal'] },
        entityId: { type: 'string', description: 'Employee, Document, or Goal ID' },
      },
      required: ['tagId', 'entityType', 'entityId'],
    },
  },
}

Example prompts:

  • "Tag John as a Python expert"
  • "Add the 'Confidential' tag to this document"
  • "Mark Sarah with the Senior Developer skill"

Confirmation card fields:

  • Tag Name, Entity Type, Entity Name

tag_remove

Removes a tag from an entity.

{
  type: 'function',
  function: {
    name: 'tag_remove',
    description: 'Remove a tag from an employee, document, or goal',
    parameters: {
      type: 'object',
      properties: {
        tagId: { type: 'string', description: 'Tag ID to remove' },
        entityType: { type: 'string', enum: ['employee', 'document', 'goal'] },
        entityId: { type: 'string', description: 'Employee, Document, or Goal ID' },
      },
      required: ['tagId', 'entityType', 'entityId'],
    },
  },
}

Example prompts:

  • "Remove the 'Remote' tag from Mike"
  • "Untag this document as confidential"
  • "Remove the contractor tag from Sarah"

Searches for entities by tag.

{
  type: 'function',
  function: {
    name: 'tag_search',
    description: 'Search for employees, documents, or goals by tag',
    parameters: {
      type: 'object',
      properties: {
        tagId: { type: 'string', description: 'Tag ID to search by' },
        tagName: { type: 'string', description: 'Tag name to search by (alternative to tagId)' },
        entityType: { type: 'string', enum: ['employee', 'document', 'goal', 'all'] },
      },
      required: [],
    },
  },
}

Example prompts:

  • "Find all employees tagged as Python developers"
  • "Show me documents with the Policy tag"
  • "Who has the Senior Engineer skill?"

Result: List of matching entities with links


tag_list

Lists all tags in a category.

{
  type: 'function',
  function: {
    name: 'tag_list',
    description: 'List all tags in a category or all categories',
    parameters: {
      type: 'object',
      properties: {
        categoryId: { type: 'string', description: 'Optional category ID to filter' },
        entityType: { type: 'string', enum: ['employee', 'document', 'goal', 'all'] },
      },
    },
  },
}

Example prompts:

  • "What skill tags do we have?"
  • "List all document tags"
  • "Show me available employee tags"

Custom Field Tools

custom_field_get

Gets custom field values for an entity.

{
  type: 'function',
  function: {
    name: 'custom_field_get',
    description: 'Get custom field values for an employee, department, team, or goal',
    parameters: {
      type: 'object',
      properties: {
        entityType: { type: 'string', enum: ['employee', 'department', 'team', 'goal'] },
        entityId: { type: 'string', description: 'Entity ID' },
        fieldName: { type: 'string', description: 'Specific field name (optional, omit for all fields)' },
      },
      required: ['entityType', 'entityId'],
    },
  },
}

Example prompts:

  • "What custom fields does John have?"
  • "Get the T-shirt size for employee Sarah"
  • "Show custom data for the Engineering department"

Result: Info card with custom field values


custom_field_set

Sets a custom field value for an entity.

{
  type: 'function',
  function: {
    name: 'custom_field_set',
    description: 'Set a custom field value for an employee, department, team, or goal',
    parameters: {
      type: 'object',
      properties: {
        entityType: { type: 'string', enum: ['employee', 'department', 'team', 'goal'] },
        entityId: { type: 'string', description: 'Entity ID' },
        fieldName: { type: 'string', description: 'Field name' },
        value: { type: 'string', description: 'Field value' },
      },
      required: ['entityType', 'entityId', 'fieldName', 'value'],
    },
  },
}

Example prompts:

  • "Set John's T-shirt size to Large"
  • "Update the cost center for Engineering to CC-5000"
  • "Set Mike's employee ID to EMP-12345"

Confirmation card fields:

  • Entity Name, Field Name, Old Value (if exists), New Value

custom_field_list_definitions

Lists available custom field definitions.

{
  type: 'function',
  function: {
    name: 'custom_field_list_definitions',
    description: 'List all custom field definitions for an entity type',
    parameters: {
      type: 'object',
      properties: {
        entityType: { type: 'string', enum: ['employee', 'department', 'team', 'goal', 'all'] },
      },
    },
  },
}

Example prompts:

  • "What custom fields can employees have?"
  • "List all custom field definitions"
  • "Show me the available custom fields for departments"

Result: List of field definitions with types and validation rules


Searches entities by custom field value.

{
  type: 'function',
  function: {
    name: 'custom_field_search',
    description: 'Search for entities by custom field value',
    parameters: {
      type: 'object',
      properties: {
        entityType: { type: 'string', enum: ['employee', 'department', 'team', 'goal'] },
        fieldName: { type: 'string', description: 'Field name to search' },
        value: { type: 'string', description: 'Value to search for' },
        matchType: { type: 'string', enum: ['exact', 'contains'], default: 'contains' },
      },
      required: ['entityType', 'fieldName', 'value'],
    },
  },
}

Example prompts:

  • "Find all employees with T-shirt size Large"
  • "Search for departments in cost center CC-5000"
  • "Who has employee ID starting with EMP-1?"

Result: List of matching entities with links


Document Access Control Tools

document_share

Shares a document with specific users, teams, or departments.

{
  type: 'function',
  function: {
    name: 'document_share',
    description: 'Share a document with specific users, teams, or departments',
    parameters: {
      type: 'object',
      properties: {
        documentId: { type: 'string', description: 'Document ID' },
        accessType: { type: 'string', enum: ['user', 'team', 'department', 'role'] },
        targetId: { type: 'string', description: 'User/Team/Department/Role ID' },
        permission: { type: 'string', enum: ['view', 'download', 'edit'], default: 'view' },
        expiresAt: { type: 'string', format: 'date-time', description: 'Optional expiration date' },
      },
      required: ['documentId', 'accessType', 'targetId'],
    },
  },
}

Example prompts:

  • "Share this document with John"
  • "Give the Engineering team access to the handbook"
  • "Share the policy document with all managers"
  • "Grant edit access to this file for Sarah"

Confirmation card fields:

  • Document Name, Share With (target name), Permission Level, Expiration

document_revoke_access

Revokes document access from a user, team, or department.

{
  type: 'function',
  function: {
    name: 'document_revoke_access',
    description: 'Revoke document access from a user, team, or department',
    parameters: {
      type: 'object',
      properties: {
        documentId: { type: 'string', description: 'Document ID' },
        accessType: { type: 'string', enum: ['user', 'team', 'department', 'role'] },
        targetId: { type: 'string', description: 'User/Team/Department/Role ID' },
      },
      required: ['documentId', 'accessType', 'targetId'],
    },
  },
}

Example prompts:

  • "Remove John's access to this document"
  • "Revoke the Engineering team's access to the handbook"
  • "Stop sharing this file with the Sales department"

Confirmation card fields:

  • Document Name, Remove Access From

document_visibility_set

Sets the visibility level for a document.

{
  type: 'function',
  function: {
    name: 'document_visibility_set',
    description: 'Set the visibility level for a document',
    parameters: {
      type: 'object',
      properties: {
        documentId: { type: 'string', description: 'Document ID' },
        visibility: {
          type: 'string',
          enum: ['private', 'team', 'department', 'managers', 'company', 'custom'],
          description: 'Visibility level',
        },
      },
      required: ['documentId', 'visibility'],
    },
  },
}

Example prompts:

  • "Make this document private"
  • "Set visibility to company-wide for the employee handbook"
  • "Restrict this document to my team only"
  • "Make this document visible to all managers"

Confirmation card fields:

  • Document Name, Current Visibility, New Visibility

document_access_list

Lists who has access to a document.

{
  type: 'function',
  function: {
    name: 'document_access_list',
    description: 'List all users, teams, and departments with access to a document',
    parameters: {
      type: 'object',
      properties: {
        documentId: { type: 'string', description: 'Document ID' },
      },
      required: ['documentId'],
    },
  },
}

Example prompts:

  • "Who has access to this document?"
  • "Show me the sharing settings for the handbook"
  • "List everyone who can view this file"

Result: Info card with visibility level and access list


Dashboard Tools

dashboard_create

Creates a new dashboard.

{
  type: 'function',
  function: {
    name: 'dashboard_create',
    description: 'Create a new personal or shared dashboard',
    parameters: {
      type: 'object',
      properties: {
        name: { type: 'string', description: 'Dashboard name' },
        description: { type: 'string', description: 'Dashboard description' },
        isDefault: { type: 'boolean', description: 'Set as default dashboard', default: false },
        widgets: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              type: {
                type: 'string',
                enum: ['employee_count', 'active_requests', 'pending_approvals', 'time_off_balance',
                       'headcount_trend', 'department_breakdown', 'time_off_calendar',
                       'upcoming_birthdays', 'new_hires', 'anniversaries', 'team_activity'],
              },
              title: { type: 'string' },
            },
          },
          description: 'Initial widgets to add',
        },
      },
      required: ['name'],
    },
  },
}

Example prompts:

  • "Create a new dashboard called 'HR Overview'"
  • "Set up a team dashboard with headcount and time-off widgets"
  • "Make me a dashboard to track new hires"

Confirmation card fields:

  • Dashboard Name, Description, Widget Count

dashboard_add_widget

Adds a widget to a dashboard.

{
  type: 'function',
  function: {
    name: 'dashboard_add_widget',
    description: 'Add a widget to a dashboard',
    parameters: {
      type: 'object',
      properties: {
        dashboardId: { type: 'string', description: 'Dashboard ID' },
        widgetType: {
          type: 'string',
          enum: ['employee_count', 'active_requests', 'pending_approvals', 'time_off_balance',
                 'headcount_trend', 'department_breakdown', 'time_off_calendar', 'attendance_chart',
                 'upcoming_birthdays', 'new_hires', 'anniversaries', 'recent_documents',
                 'team_activity', 'my_tasks', 'announcements', 'quick_actions'],
        },
        title: { type: 'string', description: 'Custom widget title' },
        config: {
          type: 'object',
          description: 'Widget-specific configuration',
          properties: {
            departmentId: { type: 'string' },
            teamId: { type: 'string' },
            dateRange: { type: 'string', enum: ['week', 'month', 'quarter', 'year'] },
            limit: { type: 'number' },
          },
        },
      },
      required: ['dashboardId', 'widgetType'],
    },
  },
}

Example prompts:

  • "Add a headcount widget to my dashboard"
  • "Put a time-off calendar on my HR dashboard"
  • "Add an employee count widget for Engineering"

Confirmation card fields:

  • Dashboard Name, Widget Type, Configuration

dashboard_share

Shares a dashboard with other users or teams.

{
  type: 'function',
  function: {
    name: 'dashboard_share',
    description: 'Share a dashboard with users, teams, or the whole company',
    parameters: {
      type: 'object',
      properties: {
        dashboardId: { type: 'string', description: 'Dashboard ID' },
        shareType: { type: 'string', enum: ['user', 'team', 'department', 'company'] },
        targetId: { type: 'string', description: 'User/Team/Department ID (not needed for company)' },
        permission: { type: 'string', enum: ['view', 'edit'], default: 'view' },
      },
      required: ['dashboardId', 'shareType'],
    },
  },
}

Example prompts:

  • "Share my HR dashboard with the management team"
  • "Give John access to view my dashboard"
  • "Make this dashboard available company-wide"

Confirmation card fields:

  • Dashboard Name, Share With, Permission Level

dashboard_list

Lists available dashboards for the user.

{
  type: 'function',
  function: {
    name: 'dashboard_list',
    description: 'List all dashboards available to the user',
    parameters: {
      type: 'object',
      properties: {
        includeShared: { type: 'boolean', description: 'Include dashboards shared with me', default: true },
      },
    },
  },
}

Example prompts:

  • "What dashboards do I have?"
  • "Show me my dashboards"
  • "List available dashboards"

Result: List of dashboards with links


Tool Endpoint Alignment (MVP)

The following documents the actual HRMS API endpoints used by AI tools in Phase 09:

employee_search

  • Endpoint: GET /api/v1/employees?search={query}&limit={limit}
  • MVP Limitation: Only query and limit parameters supported
  • Future (Phase 10+): departmentId, roleId, tags filtering

org_explain

  • Endpoint: GET /api/v1/org/employees/{id}/summary
  • MVP Response: Simplified structure without roles or crossFunctionalInvolvement
  • Full spec response documented in ai-integration.mdx will be expanded in Phase 10

timeoff_balance

  • Tool Name: timeoff_balance (not timeoff_check_balance)
  • Endpoint: GET /api/v1/timeoff/balances/{employeeId}
  • MVP Limitation: Returns array of balances per policy type

Response Shape Transformations

AI tools transform HRMS API responses to match expected tool output:

// timeoff_balance: API → Tool response transformation
{
  // API returns:
  data: [{ policy: { name, code }, entitled, used, pending, adjustment, carryOver }]

  // Tool transforms to:
  balances: [{ policyName, policyCode, entitled, used, pending, available }]
}

API Endpoints Required Before Phase 09

Verify these endpoints exist from earlier phases:

EndpointSource PhaseNotes
GET /api/v1/employeesPhase 02Needs search query param
GET /api/v1/org/employees/:id/summaryPhase 03New endpoint for org explain
GET /api/v1/timeoff/balances/:employeeIdPhase 05Balance lookup

On this page

AI Chat SpecificationCore PhilosophyAI-Native ArchitectureAIProvider ContextAI Chat ModesAI Action Card TypesAI Floating ButtonTyping Indicator ComponentQuick Actions ComponentChat Message ComponentChat UI ComponentsMessage TypesWidget SpecificationsAction Confirmation CardProgress WidgetResult Card (Success)Result Card (Error)Info CardAction Execution FlowRead Operations (No Confirmation)Write Operations (Requires Confirmation)Error Handling FlowAll AI Chat ToolsEmployee Management Toolsemployee_createemployee_searchemployee_transferemployee_terminateemployee_tagTime-Off Toolstimeoff_submittimeoff_check_balancetimeoff_approvetimeoff_team_calendartimeoff_cancelWorkflow Toolsworkflow_createworkflow_trackworkflow_complete_taskonboarding_initiateoffboarding_initiateDocument Toolsdocument_searchdocument_askdocument_uploadDashboard Toolsdashboard_metricsdashboard_insightsdashboard_pending_approvalsOrganization Toolsorg_explainorg_validateorg_generate_structureSystem Prompt PatternFeature Registration Checklist1. Define AI Tool2. Implement Tool Handler3. Define Chat Widgets4. Update System Prompt5. Register in Tool Registry6. Add Permission Checks7. Add Audit LoggingSecurity ConsiderationsPermission EnforcementTenant IsolationAudit TrailRate LimitingError MessagesTag Toolstag_createtag_category_createtag_assigntag_removetag_searchtag_listCustom Field Toolscustom_field_getcustom_field_setcustom_field_list_definitionscustom_field_searchDocument Access Control Toolsdocument_sharedocument_revoke_accessdocument_visibility_setdocument_access_listDashboard Toolsdashboard_createdashboard_add_widgetdashboard_sharedashboard_listTool Endpoint Alignment (MVP)employee_searchorg_explaintimeoff_balanceResponse Shape TransformationsAPI Endpoints Required Before Phase 09