Spotter Agent — Code Map
Module wiring
apps/api/src/ai/ai.module.ts— registers controller, orchestrator, runtime services, tool registry, and every leaf provider. Imports the resource modules whose services the leaves call.
Controller
apps/api/src/ai/agent/agent.controller.tsGET /organizations/:orgId/agent/usageGET /organizations/:orgId/agent/conversationsGET /organizations/:orgId/agent/conversations/:conversationIdPOST /organizations/:orgId/agent/messagesPOST /organizations/:orgId/agent/conversations/:conversationId/confirm/:toolUseIdPOST /organizations/:orgId/agent/conversations/:conversationId/pick/:toolUseIdPOST /organizations/:orgId/agent/conversations/:conversationId/undo/:toolUseId
Orchestration / runtime
apps/api/src/ai/agent/agent.orchestrator.ts—run,resume,resumeAfterPick,driveModelLoop,processToolUses,withCachedTail,computeCostUsdMicros.apps/api/src/ai/agent/agent.runtime.ts—AgentRuntimetype (orgId, clerkId, user, membership, role, locale, now, pageContext, abortSignal).apps/api/src/ai/agent/anthropic.client.ts— Anthropic SDK wrapper.DEFAULT_MODEL = 'claude-sonnet-4-5'.apps/api/src/ai/agent/context-builder.service.ts—STATIC_SYSTEM_PROMPT+ org/page blocks withcache_control.apps/api/src/ai/agent/conversations.service.ts— persistence: create, listForUser, getOwn, listMessages, listMessagesForReplay, appendMessage, insertToolExecution, updateToolExecutionStatus, listToolExecutionsForMessage, hasOtherPendingForMessage, touchAfterTurn, getToolExecutionByToolUseId.apps/api/src/ai/agent/rate-limit.service.ts—preCheck,getUsageSnapshot.apps/api/src/ai/agent/cost-tracker.service.ts—recordTurn,getOrgSpendTodayMicros.apps/api/src/ai/agent/audit.adapter.ts— bridges toaudit_logswithmetadata.agent: true.apps/api/src/ai/agent/compaction.service.ts—generateTitleIfMissing,compactIfNeeded. Haiku-driven, time-budgeted.apps/api/src/ai/agent/rag.service.ts—findAmbient, hybrid lex+semantic search across org entities.
Observability
apps/api/src/ai/agent/observability/agent-observability.service.ts—emit,logTurnFailure,logReplayViolation,newTraceId. Fans out to Pino + Sentry + PostHog.apps/api/src/ai/agent/observability/error-classifier.ts—classifyAgentError,ReplayIntegrityError.apps/api/src/ai/agent/observability/replay-validator.ts—validateReplay,validateAndRepairReplay.apps/api/src/ai/agent/observability/storage-snapshot.service.ts—@Cron(EVERY_DAY_AT_3AM)runSnapshot. Emitsagent.storage.snapshotevent.
Tool registry / runner
apps/api/src/ai/agent/tools/tool-registry.service.ts— discovers@AgentTool-decorated methods atonModuleInit, indexes by<router>.<action>, builds Anthropic tool definitions grouped by router.apps/api/src/ai/agent/tools/tool-runner.service.ts—execute({ router, action, rawInput, runtime }). RBAC defence, Zod validation, handler invocation, audit write, output → resourceId extraction.apps/api/src/ai/agent/tools/tool.types.ts—AgentToolMetadata,ToolHandler,ToolRunResult,ToolScope,ToolAuditMeta,ToolInverseMeta,AgentToolKind.apps/api/src/ai/agent/tools/decorators.ts—@AgentTool(opts). Stores metadata via Reflect.
Tool leaves (per router)
| File | Router | Actions |
|---|---|---|
apps/api/src/ai/agent/tools/leaves/read.tools.ts | read | get_current_context, programs_list, members_search, members_get, exercises_search, exercises_resolve_batch, ask_user_to_pick (user_picker), search_anything, lookup_by_id, workout_comments_in_program, workout_comments_for_assignment |
apps/api/src/ai/agent/tools/leaves/workouts.tools.ts | workouts | create (inverse: delete), update, set_sections, delete (destructive) |
apps/api/src/ai/agent/tools/leaves/programs.tools.ts | programs | create (inverse: delete), update, delete (destructive), enroll_member |
apps/api/src/ai/agent/tools/leaves/assignments.tools.ts | assignments | assign_personal, update, set_published, delete (destructive), mark_comments_read, bulk_preview, bulk_delete (destructive), bulk_publish (always) |
apps/api/src/ai/agent/tools/leaves/bookings.tools.ts | bookings | list_mine, attendance_summary, attendance_trend |
apps/api/src/ai/agent/tools/leaves/class-sessions.tools.ts | class_sessions | list_for_date, create (inverse: cancel), update, publish (inverse: unpublish), unpublish, cancel (destructive), bulk_preview, bulk_delete (destructive), bulk_publish (always) |
apps/api/src/ai/agent/tools/leaves/class-types.tools.ts | class_types | list_for_program |
apps/api/src/ai/agent/tools/leaves/analytics.tools.ts | analytics | revenue_summary, revenue_trend, members_summary, members_growth, at_risk_members, popular_classes, class_utilization, coach_overview, org_insights, plan_distribution, members_activation, workouts_summary |
apps/api/src/ai/agent/tools/leaves/tasks.tools.ts | tasks | list, create (inverse: delete), update, complete, delete (destructive) |
apps/api/src/ai/agent/tools/leaves/program-templates.tools.ts | program_templates | list, create, apply (always), from_history (always) |
apps/api/src/ai/agent/tools/leaves/forms.tools.ts | forms | list_pending_for_org, compliance_status_for_member |
apps/api/src/ai/agent/tools/leaves/bulk-tools.unit.spec.ts | (tests) | Bulk-tool unit tests. |
Total: 63 tools across 11 routers (as of FIT-161 phase 1; the original FIT-161 scoping called for 56 — drift +7 reflects post-ship additions).
Tool input/output schemas
libs/shared/src/lib/agent-schemas/index.ts— barrel.libs/shared/src/lib/agent-schemas/common.ts—AgentPageContext,AgentMessageRequest, conversation summary / detail / loaded message / loaded tool call.libs/shared/src/lib/agent-schemas/sse-events.ts— full SSE event discriminated union.libs/shared/src/lib/agent-schemas/tool-categories.ts—AGENT_ROUTERS, per-router*_ACTIONSenums,ToolSideEffect,ToolConfirmPolicy.libs/shared/src/lib/agent-schemas/read.ts— everyread.*input schema.libs/shared/src/lib/agent-schemas/workouts.ts,programs.ts,assignments.ts,bookings.ts,analytics.ts,class-sessions.ts,class-types.ts,tasks.ts,forms.ts— per-router input schemas.
Embeddings (supporting infra)
apps/api/src/ai/embeddings/embeddings.module.tsapps/api/src/ai/embeddings/embedding.service.ts— Voyagevoyage-multilingual-2client.apps/api/src/ai/embeddings/embedding-helper.tsapps/api/src/ai/embeddings/ai-cache.service.ts— keyed by(model, input_hash), persisted toai_cache.apps/api/src/ai/embeddings/ai.controller.tsapps/api/src/ai/embeddings/{workouts,programs,member-profiles}-embedding.{service,processor}.ts— domain embedding pipelines.apps/api/src/ai/embeddings/exercise-enrichment.{service,processor}.ts— exercise canonicalization.
Frontend
apps/web/src/components/agent/agent-launcher.tsxapps/web/src/components/agent/agent-sheet.tsxapps/web/src/components/agent/agent-sheet-mount.tsxapps/web/src/components/agent/composer.tsxapps/web/src/components/agent/message-list.tsxapps/web/src/components/agent/tool-call-card.tsxapps/web/src/components/agent/streaming-text.tsxapps/web/src/components/agent/usage-footer.tsxapps/web/src/components/agent/conversation-list.tsxapps/web/src/components/agent/suggested-prompts.tsxapps/web/src/providers/agent-provider.tsx— state machine, SSE reducer, conversation cache.
Schema
libs/db/src/lib/schema/agent.ts—ai_conversations,ai_messages,ai_tool_executions,ai_usage_daily+ relations.libs/db/src/lib/schema/ai-cache.ts—ai_cache(embeddings + enrichment).libs/db/src/lib/schema/enums.ts—aiMessageRole,aiToolStatusenums.libs/db/src/lib/schema/admin.ts—audit_logs(written viaAgentAuditAdapter).
Tier mapping
libs/shared/src/lib/constants/platform-tiers.ts—PLATFORM_TIER_MAPsource of truth foraiDailyBudgetUsdMicros.
Tests
apps/api/src/ai/agent/tools/leaves/bulk-tools.unit.spec.ts— bulk tool semantics.- Per-leaf and orchestrator unit tests (where present) live colocated.