Endpoint Flow
How a request travels from frontend to backend. Two flavors: persistence calls (Firebase Functions, sync) and chat calls (Cloud Run, streaming SSE).
Persistence calls (Firebase Functions)
Example: a manager creates a scheduled report.
Key files:
- Router mount:
functions/modules/ai-memory/endpoints/apis/router.ts - Sub-router:
functions/modules/ai-memory/endpoints/apis/ai-memory.router.ts - Auth middleware:
functions/shared/middleware/auth.middleware.ts - Company scope:
functions/shared/middleware/company-scope.middleware.ts - Request context:
functions/shared/infrastructure/request-context-from-token.ts
Notable: the RTDB write always commits; the Temporal call is best-effort. The handler returns temporalScheduled: false plus temporalError if Temporal was unreachable, but the task is still persisted. See MIA Task Lifecycle for reconciliation.
Chat calls (Cloud Run, streaming SSE)
Example: a user asks Mia "what was labor cost last week?"
Key files:
- Entrypoint:
functions/pivotAiAgent/index.ts(chatHandler, mounted at/api/chat+/api/chat-async) - Intent:
functions/pivotAiAgent/intent.ts - Tool loop:
functions/pivotAiAgent/pipeline.ts - Dispatcher:
functions/pivotAiAgent/tools/index.ts:192(executeTool) - URL builder:
functions/pivotAiAgent/tools/_endpoints.ts(getFunctionsUrl,authHeaders) - Workflows:
functions/pivotAiAgent/temporal/workflows.ts
Streaming protocol: SSE with Anthropic's content-block delta shape interleaved with custom event types — see Agent SDK: Streaming.
Exceptions to "tool → internal endpoint"
Two categories, only one of which is intentional:
Intentional — external API calls:
web_search,get_weather,lookup_pivot_helphit public third-party APIs (Brave, Open-Meteo, KB). No Pivot auth.
Tech debt — Admin-SDK fallbacks for RTDB paths without an endpoint:
create_shiftwritesWeeklySchedule/{cid}/{date}via Firebase REST?auth=. Schedule module has no "create published shift" endpoint yet. File carries aTODO(refacto-endpoint)comment.- Onboarding tools (
create_company,complete_onboarding, etc.) use endpoints for everything that has one (company create, patch, employee create); they only fall back to Admin SDK for onboarding-specific paths that aren't on the public API —AIOnboardingSessions/,Users/{uid}/signupPhase,Companies/{cid}/businessProfile, etc. The createCompany.ts source comment makes this explicit.
See Agent SDK: exceptions for the full breakdown.
A fetch interceptor in functions/pivotAiAgent/firebase.ts patches globalThis.fetch so RTDB-hostname URLs automatically use the Admin SDK when service-account credentials are present — this makes the stopgap Admin-SDK writes work transparently without explicit branching in each tool.
Why two runtimes?
Firebase Functions has a 9-minute execution ceiling and no native streaming. The data path can run 5–30 seconds and the chat path is SSE-streamed — both incompatible. Cloud Run gives us streaming + longer execution; Firebase Functions stays the right tool for short CRUD over RTDB.