// overview

AI layer overview

The staff7 AI layer is an intelligence interface built directly on top of the platform's live data. It lets users query their staffing, financial, and operational data in plain language — and act on it directly from the console.

AI Console
Terminal-style chat interface. Type questions or use structured /commands to load specific context.
Agentic actions
Approve leaves, update project status, assign consultants — directly from the console with a confirmation step.
RLS-aware queries
The agent uses your session JWT — it can only see your company's data. RLS enforces tenant isolation.
Bring your own model
Connect any Ollama-compatible model: local (privacy-first) or cloud (kimi-k2.5, llama3, mistral…).
// console

AI Console

The console is a terminal-style chat interface accessible from the sidebar under Agents. It maintains conversation history within the session and streams responses in real time.

/
Command menu
Type / to open the structured command browser. Select a command to pre-load the right data context.
Streaming cursor
Responses appear character-by-character. The ▋ cursor shows the agent is still generating.
Clear history
Clear button resets the conversation history. The agent starts fresh without prior context.
Agent status bar
Shows which sub-agents are ONLINE / THINKING / IDLE at a glance.
The console uses SSE (Server-Sent Events) to stream the Ollama response. The route at /api/ai proxies to Ollama and reformats NDJSON chunks as SSE events. Actions use a separate PUT /api/ai endpoint.
/
// commands

Commands

Commands pre-load specific Supabase context before sending your message. Without a command, the agent loads a general staff + profitability summary.

/staff.benchAvailable consultants + occupancy + pending leaves + profitability summarystaff
/staff.allAll consultants + active projects + full profitabilitystaff
/leave.checkPending leave requests with consultant detailsleave
/fin.marginProject margins and daily rates + profitability view per consultantfin
/timesheet.weekCurrent week timesheet status — all consultantstimesheet
/profit.analysisFull profitability analysis: margins, target gaps, freelance vs employeeprofit
Commands use prefix matching/staff.bench and /staff.all both load the /staff context. The sub-label after the dot is passed as a hint to focus the response.
// actions

Agentic actions

The action agent uses native tool calling (kimi-k2.5 supports it natively) to detect write intentions and execute them with a confirmation step.

Intent detection
The router detects action keywords (approve, refuse, assign, update) and routes to the action agent.
Confirmation UI
A card appears showing the action and parameters. User must click CONFIRM before execution.
Activity log
Every executed action is written to the activity feed with a "via AI" tag — full audit trail.
Role-gated
Actions available to admin and super_admin only. Managers and consultants cannot trigger writes.
approve_leaveApprove a pending leave requestconsultant_name, leave_id?
refuse_leaveRefuse a pending leave requestconsultant_name, reason?
update_project_statusUpdate a project's statusproject_name, status
assign_consultantAssign a consultant to a projectconsultant_name, project_name, allocation?
// Example flow
User    > "approve Clara's leave"
ACTION  > ⚠ Approve leave request
           consultant_name: Clara Kim
           [ CONFIRM ]  [ CANCEL ]

User    > CONFIRM
STAFF7  > ✓ Leave request approved for Clara Kim —
           CP from 2026-03-14 to 2026-03-18 (5 days).
// context

Live context injection

Every request to /api/ai fetches fresh data from Supabase and injects it into the system prompt. The agent always sees current data — no stale cache.

CommandTables / views queriedKey fields
/staffconsultant_occupancy, leave_requests, consultant_profitabilitystatus, contract_type, actual_cost, target_rate, occupancy_rate
/finproject_financials, consultant_profitabilitysold_rate, margin_pct, revenue, gross_margin
/profitconsultant_profitability, consultant_occupancyFull profitability + pre-computed summary aggregates
/timesheetconsultant_occupancy, timesheetsdate, value, status — current week only
/leaveleave_requests, consultant_occupancypending only, limit 30
// profitability

Profitability AI

The /profit.analysis command loads the richest context — the full consultant_profitability view plus pre-computed aggregates.

Margin analysis
"Which consultant is least profitable?" — sorted by margin % with full cost breakdown.
Target gap
"Who is not hitting their target rate?" — compares target vs actual cost, flags < 10% margin.
Freelance vs employee
"Average freelancer cost?" — contract type segmentation across all contexts.
Risk surface
"Under-occupied with low margin?" — cross-metric analysis combining occupancy and profitability.
// Pre-computed summary injected into /profit context
{
  total_consultants: 11,
  employees: 8,  freelances: 3,
  total_ca: 312000,  total_marge: 142000,
  avg_marge_pct: "34.2",
  below_target_count: 2,
  below_target: [
    { name: "David Mora",   tjm_cout: 680, tjm_cible: 700 },
    { name: "Lucas Martin", tjm_cout: 450, tjm_cible: 460 }
  ]
}
// privacy

Privacy & model choice

staff7 is designed around privacy-by-design. You choose where your data goes — local model or cloud API.

ModeData leaves your infra?Setup
Local OllamaNever — model runs on your serverInstall Ollama, set OLLAMA_HOST=http://localhost:11434
Ollama CloudYes — sent to Ollama Cloud APISet OLLAMA_HOST + OLLAMA_API_KEY
Any OpenAI-compat.Yes — sent to third-party APIPoint OLLAMA_HOST to any compatible endpoint
# .env.local — local model (privacy-first)
OLLAMA_HOST=http://localhost:11434
OLLAMA_MODEL=llama3.2:3b
OLLAMA_API_KEY=

# or cloud
OLLAMA_HOST=https://ollama.com
OLLAMA_MODEL=kimi-k2.5:cloud
OLLAMA_API_KEY=sk-...
// rls

RLS & tenant isolation

The AI query route does not use the service role key for reads. It uses the authenticated user's JWT — RLS applies to every agent query.

// /api/ai — JWT passthrough (query agent)
const userToken = req.headers.get('Authorization')?.replace('Bearer ', '')

// Supabase query — RLS applied via user token
const headers = {
  'apikey':        anonKey,
  'Authorization': `Bearer ${userToken}`,
}

// Action agent — service role AFTER role check
if (role !== 'admin' && role !== 'super_admin') return 403
// → executes with service role key
// mcp

MCP integration (roadmap)

The Model Context Protocol (MCP) is planned as the next evolution — standardising tool calls and enabling external integrations.

MCP server
FastAPI-based MCP server exposing tools: get_consultants, approve_leave, etc. — replacing direct REST calls.
External sources
Connect Google Calendar, Slack, or Pennylane as MCP tools alongside Supabase data.
Model-agnostic
MCP is a standard protocol. Any compatible model (Claude, GPT-4o, Gemini) can use the same tool definitions.
Auth passthrough
MCP server validates the JWT before executing any tool — same RLS isolation as current approach.
The current action agent already implements the core pattern — native tool calling with confirmation. MCP will standardise and extend this with external integrations.