Skip to main content

Data Model: Slack Bot AG-UI Migration

Date: 2026-04-14 Spec: spec.md

Entities​

SSEEvent (Updated)​

Represents a parsed AG-UI Server-Sent Event from the dynamic agents backend.

FieldTypeDescription
typeSSEEventType (enum)Event type (RUN_STARTED, TEXT_MESSAGE_CONTENT, etc.)
delta`strNone`
message_id`strNone`
tool_call_id`strNone`
tool_call_name`strNone`
run_id`strNone`
thread_id`strNone`
outcome`strNone`
interrupt`dictNone`
message`strNone`
name`strNone`
value`AnyNone`
steps`listNone`
snapshot`dictNone`

State transitions: None (SSEEvent is a value object, not stateful).

ChatRequest (Slack Bot Side)​

Request payload sent from the Slack bot to the dynamic agents backend.

FieldTypeRequiredDescription
messagestrYesUser's message text
conversation_idstrYesUUID v5 derived from Slack thread_ts
agent_idstrYesDynamic agent config ID from channel config
trace_id`strNone`No

ResumeRequest​

Request payload for resuming after HITL interrupt.

FieldTypeRequiredDescription
agent_idstrYesSame agent_id as the interrupted stream
conversation_idstrYesSame conversation_id as the interrupted stream
form_datastrYesJSON string of form field values, or rejection message
trace_id`strNone`No

ChannelConfig (Updated)​

Configuration for a Slack channel's bot behavior.

FieldTypeRequiredDefaultDescription
namestrYesβ€”Human-readable channel name
ai_enabledboolNoTrueWhether the bot responds in this channel
agent_id`strNone`NoNone (falls back to defaults.default_agent_id)
custom_prompt`strNone`NoNone
qandaQandaConfigNoDefaultQ&A mode configuration
ai_alertsAIAlertsConfigNoDefaultAI alert processing configuration
otherOtherConfigNoDefaultJira, escalation, delete admin config

New in this migration: agent_id field.

GlobalDefaults (Updated)​

FieldTypeDefaultDescription
default_agent_id`strNone`None
(all existing fields)β€”β€”response_style_instruction, prompts, etc.

New in this migration: default_agent_id field.

HITLInterrupt​

Parsed HITL interrupt from AG-UI RUN_FINISHED event.

FieldTypeDescription
interrupt_idstrUnique identifier for this interrupt (from interrupt.id)
reasonstrAlways "human_input"
promptstrHuman-readable description of what input is needed
fieldslist[InterruptField]Form field definitions
agentstrName of the agent requesting input

InterruptField​

A single form field in a HITL interrupt.

FieldTypeDescription
field_namestrMachine-readable field identifier
field_labelstrHuman-readable label
field_description`strNone`
field_typestrOne of: text, select, multiselect, boolean, number, url, email
field_values`list[str]None`
requiredboolWhether the field is required
default_value`strNone`
placeholder`strNone`

ConversationId (Value Object)​

PropertyValue
FormatUUID v5
Namespaceuuid5(NAMESPACE_URL, "slack.caipe.io") β€” constant
NameSlack thread_ts string
DeterminismSame thread_ts always produces the same UUID

SessionManager Caches (Simplified)​

CacheKeyValueTTL
_user_info_cacheuser_idSlack user info dict600s
_skipped_cachethread_tsSkip reason string300s
_escalated_threadsthread_tsBoolean (set membership)No TTL

Removed caches: _context_cache (conversation IDs are now computed, not cached), _trace_cache (trace_id is conversation_id in AG-UI).

Relationships​

ChannelConfig ──has── agent_id ──resolves to── DynamicAgentConfig (backend)
SlackThread ──generates── ConversationId (UUID v5 from thread_ts)
ConversationId ──maps to── LangGraph thread_id (backend)
SSEClient ──sends── ChatRequest ──to── /api/v1/chat/stream/start
SSEClient ──receives── SSEEvent stream
SSEEvent(RUN_FINISHED, interrupt) ──parsed as── HITLInterrupt
HITLInterrupt ──rendered as── Slack Block Kit form
FormSubmission ──sends── ResumeRequest ──to── /api/v1/chat/stream/resume