Your handler receives one *nevo.Event per delivery. Switch on event.Type
and call the matching accessor — only the accessor matching the event’s
type returns non-nil.
func handle(ctx context.Context, e *nevo.Event) error {
switch e.Type {
case nevo.EventWebhookReceived:
wh := e.Webhook()
fmt.Println(wh.Method, wh.Path)
case nevo.EventEmailReceived:
em := e.Email()
fmt.Println("from", em.From, "->", em.Subject)
case nevo.EventSlackEvent:
sl := e.Slack()
fmt.Println(sl.UserID, "said", sl.Text)
case nevo.EventCronFired:
cr := e.Cron()
fmt.Println("cron fired:", cr.CronExpr)
}
return nil
}
Fields
| Field | Type | Notes |
|---|---|---|
ID | string | ULID. Stable across live + replay. |
Type | string | See constants below. |
Origin | string | "live" or "replay". Use for idempotency. |
CreatedAt | time.Time | UTC. |
Channel | Channel | { ID, Label, Type }. |
Data | map[string]any | Raw source payload — always populated. |
PromptReady | string | LLM-ready text rendering. |
PromptReadyVersion | int | Renderer version stamp. |
Type constants
const (
EventWebhookReceived = "webhook.received"
EventEmailReceived = "email.received"
EventSlackEvent = "slack.event"
EventCronFired = "cron.fired"
)
Accessors
Each returns nil unless the event’s type matches. Safe to check and use
inline with the if ptr := e.Foo(); ptr != nil idiom.
Webhook() → *WebhookData
type WebhookData struct {
Method string
Path string
Headers map[string]string
BodyEncoding string // "json" | "text" | "base64"
Body any // JSON-decoded when BodyEncoding == "json"
BodyRawB64 string // raw bytes base64-encoded
BodySizeBytes int
}
Email() → *EmailData
type EmailData struct {
From string
To []string
CC []string
BCC []string
Subject string
Text string
HTML string
MessageID string
Attachments []Attachment
ReceivedAt *time.Time
}
Slack() → *SlackData
type SlackData struct {
TeamID string
TeamName string
EventType string // "app_mention" | "message" | …
EventTs string // also used for threading
ChannelID string
UserID string
Text string
ThreadTs string // set when the message is already in a thread
Raw map[string]any // full outer Slack event preserved verbatim
}
Cron() → *CronData
type CronData struct {
ScheduleID string
CronExpr string
Timezone string
ScheduledAt time.Time
FiredAt time.Time
Payload map[string]any // static JSON attached to the schedule
}
See cron template tokens if your payload uses {{…}} markers.
Immutability
Event is populated once and never mutated by the SDK. Treat it as
read-only from handler code.
Prompt-ready
event.PromptReady is a pre-rendered text string useful when a model is the next hop. Ignore it if you don’t need it. See Prompt-ready.