Skip to main content

ai-orchestrator-service — Event Schemas

Companion to: DOMAIN_MODEL.md · APPLICATION_LOGIC.md · Standards: 04 Event-Driven Architecture · NAMING

All events follow the platform CloudEvents-compatible envelope (see 04-event-driven-architecture.md §3). Subjects follow melmastoon.<service>.<aggregate>.<verb-past-tense>.v<n>. Service prefix is ai_orchestrator. Schemas are version-controlled in @ghasi/event-envelope/schemas/ai-orchestrator/ and registered with the platform schema registry. Breaking changes require a v<n+1> topic.

1. Envelope (reference)

interface DomainEvent<T> {
id: string; // 'evt_<ULID>'
subject: string; // 'melmastoon.ai_orchestrator.inference.completed.v1'
source: 'ai-orchestrator-service';
specVersion: '1.0';
type: string; // mirrors subject
time: string; // ISO-8601
tenantId: string; // 'tnt_<ULID>'
correlation: { traceId: string; requestId: string; causationId?: string };
data: T; // event-specific payload (schemas below)
retention: 'operational' | 'regulated' | 'audit';
schemaUri: string; // 'https://schemas.melmastoon.ghasi.io/ai-orchestrator/inference-completed.v1.json'
}

2. Retention classes

ClassTTLExamples
operational30 dinference.requested, inference.cached_hit, model.deployment_changed
regulated7 y (BigQuery long-term)inference.completed, hitl.gate_decided, budget.exceeded, moderation.flagged (carry decisions/cost/risk material)
audit7 y (audit-service)All events with HITL outcomes, all prompt.version_published, all edge_model.manifest_updated

3. Events Published

3.1 melmastoon.ai_orchestrator.inference.requested.v1

Fires on every accepted call to /api/v1/ai/complete, /embed, /rag/query, /vision, /transcribe (one per accepted request).

interface InferenceRequested {
requestId: string; // 'ifr_<ULID>'
capability: string; // 'pricing.suggest'
callerService: string;
callerSurface?: 'consumer' | 'tenant-booking' | 'backoffice';
inputBytes: number;
inputHash: string; // 'sha256:...'
redactedInputHash: string;
promptVersionId?: string;
abBucket?: number; // 0..99 (sticky-by-tenant)
context: { local: boolean; regionPin?: string; timeoutMs: number };
}

Retention: operational.

3.2 melmastoon.ai_orchestrator.inference.completed.v1

Fires on every successful return (including cache hit and deterministic fallback paths).

interface InferenceCompleted {
requestId: string; // 'ifr_...'
resultId: string; // 'ifs_...'
capability: string;
promptVersionId?: string;
model: { provider: 'vertex'|'anthropic'|'openai'|'onnx-edge'; name: string; version?: string };
tokens: { input: number; output: number };
costMicros: number;
latencyMs: number;
cacheHit: boolean;
fallbackApplied: boolean;
fallbackReason?: 'budget_hard_cap' | 'all_providers_unhealthy' | 'moderation_block' | 'schema_invalid';
hitl?: { gateId: string; slaDeadline: string };
provenanceId: string;
outputSummary?: string; // ≤ 256 chars; never raw PII
}

Retention: regulated.

3.3 melmastoon.ai_orchestrator.inference.failed.v1

Fires when the fallback chain is exhausted or the request is otherwise unrecoverable.

interface InferenceFailed {
requestId: string;
capability: string;
errorCode: string; // 'MELMASTOON.AI.PROVIDER_UNAVAILABLE' etc.
attempts: { provider: string; modelName: string; errorCode: string; latencyMs: number }[];
}

Retention: regulated.

3.4 melmastoon.ai_orchestrator.inference.cached_hit.v1

Lightweight signal for the cache-hit dashboard. Also produced as part of inference.completed.v1 flag, but a separate event keeps the cache-rate fact table simple.

interface InferenceCachedHit {
requestId: string;
capability: string;
inputHash: string;
cachedAt: string; // when the original result was cached
ttlRemainingSec: number;
}

Retention: operational.

3.5 Capability-specific signal events

These wrap the validated structured output of a capability call so subscribers don't need to re-fetch the artifact. They are emitted in addition to inference.completed.v1 and carry the same requestId for correlation.

melmastoon.ai_orchestrator.suggestion.dynamic_pricing.v1

interface DynamicPricingSuggested {
requestId: string;
propertyId: string;
roomTypeId: string;
date: string; // ISO date
baselineAmountMicros: number;
suggestedAmountMicros: number;
currency: string; // ISO 4217
deviationPctFromBaseline: number;
rationale: string;
confidence: number;
hitl: { required: boolean; gateId?: string };
provenanceId: string;
}

Retention: regulated.

melmastoon.ai_orchestrator.suggestion.demand_forecast.v1

interface DemandForecast {
propertyId: string;
horizonDays: 30 | 60 | 90;
buckets: { date: string; expectedOccupancyPct: number; p10: number; p90: number }[];
notes?: string;
provenanceId: string;
}

Retention: regulated.

melmastoon.ai_orchestrator.suggestion.housekeeping_routing.v1

interface HousekeepingRouting {
propertyId: string;
shiftId: string;
routes: { staffId: string; orderedTaskIds: string[]; estimatedMinutes: number }[];
hitl: { required: boolean; gateId?: string };
provenanceId: string;
}

Retention: operational.

melmastoon.ai_orchestrator.suggestion.shift_optimization.v1

interface ShiftOptimization {
propertyId: string;
weekStartDate: string;
shifts: { staffId: string; date: string; startHHMM: string; endHHMM: string; role: string }[];
hitl: { required: boolean; gateId?: string };
provenanceId: string;
}

Retention: operational.

melmastoon.ai_orchestrator.anomaly.detected.v1

interface AnomalyDetected {
domain: 'booking'|'payment'|'lock'|'login'|'occupancy';
subjectRef: { kind: string; id: string };
riskScore: number; // 0..1
signals: string[]; // ['rapid_fire_booking', 'same_ip', ...]
recommendedAction: 'monitor'|'hold'|'block'|'page';
hitl: { required: boolean; gateId?: string };
provenanceId: string;
}

Retention: regulated.

melmastoon.ai_orchestrator.upsell.recommended.v1

interface UpsellRecommended {
reservationId: string;
guestId: string;
offers: { kind: 'room_upgrade'|'breakfast'|'late_checkout'|'transfer'|'spa'; priceMicros: number; currency: string; rationale: string }[];
channelHint: 'email'|'sms'|'whatsapp'|'in_app';
provenanceId: string;
}

Retention: operational.

melmastoon.ai_orchestrator.message.drafted.v1

interface MessageDrafted {
intent: 'pre_arrival'|'post_stay'|'apology'|'upsell'|'reminder'|'custom';
targetRecipientId: string;
locale: string; // 'ps' | 'fa-AF' | 'ar' | 'en' | 'fr'
subject?: string;
bodyDraft: string; // post-moderation; HITL-gated
hitl: { required: true; gateId: string };
provenanceId: string;
}

Retention: regulated.

melmastoon.ai_orchestrator.review.summarized.v1

interface ReviewSummarized {
propertyId: string;
windowDays: 30 | 90 | 365;
reviewCount: number;
summary: { themes: string[]; sentiment: 'pos'|'neg'|'mixed'; actionable: string[]; topQuotes: string[] };
provenanceId: string;
}

Retention: operational.

melmastoon.ai_orchestrator.ocr.completed.v1

interface OcrCompleted {
guestId?: string; // pre-create flow may not have id yet
documentRef: { kind: 'passport'|'national_id'|'drivers_license'; uri: string };
extractedFields: { fullName: string; dateOfBirth: string; documentNumber: string; nationality: string; expiry: string };
fieldConfidences: Record<string, number>;
hitl: { required: true; gateId: string };
provenanceId: string;
}

Retention: regulated. PII fields are encrypted at rest in audit-service.

melmastoon.ai_orchestrator.transcription.completed.v1

interface TranscriptionCompleted {
audioRef: { uri: string; durationMs: number };
transcript: string;
language: string;
intent?: { action: string; params: Record<string, string> };
provenanceId: string;
}

Retention: operational.

melmastoon.ai_orchestrator.description.drafted.v1

interface DescriptionDrafted {
targetRef: { kind: 'property'|'room_type'|'amenity'|'policy'; id: string };
locale: string;
draft: string;
hitl: { required: true; gateId: string };
provenanceId: string;
}

Retention: operational.

melmastoon.ai_orchestrator.translation.drafted.v1

interface TranslationDrafted {
sourceRef: { kind: string; id: string };
sourceLocale: string;
targetLocale: string;
draft: string;
untranslatableTerms: string[];
hitl: { required: true; gateId: string };
provenanceId: string;
}

Retention: operational.

3.6 melmastoon.ai_orchestrator.hitl.gate_opened.v1

interface HitlGateOpened {
gateId: string; // 'hgt_...'
capability: string;
artifactRef: { kind: string; id: string };
reviewerRoles: string[];
slaDeadline: string;
draftJson: unknown; // size-bounded (≤ 16 KB)
}

Retention: audit.

3.7 melmastoon.ai_orchestrator.hitl.gate_decided.v1

interface HitlGateDecided {
gateId: string;
decisionId: string; // 'dec_...'
outcome: 'accepted' | 'modified' | 'rejected';
modifiedJson?: unknown;
justification?: string;
reviewerUserId: string;
reviewerRole: string;
decidedAt: string;
auto: boolean; // true on timeout-default
}

Retention: audit. Sibling services subscribe to this event to commit the gated state change (e.g., pricing-service publishes the price; notification-service dispatches the message).

3.8 melmastoon.ai_orchestrator.budget.warning.v1

interface BudgetWarning {
scope: { kind: 'tenant_total' | 'capability' | 'feature'; key?: string };
periodKey: string;
tokensUsed: number;
tokensCap: number;
costMicrosUsed: number;
costMicrosCap: number;
pctConsumed: number; // 0.80..0.99
}

Retention: operational.

3.9 melmastoon.ai_orchestrator.budget.exceeded.v1

interface BudgetExceeded {
scope: { kind: 'tenant_total' | 'capability' | 'feature'; key?: string };
periodKey: string;
trippedAt: string;
fallbackBehavior: 'deterministic' | 'refuse';
resetsAt: string;
}

Retention: regulated.

3.10 melmastoon.ai_orchestrator.eval.run_completed.v1

interface EvalRunCompleted {
runId: string; // 'evr_...'
suiteId: string; // 'eva_...'
promptVersionId: string;
modelRef: { provider: string; name: string; version?: string };
scores: Record<string, number>;
verdict: 'green' | 'red' | 'inconclusive';
comparison?: { baselineVersionId: string; deltas: Record<string, number> };
durationMs: number;
}

Retention: audit.

3.11 melmastoon.ai_orchestrator.prompt.version_published.v1

interface PromptVersionPublished {
promptVersionId: string; // 'pmv_...'
canonicalCode: string; // 'PRMP_PRICING_001_v3'
capabilityKey: string;
deprecatedVersionId?: string;
evalRunId: string;
publishedAt: string;
publishedBy: string; // 'usr_...'
}

Retention: audit.

3.12 melmastoon.ai_orchestrator.model.deployment_changed.v1

interface ModelDeploymentChanged {
changeKind: 'health' | 'traffic_share' | 'lifecycle';
modelRef: { provider: string; name: string; version?: string };
region?: string;
before: { health?: string; trafficSharePct?: number; status?: string };
after: { health?: string; trafficSharePct?: number; status?: string };
reason?: string; // e.g. 'circuit_open_5_consecutive_errors'
}

Retention: operational.

3.13 melmastoon.ai_orchestrator.edge_model.manifest_updated.v1

interface EdgeModelManifestUpdated {
manifestId: string; // 'emm_...'
version: string; // semver
supersedesId?: string;
modelKeys: string[];
publishedAt: string;
}

Retention: audit.

3.14 melmastoon.ai_orchestrator.moderation.flagged.v1

interface ModerationFlagged {
requestId: string;
capability: string;
side: 'input' | 'output';
verdict: 'flag_low' | 'flag_high' | 'block';
axes: Record<string, number>; // 'hate', 'sexual', 'dangerous', 'self_harm', 'pii_exposed'
action: 'allowed_with_warning' | 'blocked';
}

Retention: regulated.

4. Events Consumed

These events trigger inference jobs. Subscriber names follow the convention ai-orchestrator.<topic> (e.g., ai-orchestrator.melmastoon.reservation.booking.confirmed.v1).

Source eventTriggered capabilityNotes
melmastoon.reservation.booking.confirmed.v1upsell.recommend (immediate); schedule upsell.recommend (T-48h via Cloud Scheduler)One inference per reservation
melmastoon.reservation.booking.cancelled.v1anomaly.detect (cancellation pattern signal)Aggregated daily for tenant
melmastoon.iam.user.login_failed.v1anomaly.detect (credential stuffing)Edge classifier on tenant tally; cloud explanation if riskScore ≥ 0.7
melmastoon.payment.transaction.failed.v1anomaly.detect (payment fraud)Edge classifier; HITL on auto-block
melmastoon.payment.intent.captured.v1anomaly.detect (rapid-fire pattern)Sliding window per IP / payment method
melmastoon.lock_integration.key_credential.issued.v1anomaly.detect (key issuance pattern)
melmastoon.lock_integration.key_credential.not_returned.v1anomaly.detect (key-not-returned > 24 h)Daily aggregation job
melmastoon.housekeeping.task.assigned.v1 (batch flush)housekeeping.routeOne inference per shift assignment batch
melmastoon.inventory.allocation.committed.v1 (occupancy ≥ 70%)pricing.suggest for tomorrowThreshold filter applied in subscriber
melmastoon.tenant.guest.erasure_requested.v1Purge per-tenant embeddings + cached prompt artifacts + redacted inference rows referencing the guest within 7 daysSaga participant; emits melmastoon.audit.guest.erasure_acknowledged.v1
melmastoon.tenant.suspended.v1Flip per-tenant capability allowlist to read-onlyGateway refuses inference with MELMASTOON.TENANT.SUSPENDED
melmastoon.tenant.created.v1Bootstrap default BudgetCounter rows for tenant + standard RAGCorpus namespaces (policies, faq, sop, amenity)

5. Schema evolution

  • Additive only within a v<n> topic: new optional fields permitted; required-field changes, type changes, enum-value removals require v<n+1>.
  • New topic version is published in parallel for ≥ 30 days. Subscribers migrate; the old topic is then drained and retired.
  • The schema registry CI gate fails any PR that publishes a breaking change without a topic bump.

6. Idempotency on consumption

  • Inbox table dedupes by Pub/Sub message.id.
  • Effective key for AI-triggered inference is (source.subject, source.event.id, capability) so the same source event won't fire two pricing.suggest calls.
  • Capability-specific events carry requestId so downstream subscribers (e.g., notification-service consuming message.drafted.v1) dedupe on that.

7. Sample envelope (full)

{
"id": "evt_01H8...",
"subject": "melmastoon.ai_orchestrator.suggestion.dynamic_pricing.v1",
"source": "ai-orchestrator-service",
"specVersion": "1.0",
"type": "melmastoon.ai_orchestrator.suggestion.dynamic_pricing.v1",
"time": "2026-05-12T01:31:09.412Z",
"tenantId": "tnt_01H8...",
"correlation": { "traceId": "00-...-00", "requestId": "req_01H8...", "causationId": "evt_01H8...source" },
"data": {
"requestId": "ifr_01H8...",
"propertyId": "ppt_01H8...",
"roomTypeId": "rmt_01H8...",
"date": "2026-05-13",
"baselineAmountMicros": 4500000000,
"suggestedAmountMicros": 4725000000,
"currency": "USD",
"deviationPctFromBaseline": 0.05,
"rationale": "Occupancy 78% with shoulder-season trend; +5% recommended.",
"confidence": 0.74,
"hitl": { "required": true, "gateId": "hgt_01H8..." },
"provenanceId": "prv_p_01H8..."
},
"retention": "regulated",
"schemaUri": "https://schemas.melmastoon.ghasi.io/ai-orchestrator/suggestion-dynamic-pricing.v1.json"
}