Skip to content

Normalized Events

Every connector in Kairosis produces NormalizedEvent[]. This is the only output type. The schema is defined in @kairosis/events-core and shared across Kairosis and all downstream consumers.

import { NormalizedEventSchema } from '@kairosis/events-core';
// inferred type
type NormalizedEvent = z.infer<typeof NormalizedEventSchema>;

A NormalizedEvent contains:

{
id: string; // unique event ID (UUID)
type: string; // routing key — e.g. 'github.commit.pushed'
workspaceId: string; // tenant identifier
occurredAt: string; // ISO 8601 timestamp
source: string; // connector ID — e.g. 'github'
actor: {
id: string; // source-system user ID
name?: string;
email?: string;
avatarUrl?: string;
};
subject: {
id: string; // the thing the event is about
type: string; // e.g. 'pull_request', 'commit', 'message'
url?: string;
};
payload: Record<string, unknown>; // connector-specific, Zod-validated
}

Each event package defines Zod schemas for connector-specific payloads:

// @kairosis/github-events
import { GithubCommitPushedPayload } from '@kairosis/github-events';
const payload = GithubCommitPushedPayload.parse(event.payload);
// payload.commits, payload.ref, payload.repository, ...

Routing keys are defined as constants in each event package:

import { GithubEventType } from '@kairosis/github-events';
GithubEventType.COMMIT_PUSHED // 'github.commit.pushed'
GithubEventType.PR_OPENED // 'github.pr.opened'
GithubEventType.PR_MERGED // 'github.pr.merged'
GithubEventType.ISSUE_OPENED // 'github.issue.opened'
PackageEvents
@kairosis/events-coreNormalizedEvent, ActorSchema, SubjectSchema, RoutingKey
@kairosis/github-eventscommit, PR, issue events
@kairosis/slack-eventsmessage, reaction, channel events
@kairosis/email-eventsemail received/sent events
@kairosis/calendar-eventsevent created/updated/cancelled
@kairosis/browser-eventspage view, tab focus events
@kairosis/terminal-eventscommand executed events
@kairosis/health-eventshealth metric events
@kairosis/location-eventslocation update events
@kairosis/obsidian-eventsnote created/updated events
@kairosis/notion-eventspage/block change events
@kairosis/synthesized-eventsAI-synthesized higher-order events

Every event must be validated with NormalizedEventSchema.parse() before being published. Connectors never bypass this step.

// always
const event = NormalizedEventSchema.parse(raw);
await publisher.publish(event);
// never
await publisher.publish(raw);