Documentation
¶
Overview ¶
Package protocol is the Go client for the smooth-operator WebSocket protocol.
It mirrors the TypeScript reference implementation: a transport-agnostic Client that correlates server events back to client actions by requestId, exposes the non-streaming actions (create session, get session, get messages, ping) as plain request/response calls, and models a send_message turn as a streaming MessageTurn — a channel of typed events plus an awaitable terminal eventual_response. HITL resumes (confirm_tool_action, verify_otp) route their resumed stream back into the original turn by requestId.
Index ¶
- Constants
- Variables
- func IsKnownEventType(t EventType) bool
- type ActionEnvelope
- type ActionEnvelopeAction
- type ActionType
- type Checkpoint
- type CheckpointMetadata
- type Citation
- type Client
- func (c *Client) Close() error
- func (c *Client) ConfirmToolAction(p ConfirmToolActionParams) error
- func (c *Client) Connect(ctx context.Context) error
- func (c *Client) CreateConversationSession(ctx context.Context, p CreateConversationSessionParams) (CreateConversationSessionResponse, error)
- func (c *Client) GetMessages(ctx context.Context, p GetMessagesParams) (GetMessagesResponse, error)
- func (c *Client) GetSession(ctx context.Context, p GetSessionParams) (GetSessionResponse, error)
- func (c *Client) OnEvent(fn func(ServerEvent)) (unsubscribe func())
- func (c *Client) Ping(ctx context.Context) (int, error)
- func (c *Client) SendMessage(p SendMessageParams) *MessageTurn
- func (c *Client) VerifyOTP(p VerifyOTPParams) error
- type ConfirmToolActionParams
- type ConfirmToolActionRequest
- type ConfirmToolActionResponse
- type ContentItem
- type ContentItemType
- type Conversation
- type ConversationAnalyticsJSON
- type ConversationMessage
- type ConversationMessageContent
- type ConversationMessageContentStructuredResponse
- type ConversationMessageDirection
- type ConversationMessageFrom
- type ConversationMessageTo
- type ConversationMetadataJSON
- type ConversationPlatform
- type CreateConversationSessionParams
- type CreateConversationSessionRequest
- type CreateConversationSessionResponse
- type Error
- type ErrorData
- type ErrorDataError
- type ErrorError
- type ErrorObject
- type EventEnvelope
- type EventEnvelopeType
- type EventType
- type EventualResponse
- type EventualResponseData
- type EventualResponseDataData
- type EventualResponseDataDataCitationsElem
- type GeneralAgentResponse
- type GeneralAgentResponseResolutionStatus
- type GetMessagesParams
- type GetMessagesRequest
- type GetMessagesResponse
- type GetSessionParams
- type GetSessionRequest
- type GetSessionResponse
- type ImmediateResponse
- type ImmediateResponseData
- type Keepalive
- type KeepaliveData
- type Message
- type MessageAnalyticsJSON
- type MessageContent
- type MessageContentStructuredResponse
- type MessageContentText
- type MessageConversationID
- type MessageDirection
- type MessageExternalID
- type MessageFrom
- type MessageFromName
- type MessageMetadataJSON
- type MessageOrganizationID
- type MessageTo
- type MessageToName
- type MessageTurn
- type MessageUpdatedAt
- type OTPInvalid
- type OTPInvalidData
- type OTPInvalidDataData
- type OTPInvalidDataDataError
- type OTPSent
- type OTPSentData
- type OTPSentDataData
- type OTPSentDataDataChannel
- type OTPVerificationRequired
- type OTPVerificationRequiredData
- type OTPVerificationRequiredDataData
- type OTPVerificationRequiredDataDataAvailableChannelsElem
- type OTPVerified
- type OTPVerifiedData
- type OTPVerifiedDataData
- type Options
- type Participant
- type ParticipantBrowserFingerprint
- type ParticipantBrowserInfo
- type ParticipantCrmContactID
- type ParticipantEmail
- type ParticipantExternalID
- type ParticipantInternalID
- type ParticipantMetadataJSON
- type ParticipantPhone
- type ParticipantType
- type PingRequest
- type Pong
- type PongData
- type PongResponse
- type ProtocolError
- type RequestAuthContext
- type RequestMetadata
- type ResponseStatus
- type SendMessageParams
- type SendMessageRequest
- type SendMessageResponse
- type ServerEvent
- func (e ServerEvent) AsError() (Error, error)
- func (e ServerEvent) AsEventualResponse() (EventualResponse, error)
- func (e ServerEvent) AsImmediateResponse() (ImmediateResponse, error)
- func (e ServerEvent) AsKeepalive() (Keepalive, error)
- func (e ServerEvent) AsOTPInvalid() (OTPInvalid, error)
- func (e ServerEvent) AsOTPSent() (OTPSent, error)
- func (e ServerEvent) AsOTPVerificationRequired() (OTPVerificationRequired, error)
- func (e ServerEvent) AsOTPVerified() (OTPVerified, error)
- func (e ServerEvent) AsPong() (Pong, error)
- func (e ServerEvent) AsStreamChunk() (StreamChunk, error)
- func (e ServerEvent) AsStreamToken() (StreamToken, error)
- func (e ServerEvent) AsWriteConfirmationRequired() (WriteConfirmationRequired, error)
- func (e ServerEvent) IsTerminal() bool
- type Session
- type SessionEndedAt
- type SessionMetadata
- type SessionStatus
- type StreamChunk
- type StreamChunkData
- type StreamChunkDataState
- type StreamChunkDataStatePendingOTPVerification
- type StreamChunkDataStatePendingWriteConfirmation
- type StreamToken
- type StreamTokenData
- type Transport
- type TurnTimeoutError
- type UnknownEventError
- type Validator
- type VerifyOTPParams
- type VerifyOTPRequest
- type VerifyOTPResponse
- type WebSocketTransport
- type WriteConfirmationRequired
- type WriteConfirmationRequiredData
- type WriteConfirmationRequiredDataData
Constants ¶
const DefaultTurnTimeout = 120 * time.Second
DefaultTurnTimeout bounds a streaming send_message turn: if the server accepts the message but never emits a terminal eventual_response / error within this window, the turn settles with a *TurnTimeoutError instead of hanging forever. Override via Options.TurnTimeout (set it to a negative value to disable).
Variables ¶
var ErrTransportClosed = errors.New("smooth-agent: transport closed")
ErrTransportClosed is returned by Send when the transport is no longer open.
Functions ¶
func IsKnownEventType ¶
IsKnownEventType reports whether t is a recognised server event discriminator.
Types ¶
type ActionEnvelope ¶
type ActionEnvelope struct {
// The action to perform.
Action ActionEnvelopeAction `json:"action"`
// Client-generated correlation ID. Will be echoed back on all related server
// events. Should be unique per in-flight request. If omitted the server may
// generate one, but correlating responses becomes the client's problem.
RequestID *string `json:"requestId,omitempty,omitzero"`
AdditionalProperties interface{} `mapstructure:",remain"`
}
Base shape for every client-to-server WebSocket frame. The `action` field is a snake_case verb that selects the handler. `requestId` is chosen by the client and echoed back on all related server events so the client can correlate responses to pending requests.
type ActionEnvelopeAction ¶
type ActionEnvelopeAction string
const ActionEnvelopeActionConfirmToolAction ActionEnvelopeAction = "confirm_tool_action"
const ActionEnvelopeActionCreateConversationSession ActionEnvelopeAction = "create_conversation_session"
const ActionEnvelopeActionGetConversationMessages ActionEnvelopeAction = "get_conversation_messages"
const ActionEnvelopeActionGetSession ActionEnvelopeAction = "get_session"
const ActionEnvelopeActionPing ActionEnvelopeAction = "ping"
const ActionEnvelopeActionSendMessage ActionEnvelopeAction = "send_message"
const ActionEnvelopeActionVerifyOTP ActionEnvelopeAction = "verify_otp"
type ActionType ¶
type ActionType string
ActionType is the client→server `action` discriminator carried on every action frame.
const ( ActionCreateConversationSession ActionType = "create_conversation_session" ActionSendMessage ActionType = "send_message" ActionGetSession ActionType = "get_session" ActionGetConversationMessages ActionType = "get_conversation_messages" ActionConfirmToolAction ActionType = "confirm_tool_action" ActionVerifyOTP ActionType = "verify_otp" ActionPing ActionType = "ping" )
All client→server action discriminator values.
type Checkpoint ¶
type Checkpoint struct {
// The agent whose state is captured in this checkpoint.
AgentID string `json:"agentId"`
// ISO 8601 timestamp when the checkpoint was created.
CreatedAt time.Time `json:"createdAt"`
// Unique checkpoint identifier (UUID v4).
ID string `json:"id"`
// Agent loop iteration counter at the time the checkpoint was taken.
Iteration int `json:"iteration"`
// Arbitrary string key/value metadata attached to this checkpoint (e.g. phase
// name, bead ID).
Metadata CheckpointMetadata `json:"metadata,omitempty,omitzero"`
// smooth-operator workflow thread identifier this checkpoint belongs to. Matches
// `Session.threadId` for the associated session.
ThreadID string `json:"threadId"`
}
A point-in-time snapshot of a smooth-operator agent's state. Checkpoints are written by the agent runtime and are used to resume execution after interruptions (Lambda cold starts, HITL pauses, network errors). Corresponds to the `Checkpoint` struct in the smooth-operator Rust crate.
type CheckpointMetadata ¶
Arbitrary string key/value metadata attached to this checkpoint (e.g. phase name, bead ID).
type Citation ¶
type Citation struct {
// Stable identifier of the cited source document (the knowledge-base
// `document_id`). Used to deduplicate citations within a turn.
ID string `json:"id"`
// Relevance score of this source for the turn's query (the knowledge-base
// similarity score). Higher is more relevant.
Score float64 `json:"score"`
// The retrieved chunk text that grounded the answer, truncated to a bounded
// length for display.
Snippet string `json:"snippet"`
// Human-readable label for the source — typically the document's source path or,
// for web-sourced docs, the URL/title.
Title string `json:"title"`
// Canonical link to the source, when one exists. For GitHub-sourced documents
// this is the blob/issue URL stamped onto the document's `source` at ingest (see
// CONNECTORS.md). Absent for sources with no web location (e.g. uploaded files).
URL *string `json:"url,omitempty,omitzero"`
}
A source the agent used to ground its answer. Each citation points back at one retrieved knowledge-base document — the chunk the model read, plus enough metadata to render an attribution link. Citations are collected by the runtime from the documents that actually grounded a turn (the auto-injected `[Relevant knowledge]` context and any `knowledge_search` tool results) and attached to the terminal `eventual_response`. For GitHub-sourced documents `url` is the blob/issue URL; documents without a web source omit it.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a transport-agnostic smooth-operator protocol client.
It is safe for concurrent use. Construct it with New, call Connect, then issue actions. A single read loop dispatches inbound frames to the waiting request, active turn, or unsolicited-event listeners.
func (*Client) Close ¶
Close shuts the client down: it closes the transport and fails every in-flight request and turn.
func (*Client) ConfirmToolAction ¶
func (c *Client) ConfirmToolAction(p ConfirmToolActionParams) error
ConfirmToolAction approves or rejects a pending tool write, resuming the paused turn identified by p.RequestID. The resumed stream flows back into that turn.
func (*Client) CreateConversationSession ¶
func (c *Client) CreateConversationSession(ctx context.Context, p CreateConversationSessionParams) (CreateConversationSessionResponse, error)
CreateConversationSession starts a new conversation session and returns the session descriptor carried in the immediate_response.
func (*Client) GetMessages ¶
func (c *Client) GetMessages(ctx context.Context, p GetMessagesParams) (GetMessagesResponse, error)
GetMessages fetches a page of conversation messages.
func (*Client) GetSession ¶
func (c *Client) GetSession(ctx context.Context, p GetSessionParams) (GetSessionResponse, error)
GetSession fetches a session snapshot by ID.
func (*Client) OnEvent ¶
func (c *Client) OnEvent(fn func(ServerEvent)) (unsubscribe func())
OnEvent registers a listener for unsolicited / uncorrelated server events (e.g. keepalive, server push). It returns an unsubscribe function.
func (*Client) SendMessage ¶
func (c *Client) SendMessage(p SendMessageParams) *MessageTurn
SendMessage submits a user message and returns a MessageTurn. Range over turn.Events() to receive each streamed event in order, or call turn.Wait(ctx) to block for the terminal eventual_response.
func (*Client) VerifyOTP ¶
func (c *Client) VerifyOTP(p VerifyOTPParams) error
VerifyOTP submits an OTP code, resuming the paused turn identified by p.RequestID. The resumed stream flows back into that turn.
type ConfirmToolActionParams ¶
type ConfirmToolActionParams struct {
SessionID string `json:"sessionId"`
// RequestID must match the write_confirmation_required event being answered.
RequestID string `json:"requestId"`
Approved bool `json:"approved"`
}
ConfirmToolActionParams holds the caller-supplied fields for ConfirmToolAction.
type ConfirmToolActionRequest ¶
type ConfirmToolActionRequest struct {
// Action discriminator.
Action string `json:"action"`
// True to allow the tool call to proceed; false to reject it. On rejection the
// agent workflow resumes with an informational context message.
Approved bool `json:"approved"`
// Must match the `requestId` from the `write_confirmation_required` event being
// responded to. This is how the server correlates the confirmation back to the
// paused workflow.
RequestID string `json:"requestId"`
// Session ID of the paused session.
SessionID string `json:"sessionId"`
}
Fields sent by the client to approve or reject a pending tool write.
type ConfirmToolActionResponse ¶
type ConfirmToolActionResponse map[string]interface{}
No dedicated response — the workflow continuation is signalled by resumed streaming events.
type ContentItem ¶
type ContentItem struct {
// The text content (required when type = `text`).
Text *string `json:"text,omitempty,omitzero"`
// Content item type discriminator.
Type ContentItemType `json:"type"`
}
A single content element within a message. Currently only `text` items are defined; additional types (image, file, tool_result) may be added in future protocol versions.
type ContentItemType ¶
type ContentItemType string
const ContentItemTypeText ContentItemType = "text"
type Conversation ¶
type Conversation struct {
// Analytics and scoring data aggregated from messages in this conversation.
AnalyticsJSON ConversationAnalyticsJSON `json:"analyticsJson,omitempty,omitzero"`
// ISO 8601 timestamp when the conversation was created.
CreatedAt time.Time `json:"createdAt"`
// Unique conversation identifier.
ID string `json:"id"`
// Client-provided key that prevents duplicate conversations from being created
// for the same logical thread.
IdempotencyKey string `json:"idempotencyKey"`
// Arbitrary key/value metadata attached to the conversation (e.g. campaign
// source, CRM fields).
MetadataJSON ConversationMetadataJSON `json:"metadataJson,omitempty,omitzero"`
// Human-readable display name for the conversation.
Name string `json:"name"`
// The organization that owns this conversation.
OrganizationID string `json:"organizationId"`
// The channel on which this conversation takes place.
Platform ConversationPlatform `json:"platform"`
// ISO 8601 timestamp when the conversation was last updated.
UpdatedAt time.Time `json:"updatedAt"`
}
A conversation thread between participants (users, AI agents, or human agents). Corresponds to a row in the `conversations` table. Platform indicates the channel on which the conversation takes place.
type ConversationAnalyticsJSON ¶
type ConversationAnalyticsJSON map[string]interface{}
Analytics and scoring data aggregated from messages in this conversation.
type ConversationMessage ¶
type ConversationMessage struct {
// Message payload. `text` contains the plain-text form; `structuredResponse`
// contains parsed agent output when present.
Content ConversationMessageContent `json:"content"`
// ISO 8601 timestamp when the message was created.
CreatedAt time.Time `json:"createdAt"`
// Message direction: `inbound` = from user, `outbound` = from agent.
Direction ConversationMessageDirection `json:"direction"`
// Abbreviated sender descriptor.
From *ConversationMessageFrom `json:"from,omitempty,omitzero"`
// Unique message ID.
ID string `json:"id"`
// Abbreviated recipient descriptor.
To *ConversationMessageTo `json:"to,omitempty,omitzero"`
}
A single message as returned on the wire. This is a subset of the full `Message` domain object — it omits server-only fields (metadataJson, analyticsJson) and includes abbreviated participant descriptors.
type ConversationMessageContent ¶
type ConversationMessageContent struct {
// Structured agent response (shape depends on agent template).
StructuredResponse *ConversationMessageContentStructuredResponse `json:"structuredResponse,omitempty,omitzero"`
// Plain-text content.
Text *string `json:"text,omitempty,omitzero"`
}
Message payload. `text` contains the plain-text form; `structuredResponse` contains parsed agent output when present.
type ConversationMessageContentStructuredResponse ¶
type ConversationMessageContentStructuredResponse map[string]interface{}
Structured agent response (shape depends on agent template).
type ConversationMessageDirection ¶
type ConversationMessageDirection string
const ConversationMessageDirectionInbound ConversationMessageDirection = "inbound"
const ConversationMessageDirectionOutbound ConversationMessageDirection = "outbound"
type ConversationMessageFrom ¶
type ConversationMessageFrom struct {
// ID corresponds to the JSON schema field "id".
ID string `json:"id"`
// Name corresponds to the JSON schema field "name".
Name *string `json:"name,omitempty,omitzero"`
// Type corresponds to the JSON schema field "type".
Type string `json:"type"`
}
Abbreviated sender descriptor.
type ConversationMessageTo ¶
type ConversationMessageTo struct {
// ID corresponds to the JSON schema field "id".
ID string `json:"id"`
// Name corresponds to the JSON schema field "name".
Name *string `json:"name,omitempty,omitzero"`
// Type corresponds to the JSON schema field "type".
Type string `json:"type"`
}
Abbreviated recipient descriptor.
type ConversationMetadataJSON ¶
type ConversationMetadataJSON map[string]interface{}
Arbitrary key/value metadata attached to the conversation (e.g. campaign source, CRM fields).
type ConversationPlatform ¶
type ConversationPlatform string
const ConversationPlatformDiscord ConversationPlatform = "discord"
const ConversationPlatformEmail ConversationPlatform = "email"
const ConversationPlatformInstagram ConversationPlatform = "instagram"
const ConversationPlatformMessenger ConversationPlatform = "messenger"
const ConversationPlatformPhone ConversationPlatform = "phone"
const ConversationPlatformSlack ConversationPlatform = "slack"
const ConversationPlatformSms ConversationPlatform = "sms"
const ConversationPlatformTiktok ConversationPlatform = "tiktok"
const ConversationPlatformWeb ConversationPlatform = "web"
const ConversationPlatformWhatsapp ConversationPlatform = "whatsapp"
type CreateConversationSessionParams ¶
type CreateConversationSessionParams struct {
AgentID string `json:"agentId"`
UserName string `json:"userName,omitempty"`
UserEmail string `json:"userEmail,omitempty"`
BrowserFingerprint string `json:"browserFingerprint,omitempty"`
Metadata map[string]interface{} `json:"metadata,omitempty"`
AuthContext *RequestAuthContext `json:"authContext,omitempty"`
}
CreateConversationSessionParams holds the caller-supplied fields for CreateConversationSession (action + requestId are filled in by the client).
type CreateConversationSessionRequest ¶
type CreateConversationSessionRequest struct {
// Action discriminator.
Action string `json:"action"`
// UUID of the agent to start a session with.
AgentID string `json:"agentId"`
// Pre-auth context for HMAC-based identity verification. When provided, the
// server can skip OTP flows by verifying the HMAC signature instead.
AuthContext *RequestAuthContext `json:"authContext,omitempty,omitzero"`
// Browser fingerprint string (e.g. from ThumbmarkJS) used for anonymous user
// correlation across sessions.
BrowserFingerprint *string `json:"browserFingerprint,omitempty,omitzero"`
// Arbitrary key/value metadata to attach to the session.
Metadata RequestMetadata `json:"metadata,omitempty,omitzero"`
// Client-generated correlation ID echoed back on all related events.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Optional email address for the user participant.
UserEmail *string `json:"userEmail,omitempty,omitzero"`
// Optional display name for the user participant.
UserName *string `json:"userName,omitempty,omitzero"`
}
Fields sent by the client to open a new session.
type CreateConversationSessionResponse ¶
type CreateConversationSessionResponse struct {
// ID of the agent handling this session.
AgentID string `json:"agentId"`
// Display name of the agent.
AgentName string `json:"agentName"`
// Participant ID representing the AI agent in this conversation.
AgentParticipantID string `json:"agentParticipantId"`
// ID of the conversation created for this session.
ConversationID string `json:"conversationId"`
// Newly created session ID. Use this in all subsequent actions.
SessionID string `json:"sessionId"`
// Participant ID representing the user in this conversation.
UserParticipantID string `json:"userParticipantId"`
}
Data payload carried in the `immediate_response` event that acknowledges session creation.
type Error ¶
type Error struct {
// Full error payload.
Data ErrorData `json:"data"`
// Top-level error object (duplicate of `data.error`; kept for clients that
// pattern-match on the envelope-level `error` field).
Error *ErrorError `json:"error,omitempty,omitzero"`
// Echoes the `requestId` from the originating action, if applicable. Absent for
// server-initiated errors with no associated request.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `error`. Emitted when an unrecoverable error occurs during request processing. The nested `error` object shape (`{ code, message }`) is preserved for wire compatibility with clients that destructure `message.error.code`. `details` carries additional structured context when available.
type ErrorData ¶
type ErrorData struct {
// Optional additional structured error context (e.g. validation issues, partial
// results).
Details interface{} `json:"details,omitempty,omitzero"`
// The error descriptor (nested for wire backward-compatibility).
Error ErrorDataError `json:"error"`
// The request ID this error belongs to, if any.
RequestID *string `json:"requestId,omitempty,omitzero"`
}
Full error payload.
type ErrorDataError ¶
type ErrorDataError struct {
// Machine-readable error code (e.g. `SESSION_NOT_FOUND`, `RATE_LIMITED`,
// `VALIDATION_ERROR`, `INTERNAL_ERROR`).
Code string `json:"code"`
// Human-readable error description.
Message string `json:"message"`
}
The error descriptor (nested for wire backward-compatibility).
type ErrorError ¶
type ErrorError struct {
// Machine-readable error code.
Code string `json:"code"`
// Human-readable error description.
Message string `json:"message"`
}
Top-level error object (duplicate of `data.error`; kept for clients that pattern-match on the envelope-level `error` field).
type ErrorObject ¶
type ErrorObject struct {
// Machine-readable error code (e.g. `SESSION_NOT_FOUND`, `RATE_LIMITED`,
// `VALIDATION_ERROR`).
Code string `json:"code"`
// Human-readable error description.
Message string `json:"message"`
}
A structured error descriptor. Used in error events and nested inside event data payloads.
type EventEnvelope ¶
type EventEnvelope struct {
// Event-specific payload. Shape is defined by the per-event schema in `events/`.
Data interface{} `json:"data,omitempty,omitzero"`
// Present on `error` events.
Error *ErrorObject `json:"error,omitempty,omitzero"`
// Optional human-readable status description (used in `immediate_response` acks).
Message *string `json:"message,omitempty,omitzero"`
// Name of the workflow node that produced this event. Present on `stream_chunk`
// events.
Node *string `json:"node,omitempty,omitzero"`
// Echoes the `requestId` from the originating action. Absent for unsolicited
// server-push events.
RequestID *string `json:"requestId,omitempty,omitzero"`
// HTTP-like status code. 202 = acknowledged/in-progress; 200 = final success;
// 4xx/5xx = error conditions.
Status *int `json:"status,omitempty,omitzero"`
// Unix epoch milliseconds. Present on `pong` events and optionally on others.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// A streamed LLM token. Present on `stream_token` events.
Token *string `json:"token,omitempty,omitzero"`
// Identifies which event this frame carries.
Type EventEnvelopeType `json:"type"`
}
Base shape for every server-to-client WebSocket frame. `type` is a snake_case noun that identifies the event. `requestId` echoes the originating action's `requestId` where applicable (may be absent for unsolicited events such as `keepalive`). `status` uses HTTP-like codes: 202 = accepted/in-progress, 200 = final success, 4xx/5xx = error.
type EventEnvelopeType ¶
type EventEnvelopeType string
const EventEnvelopeTypeError EventEnvelopeType = "error"
const EventEnvelopeTypeEventualResponse EventEnvelopeType = "eventual_response"
const EventEnvelopeTypeImmediateResponse EventEnvelopeType = "immediate_response"
const EventEnvelopeTypeKeepalive EventEnvelopeType = "keepalive"
const EventEnvelopeTypeOTPInvalid EventEnvelopeType = "otp_invalid"
const EventEnvelopeTypeOTPSent EventEnvelopeType = "otp_sent"
const EventEnvelopeTypeOTPVerificationRequired EventEnvelopeType = "otp_verification_required"
const EventEnvelopeTypeOTPVerified EventEnvelopeType = "otp_verified"
const EventEnvelopeTypePong EventEnvelopeType = "pong"
const EventEnvelopeTypeStreamChunk EventEnvelopeType = "stream_chunk"
const EventEnvelopeTypeStreamToken EventEnvelopeType = "stream_token"
const EventEnvelopeTypeWriteConfirmationRequired EventEnvelopeType = "write_confirmation_required"
type EventType ¶
type EventType string
EventType is the server→client `type` discriminator carried on every event frame.
const ( EventImmediateResponse EventType = "immediate_response" EventEventualResponse EventType = "eventual_response" EventStreamChunk EventType = "stream_chunk" EventStreamToken EventType = "stream_token" EventKeepalive EventType = "keepalive" EventWriteConfirmationRequired EventType = "write_confirmation_required" EventOTPVerificationRequired EventType = "otp_verification_required" EventOTPSent EventType = "otp_sent" EventOTPVerified EventType = "otp_verified" EventOTPInvalid EventType = "otp_invalid" EventError EventType = "error" EventPong EventType = "pong" )
All server→client event type discriminator values.
type EventualResponse ¶
type EventualResponse struct {
// The terminal response payload.
Data EventualResponseData `json:"data"`
// Echoes the `requestId` from the originating `send_message` action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// HTTP-like status. Always 200 for a successful eventual response.
Status *int `json:"status,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `eventual_response`. The terminal event of a streaming turn. Emitted after the agent workflow completes and its output has been persisted. Clients should treat this as the authoritative final state for the turn and may discard intermediate `stream_chunk` / `stream_token` data. Status is always 200 on success.
type EventualResponseData ¶
type EventualResponseData struct {
// The final agent output.
Data EventualResponseDataData `json:"data"`
// The request ID this response belongs to.
RequestID string `json:"requestId"`
// HTTP-like status. Typically 200.
Status int `json:"status"`
}
The terminal response payload.
type EventualResponseDataData ¶
type EventualResponseDataData struct {
// The sources that grounded this answer, when any were retrieved. Collected by
// the runtime from the documents that actually grounded the turn — the
// auto-injected `[Relevant knowledge]` context and any `knowledge_search` tool
// results — deduplicated by source id and capped. Optional and back-compatible:
// absent when the turn used no knowledge sources. Each item is a `Citation` (see
// `domain/citation.schema.json`).
Citations []EventualResponseDataDataCitationsElem `json:"citations,omitempty,omitzero"`
// Human-readable escalation reason when `needsEscalation` is true.
EscalationReason *string `json:"escalationReason,omitempty,omitzero"`
// ID of the agent message as persisted to the `conversation_messages` table.
MessageID string `json:"messageId"`
// True if the agent flagged this conversation for human escalation.
NeedsEscalation *bool `json:"needsEscalation,omitempty,omitzero"`
// The structured agent response payload. Shape depends on the agent template.
// Clients should validate against a template-specific schema before rendering.
Response interface{} `json:"response"`
}
The final agent output.
type EventualResponseDataDataCitationsElem ¶
type EventualResponseDataDataCitationsElem struct {
// Stable identifier of the cited source document (the knowledge-base
// `document_id`). Used to deduplicate citations within a turn.
ID string `json:"id"`
// Relevance score of this source for the turn's query (the knowledge-base
// similarity score). Higher is more relevant.
Score float64 `json:"score"`
// The retrieved chunk text that grounded the answer, truncated to a bounded
// length for display.
Snippet string `json:"snippet"`
// Human-readable label for the source — typically the document's source path or,
// for web-sourced docs, the URL/title.
Title string `json:"title"`
// Canonical link to the source, when one exists. For GitHub-sourced documents
// this is the blob/issue URL stamped onto the document's `source` at ingest.
// Absent for sources with no web location.
URL *string `json:"url,omitempty,omitzero"`
}
A source the agent used to ground its answer (a `Citation` — see `domain/citation.schema.json`). For GitHub-sourced documents `url` is the blob/issue URL; documents without a web source omit it.
type GeneralAgentResponse ¶
type GeneralAgentResponse struct {
// Estimated customer happiness for this turn (0 = very unhappy, 1 = very happy).
CustomerHappinessScore float64 `json:"customerHappinessScore"`
// Estimated degree to which the customer's needs were met (0 = not met, 1 = fully
// met).
NeedsSatisfactionScore float64 `json:"needsSatisfactionScore"`
// One-sentence summary of what the user requested.
RequestSummary string `json:"requestSummary"`
// The agent's assessment of where the conversation stands after this turn.
ResolutionStatus GeneralAgentResponseResolutionStatus `json:"resolutionStatus"`
// Ordered text segments that together form the agent's reply. Clients may join
// them or render each separately.
ResponseParts []string `json:"responseParts"`
// Ordered list of suggested follow-up actions the client UI may surface to the
// user.
SuggestedNextActions []string `json:"suggestedNextActions"`
}
Structured output from the default general-purpose agent template. Agents built on custom templates may extend or replace this shape.
type GeneralAgentResponseResolutionStatus ¶
type GeneralAgentResponseResolutionStatus string
const GeneralAgentResponseResolutionStatusBlocked GeneralAgentResponseResolutionStatus = "blocked"
const GeneralAgentResponseResolutionStatusInProgress GeneralAgentResponseResolutionStatus = "in_progress"
const GeneralAgentResponseResolutionStatusNeedsMoreInfo GeneralAgentResponseResolutionStatus = "needs_more_info"
const GeneralAgentResponseResolutionStatusRequiresEscalation GeneralAgentResponseResolutionStatus = "requires_escalation"
const GeneralAgentResponseResolutionStatusResolved GeneralAgentResponseResolutionStatus = "resolved"
type GetMessagesParams ¶
type GetMessagesParams struct {
SessionID string `json:"sessionId"`
Limit int `json:"limit,omitempty"`
Before string `json:"before,omitempty"`
}
GetMessagesParams holds the caller-supplied fields for GetMessages.
type GetMessagesRequest ¶
type GetMessagesRequest struct {
// Action discriminator.
Action string `json:"action"`
// ISO 8601 cursor: return only messages created strictly before this timestamp.
// Omit to start from the most recent message.
Before *time.Time `json:"before,omitempty,omitzero"`
// Maximum number of messages to return per page. Must be 1–100; defaults to 50.
Limit int `json:"limit,omitempty,omitzero"`
// Client-generated correlation ID echoed back on all related events.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Session ID whose conversation messages to fetch.
SessionID string `json:"sessionId"`
}
Fields sent by the client to page through conversation history.
type GetMessagesResponse ¶
type GetMessagesResponse struct {
// True if more messages exist before the oldest message in this page. Use the
// oldest `createdAt` as the next `before` cursor.
HasMore bool `json:"hasMore"`
// Ordered list of messages (newest-first up to `limit`).
Messages []ConversationMessage `json:"messages"`
}
Data payload carried in the `immediate_response` event.
type GetSessionParams ¶
type GetSessionParams struct {
SessionID string `json:"sessionId"`
}
GetSessionParams holds the caller-supplied fields for GetSession.
type GetSessionRequest ¶
type GetSessionRequest struct {
// Action discriminator.
Action string `json:"action"`
// Client-generated correlation ID echoed back on all related events.
RequestID *string `json:"requestId,omitempty,omitzero"`
// ID of the session to retrieve.
SessionID string `json:"sessionId"`
}
Fields sent by the client to retrieve a session.
type GetSessionResponse ¶
type GetSessionResponse struct {
// Agent ID.
AgentID string `json:"agentId"`
// Display name of the agent.
AgentName string `json:"agentName"`
// Participant ID for the agent in this session.
AgentParticipantID string `json:"agentParticipantId"`
// Conversation ID.
ConversationID string `json:"conversationId"`
// Session ID.
SessionID string `json:"sessionId"`
// Current lifecycle status of the session.
Status *ResponseStatus `json:"status,omitempty,omitzero"`
// smooth-operator thread identifier. Present when the session has an associated
// workflow thread.
ThreadID *string `json:"threadId,omitempty,omitzero"`
// Participant ID for the user in this session.
UserParticipantID string `json:"userParticipantId"`
}
Data payload carried in the `immediate_response` event. Field set matches `Session` in `domain/session.schema.json` (wire-subset; full domain object may include additional server-only fields).
type ImmediateResponse ¶
type ImmediateResponse struct {
// Action-specific response payload. For `create_conversation_session` and
// `get_session`, this is the session descriptor. For `get_conversation_messages`,
// this is the message page. For streaming `send_message`, this is typically empty
// or contains only a minimal ack.
Data ImmediateResponseData `json:"data"`
// Human-readable status description (e.g. `Processing your request...`).
Message *string `json:"message,omitempty,omitzero"`
// Echoes the `requestId` from the originating action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// HTTP-like status. 202 = accepted and processing; 200 = synchronous success
// (non-streaming responses).
Status *int `json:"status,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `immediate_response`. Sent by the server synchronously upon receiving any action, to acknowledge that the request was accepted and processing has begun. For streaming actions (`send_message`) this always precedes `stream_chunk` / `stream_token` events and the final `eventual_response`. For non-streaming actions (e.g. `get_session`, `create_conversation_session`) this also carries the complete response payload in `data`.
type ImmediateResponseData ¶
type ImmediateResponseData map[string]interface{}
Action-specific response payload. For `create_conversation_session` and `get_session`, this is the session descriptor. For `get_conversation_messages`, this is the message page. For streaming `send_message`, this is typically empty or contains only a minimal ack.
type Keepalive ¶
type Keepalive struct {
// Keepalive payload.
Data KeepaliveData `json:"data"`
// The `requestId` of the in-flight request this keepalive is associated with.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the keepalive was sent.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `keepalive`. Sent periodically by the server during long-running agent turns (typically every 30 seconds) to prevent AWS API Gateway's 10-minute idle connection timeout from closing the WebSocket while the backend is still computing. Clients should acknowledge receipt by updating their last-seen timestamp, but no reply action is needed. Distinct from `ping`/`pong` which are client-initiated.
type KeepaliveData ¶
type KeepaliveData struct {
// The request ID of the in-flight request this keepalive belongs to.
RequestID string `json:"requestId"`
}
Keepalive payload.
type Message ¶
type Message struct {
// Analytics data associated with this message (e.g. sentiment scores, token
// counts).
AnalyticsJSON *MessageAnalyticsJSON `json:"analyticsJson,omitempty,omitzero"`
// The message payload.
Content MessageContent `json:"content"`
// The conversation this message belongs to.
ConversationID MessageConversationID `json:"conversationId,omitempty,omitzero"`
// ISO 8601 timestamp when the message was created.
CreatedAt time.Time `json:"createdAt"`
// Message direction relative to the platform: `inbound` = from user/external,
// `outbound` = from agent/platform.
Direction MessageDirection `json:"direction"`
// ID assigned by an external platform (e.g. a Twilio SID or Messenger message
// id).
ExternalID MessageExternalID `json:"externalId,omitempty,omitzero"`
// Abbreviated sender descriptor (wire shape used in API responses; full
// participant data lives in domain/participant.schema.json).
From *MessageFrom `json:"from,omitempty,omitzero"`
// Unique message identifier.
ID string `json:"id"`
// Arbitrary key/value metadata attached to this message.
MetadataJSON *MessageMetadataJSON `json:"metadataJson,omitempty,omitzero"`
// The organization that owns this message.
OrganizationID MessageOrganizationID `json:"organizationId,omitempty,omitzero"`
// Abbreviated recipient descriptor.
To *MessageTo `json:"to,omitempty,omitzero"`
// ISO 8601 timestamp when the message was last updated.
UpdatedAt MessageUpdatedAt `json:"updatedAt,omitempty,omitzero"`
}
A single message within a conversation. Direction is from the conversation's perspective: `inbound` = arriving from the user/external party; `outbound` = sent by the agent or platform. Corresponds to a row in the `conversation_messages` table.
type MessageAnalyticsJSON ¶
type MessageAnalyticsJSON map[string]interface{}
Analytics data associated with this message (e.g. sentiment scores, token counts).
type MessageContent ¶
type MessageContent struct {
// Ordered list of content items that make up this message.
Items []ContentItem `json:"items,omitempty,omitzero"`
// Structured agent response payload. Shape varies by agent template.
StructuredResponse *MessageContentStructuredResponse `json:"structuredResponse,omitempty,omitzero"`
// Convenience flat-text representation of the message (populated for simple
// text-only messages).
Text MessageContentText `json:"text,omitempty,omitzero"`
}
Structured content of a message. Currently always contains `items`; `text` and `structuredResponse` are the two supported item types.
type MessageContentStructuredResponse ¶
type MessageContentStructuredResponse map[string]interface{}
Structured agent response payload. Shape varies by agent template.
type MessageContentText ¶
type MessageContentText *string
Convenience flat-text representation of the message (populated for simple text-only messages).
type MessageConversationID ¶
type MessageConversationID *string
The conversation this message belongs to.
type MessageDirection ¶
type MessageDirection string
const MessageDirectionInbound MessageDirection = "inbound"
const MessageDirectionOutbound MessageDirection = "outbound"
type MessageExternalID ¶
type MessageExternalID *string
ID assigned by an external platform (e.g. a Twilio SID or Messenger message id).
type MessageFrom ¶
type MessageFrom struct {
// Participant ID of the sender.
ID string `json:"id"`
// Display name of the sender.
Name MessageFromName `json:"name,omitempty,omitzero"`
// Participant type of the sender.
Type string `json:"type"`
}
Abbreviated sender descriptor (wire shape used in API responses; full participant data lives in domain/participant.schema.json).
type MessageMetadataJSON ¶
type MessageMetadataJSON map[string]interface{}
Arbitrary key/value metadata attached to this message.
type MessageOrganizationID ¶
type MessageOrganizationID *string
The organization that owns this message.
type MessageTo ¶
type MessageTo struct {
// Participant ID of the recipient.
ID string `json:"id"`
// Display name of the recipient.
Name MessageToName `json:"name,omitempty,omitzero"`
// Participant type of the recipient.
Type string `json:"type"`
}
Abbreviated recipient descriptor.
type MessageTurn ¶
type MessageTurn struct {
// contains filtered or unexported fields
}
MessageTurn is a single streaming send_message turn. Receive each intermediate event in arrival order from Events(), or block for the terminal eventual_response with Wait(ctx). HITL resumes (confirm_tool_action / verify_otp) for the same requestId flow back into the same turn.
turn := client.SendMessage(protocol.SendMessageParams{SessionID: id, Message: "hi"})
for ev := range turn.Events() {
if ev.Type == protocol.EventStreamToken {
tok, _ := ev.AsStreamToken()
fmt.Print(tok.Token)
}
}
final, err := turn.Wait(context.Background())
func (*MessageTurn) Events ¶
func (t *MessageTurn) Events() <-chan ServerEvent
Events returns the channel of streamed events. It is closed when the turn ends (after the terminal event has been delivered, or on abort / timeout).
func (*MessageTurn) RequestID ¶
func (t *MessageTurn) RequestID() string
RequestID is the correlation ID this turn is keyed on.
func (*MessageTurn) Wait ¶
func (t *MessageTurn) Wait(ctx context.Context) (EventualResponse, error)
Wait blocks until the turn produces its terminal eventual_response, the turn fails (error event / transport close / timeout), or ctx is cancelled.
type MessageUpdatedAt ¶
ISO 8601 timestamp when the message was last updated.
type OTPInvalid ¶
type OTPInvalid struct {
// Failure details.
Data OTPInvalidData `json:"data"`
// Echoes the `requestId` from the originating `verify_otp` action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `otp_invalid`. Emitted when the caller's OTP attempt is rejected — wrong code, expired, max attempts reached, or record not found. When `attemptsRemaining` is 0 the session is locked; the client must restart the OTP flow. When greater than 0 the client may prompt the user to try again.
type OTPInvalidData ¶
type OTPInvalidData struct {
// OTP invalid payload.
Data OTPInvalidDataData `json:"data"`
// The request ID this verification belongs to.
RequestID string `json:"requestId"`
}
Failure details.
type OTPInvalidDataData ¶
type OTPInvalidDataData struct {
// How many more attempts the caller has before the OTP is locked. Zero means the
// session is locked and a new OTP must be requested.
AttemptsRemaining int `json:"attemptsRemaining"`
// Machine-readable failure reason. Absent if the server cannot determine a
// specific cause.
Error *OTPInvalidDataDataError `json:"error,omitempty,omitzero"`
// Human-readable failure message suitable for display in the verification UI.
Message string `json:"message"`
}
OTP invalid payload.
type OTPInvalidDataDataError ¶
type OTPInvalidDataDataError string
const OTPInvalidDataDataErrorEXPIRED OTPInvalidDataDataError = "EXPIRED"
const OTPInvalidDataDataErrorINVALIDCODE OTPInvalidDataDataError = "INVALID_CODE"
const OTPInvalidDataDataErrorMAXATTEMPTS OTPInvalidDataDataError = "MAX_ATTEMPTS"
const OTPInvalidDataDataErrorNOTFOUND OTPInvalidDataDataError = "NOT_FOUND"
type OTPSent ¶
type OTPSent struct {
// OTP send acknowledgement details.
Data OTPSentData `json:"data"`
// Echoes the `requestId` from the originating action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `otp_sent`. Acknowledgement that an OTP code has been dispatched to the user via the chosen delivery channel. The client should update the UI to prompt the user to enter the code they received.
type OTPSentData ¶
type OTPSentData struct {
// Delivery details.
Data OTPSentDataData `json:"data"`
// The request ID this OTP delivery belongs to.
RequestID string `json:"requestId"`
}
OTP send acknowledgement details.
type OTPSentDataData ¶
type OTPSentDataData struct {
// The channel through which the OTP was delivered.
Channel OTPSentDataDataChannel `json:"channel"`
// Partially masked destination address for display in the UI (e.g.
// `j***@example.com` or `+1 ***-***-4567`). Sufficient for the user to recognize
// their own address without exposing it fully.
MaskedDestination string `json:"maskedDestination"`
}
Delivery details.
type OTPSentDataDataChannel ¶
type OTPSentDataDataChannel string
const OTPSentDataDataChannelEmail OTPSentDataDataChannel = "email"
const OTPSentDataDataChannelSms OTPSentDataDataChannel = "sms"
type OTPVerificationRequired ¶
type OTPVerificationRequired struct {
// Verification prompt details.
Data OTPVerificationRequiredData `json:"data"`
// Echoes the `requestId` from the originating `send_message` action. Must be
// included in the `verify_otp` reply.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `otp_verification_required`. Emitted when the agent workflow pauses because it needs the caller to complete OTP verification before proceeding with an authenticated action. Corresponds to smooth-operator's `AgentEvent::HumanInputRequired { Input }` for auth gates. The client should surface a channel-selection and OTP input UI. After the user selects a channel, the client may trigger OTP delivery via a separate flow; the `verify_otp` action submits the received code.
type OTPVerificationRequiredData ¶
type OTPVerificationRequiredData struct {
// Details about the authentication requirement.
Data OTPVerificationRequiredDataData `json:"data"`
// The request ID this verification belongs to.
RequestID string `json:"requestId"`
}
Verification prompt details.
type OTPVerificationRequiredDataData ¶
type OTPVerificationRequiredDataData struct {
// Human-readable description of the action requiring verification, suitable for
// the consent UI.
ActionDescription string `json:"actionDescription"`
// Required authentication level. Common values: `email`, `sms`, `mfa`,
// `end_user`, `admin`.
AuthLevel string `json:"authLevel"`
// Delivery channels available to send the OTP. The client should let the user
// choose.
AvailableChannels []OTPVerificationRequiredDataDataAvailableChannelsElem `json:"availableChannels"`
// Opaque identifier of the tool invocation awaiting verification.
ToolID string `json:"toolId"`
}
Details about the authentication requirement.
type OTPVerificationRequiredDataDataAvailableChannelsElem ¶
type OTPVerificationRequiredDataDataAvailableChannelsElem string
const OTPVerificationRequiredDataDataAvailableChannelsElemEmail OTPVerificationRequiredDataDataAvailableChannelsElem = "email"
const OTPVerificationRequiredDataDataAvailableChannelsElemSms OTPVerificationRequiredDataDataAvailableChannelsElem = "sms"
type OTPVerified ¶
type OTPVerified struct {
// Verification success details.
Data OTPVerifiedData `json:"data"`
// Echoes the `requestId` from the originating `verify_otp` action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `otp_verified`. Emitted when the caller's OTP attempt succeeds, or when a pre-auth HMAC makes OTP unnecessary. The session is now authenticated at the required level and the paused agent workflow resumes. A streaming sequence (`stream_chunk` / `stream_token` → `eventual_response`) follows.
type OTPVerifiedData ¶
type OTPVerifiedData struct {
// Success payload.
Data OTPVerifiedDataData `json:"data"`
// The request ID this verification belongs to.
RequestID string `json:"requestId"`
}
Verification success details.
type OTPVerifiedDataData ¶
type OTPVerifiedDataData struct {
// Short human-readable confirmation message (e.g. `Identity verified
// successfully.`).
Message string `json:"message"`
}
Success payload.
type Options ¶
type Options struct {
// Transport is the wire abstraction. Required (use NewWebSocketTransport for the
// default, or a mock in tests).
Transport Transport
// GenerateRequestID overrides request ID generation. Defaults to "req-" + UUIDv4.
GenerateRequestID func() string
// TurnTimeout bounds a streaming send_message turn (see DefaultTurnTimeout).
// Zero uses DefaultTurnTimeout; a negative value disables the turn timeout.
TurnTimeout time.Duration
}
Options configures a Client.
type Participant ¶
type Participant struct {
// Browser fingerprint (ThumbmarkJS) for anonymous user identification.
BrowserFingerprint ParticipantBrowserFingerprint `json:"browserFingerprint,omitempty,omitzero"`
// Parsed browser / device metadata collected at session start.
BrowserInfo *ParticipantBrowserInfo `json:"browserInfo,omitempty,omitzero"`
// The conversation this participant belongs to.
ConversationID string `json:"conversationId"`
// ISO 8601 timestamp when the participant record was created.
CreatedAt time.Time `json:"createdAt"`
// Foreign key into the CRM contacts table if this participant has been matched.
CrmContactID ParticipantCrmContactID `json:"crmContactId,omitempty,omitzero"`
// Email address if known.
Email ParticipantEmail `json:"email,omitempty,omitzero"`
// External identity (e.g. Supabase auth user UUID) for authenticated
// participants.
ExternalID ParticipantExternalID `json:"externalId,omitempty,omitzero"`
// Unique participant identifier.
ID string `json:"id"`
// Internal system identifier (e.g. agent UUID from the agents table).
InternalID ParticipantInternalID `json:"internalId,omitempty,omitzero"`
// Arbitrary key/value metadata attached to this participant.
MetadataJSON ParticipantMetadataJSON `json:"metadataJson,omitempty,omitzero"`
// Display name for this participant.
Name string `json:"name"`
// The organization that owns this participant record.
OrganizationID string `json:"organizationId"`
// Phone number in E.164 format if known.
Phone ParticipantPhone `json:"phone,omitempty,omitzero"`
// Participant role: `user` = end-user, `ai-agent` = smooth-operator agent,
// `human-agent` = live support agent.
Type ParticipantType `json:"type"`
// ISO 8601 timestamp when the participant record was last updated.
UpdatedAt time.Time `json:"updatedAt"`
}
A participant in a conversation. Participants may be end users, AI agents, or human support agents. Corresponds to a row in the `conversation_participants` table.
type ParticipantBrowserFingerprint ¶
type ParticipantBrowserFingerprint *string
Browser fingerprint (ThumbmarkJS) for anonymous user identification.
type ParticipantBrowserInfo ¶
type ParticipantBrowserInfo map[string]interface{}
Parsed browser / device metadata collected at session start.
type ParticipantCrmContactID ¶
type ParticipantCrmContactID *string
Foreign key into the CRM contacts table if this participant has been matched.
type ParticipantExternalID ¶
type ParticipantExternalID *string
External identity (e.g. Supabase auth user UUID) for authenticated participants.
type ParticipantInternalID ¶
type ParticipantInternalID *string
Internal system identifier (e.g. agent UUID from the agents table).
type ParticipantMetadataJSON ¶
type ParticipantMetadataJSON map[string]interface{}
Arbitrary key/value metadata attached to this participant.
type ParticipantType ¶
type ParticipantType string
const ParticipantTypeAiAgent ParticipantType = "ai-agent"
const ParticipantTypeHumanAgent ParticipantType = "human-agent"
const ParticipantTypeUser ParticipantType = "user"
type PingRequest ¶
type PingRequest struct {
// Action discriminator.
Action string `json:"action"`
// Client-generated correlation ID echoed back in the `pong` event.
RequestID *string `json:"requestId,omitempty,omitzero"`
}
A ping frame. Only `action` and the optional `requestId` are required.
type Pong ¶
type Pong struct {
// Pong payload (mirrors top-level `timestamp` for clients that only inspect
// `data`).
Data *PongData `json:"data,omitempty,omitzero"`
// Echoes the `requestId` from the originating `ping` action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Server-side Unix epoch milliseconds when the pong was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `pong`. The server's reply to a `ping` action. Carries the server's current Unix epoch timestamp in milliseconds. Clients use the round-trip time to detect zombie connections.
type PongData ¶
type PongData struct {
// Server-side Unix epoch milliseconds.
Timestamp int `json:"timestamp"`
}
Pong payload (mirrors top-level `timestamp` for clients that only inspect `data`).
type PongResponse ¶
type PongResponse struct {
// Server-side Unix epoch milliseconds when the pong was sent.
Timestamp int `json:"timestamp"`
}
Data payload carried in the `pong` event.
type ProtocolError ¶
ProtocolError surfaces a server `error` event as a Go error.
func (*ProtocolError) Error ¶
func (e *ProtocolError) Error() string
type RequestAuthContext ¶
type RequestAuthContext struct {
// HMAC-SHA256 signature over `userId + timestamp` using a shared secret.
Signature string `json:"signature"`
// Unix epoch seconds when the HMAC was signed. Used for replay protection
// (typical max age: 60s).
Timestamp int `json:"timestamp"`
// The user's identity claim.
UserID string `json:"userId"`
}
Pre-auth context for HMAC-based identity verification. When provided, the server can skip OTP flows by verifying the HMAC signature instead.
type RequestMetadata ¶
type RequestMetadata map[string]interface{}
Arbitrary key/value metadata to attach to the session.
type ResponseStatus ¶
type ResponseStatus string
const ResponseStatusActive ResponseStatus = "active"
const ResponseStatusEnded ResponseStatus = "ended"
const ResponseStatusIdle ResponseStatus = "idle"
type SendMessageParams ¶
type SendMessageParams struct {
SessionID string `json:"sessionId"`
Message string `json:"message"`
// Stream controls whether incremental stream_chunk/stream_token events are sent.
// nil leaves the field off the wire (server default = true).
Stream *bool `json:"stream,omitempty"`
}
SendMessageParams holds the caller-supplied fields for SendMessage.
type SendMessageRequest ¶
type SendMessageRequest struct {
// Action discriminator.
Action string `json:"action"`
// The user's message text. Between 1 and 10 000 characters.
Message string `json:"message"`
// Client-generated correlation ID echoed back on all related events.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Session ID returned by `create_conversation_session`.
SessionID string `json:"sessionId"`
// Whether to receive incremental `stream_chunk` and `stream_token` events.
// Defaults to `true`. Set to `false` to receive only the final
// `eventual_response`.
Stream bool `json:"stream,omitempty,omitzero"`
}
Fields sent by the client to submit a message.
type SendMessageResponse ¶
type SendMessageResponse struct {
// Human-readable reason when `needsEscalation` is true.
EscalationReason *string `json:"escalationReason,omitempty,omitzero"`
// ID of the agent's response message as persisted to the database.
MessageID string `json:"messageId"`
// True if the agent flagged this turn for human escalation.
NeedsEscalation bool `json:"needsEscalation"`
// Structured agent response.
Response GeneralAgentResponse `json:"response"`
}
Data payload carried in the terminal `eventual_response` event for this action. Also see `GeneralAgentResponse` for the structured response shape.
type ServerEvent ¶
type ServerEvent struct {
// Type is the event discriminator (`type` on the wire).
Type EventType
// RequestID echoes the originating action's requestId, when present.
RequestID string
// Status is the HTTP-like status code (0 if absent).
Status int
// Node is the workflow node name, present on stream_chunk events.
Node string
// Token is the streamed token text, present on stream_token events.
Token string
// Raw is the complete, undecoded event frame. Use the As* accessors to decode
// it into the concrete generated type.
Raw json.RawMessage
}
ServerEvent is the ergonomic, discriminated representation of any server→client frame. Go has no sum types, so rather than force a sealed-interface dance on callers, a ServerEvent carries the common envelope fields plus the raw frame bytes. Discriminate on Type and call the matching typed accessor (As*) to decode the concrete generated payload.
switch ev.Type {
case protocol.EventStreamToken:
tok, _ := ev.AsStreamToken()
fmt.Print(tok.Token)
case protocol.EventEventualResponse:
final, _ := ev.AsEventualResponse()
...
}
func ParseServerEvent ¶
func ParseServerEvent(frame []byte) (ServerEvent, error)
ParseServerEvent decodes a raw server frame into a discriminable ServerEvent. It returns an error if the frame is not valid JSON or carries an unknown `type`.
func (ServerEvent) AsError ¶
func (e ServerEvent) AsError() (Error, error)
AsError decodes the event as an error event.
func (ServerEvent) AsEventualResponse ¶
func (e ServerEvent) AsEventualResponse() (EventualResponse, error)
AsEventualResponse decodes the event as an eventual_response (terminal turn event).
func (ServerEvent) AsImmediateResponse ¶
func (e ServerEvent) AsImmediateResponse() (ImmediateResponse, error)
AsImmediateResponse decodes the event as an immediate_response.
func (ServerEvent) AsKeepalive ¶
func (e ServerEvent) AsKeepalive() (Keepalive, error)
AsKeepalive decodes the event as a keepalive.
func (ServerEvent) AsOTPInvalid ¶
func (e ServerEvent) AsOTPInvalid() (OTPInvalid, error)
AsOTPInvalid decodes the event as an otp_invalid.
func (ServerEvent) AsOTPSent ¶
func (e ServerEvent) AsOTPSent() (OTPSent, error)
AsOTPSent decodes the event as an otp_sent.
func (ServerEvent) AsOTPVerificationRequired ¶
func (e ServerEvent) AsOTPVerificationRequired() (OTPVerificationRequired, error)
AsOTPVerificationRequired decodes the event as an otp_verification_required (HITL auth gate).
func (ServerEvent) AsOTPVerified ¶
func (e ServerEvent) AsOTPVerified() (OTPVerified, error)
AsOTPVerified decodes the event as an otp_verified.
func (ServerEvent) AsPong ¶
func (e ServerEvent) AsPong() (Pong, error)
AsPong decodes the event as a pong.
func (ServerEvent) AsStreamChunk ¶
func (e ServerEvent) AsStreamChunk() (StreamChunk, error)
AsStreamChunk decodes the event as a stream_chunk.
func (ServerEvent) AsStreamToken ¶
func (e ServerEvent) AsStreamToken() (StreamToken, error)
AsStreamToken decodes the event as a stream_token.
func (ServerEvent) AsWriteConfirmationRequired ¶
func (e ServerEvent) AsWriteConfirmationRequired() (WriteConfirmationRequired, error)
AsWriteConfirmationRequired decodes the event as a write_confirmation_required (HITL confirm).
func (ServerEvent) IsTerminal ¶
func (e ServerEvent) IsTerminal() bool
IsTerminal reports whether this event ends a streaming turn (success or error).
type Session ¶
type Session struct {
// The agent handling this session.
AgentID string `json:"agentId"`
// Human-readable display name of the agent.
AgentName string `json:"agentName"`
// The participant record representing the AI agent in this session.
AgentParticipantID string `json:"agentParticipantId"`
// The conversation this session is attached to.
ConversationID string `json:"conversationId"`
// ISO 8601 timestamp when the session was created.
CreatedAt *time.Time `json:"createdAt,omitempty,omitzero"`
// ISO 8601 timestamp when the session ended, or null if still active.
EndedAt SessionEndedAt `json:"endedAt,omitempty,omitzero"`
// ISO 8601 timestamp of the most recent activity (message, keepalive, etc.).
LastActivityAt *time.Time `json:"lastActivityAt,omitempty,omitzero"`
// Number of messages exchanged in this session.
MessageCount *int `json:"messageCount,omitempty,omitzero"`
// Arbitrary key/value metadata attached to this session (e.g. browser info,
// campaign source).
Metadata SessionMetadata `json:"metadata,omitempty,omitzero"`
// Unique session identifier.
SessionID string `json:"sessionId"`
// Lifecycle status of the session.
Status *SessionStatus `json:"status,omitempty,omitzero"`
// smooth-operator workflow thread identifier. Used to resume agent state across
// turns and process restarts. Stored as `langgraph_thread_id` in the database for
// historical reasons.
ThreadID string `json:"threadId"`
// Cumulative token count consumed in this session.
TokenCount *int `json:"tokenCount,omitempty,omitzero"`
// ISO 8601 timestamp when the session was last updated.
UpdatedAt *time.Time `json:"updatedAt,omitempty,omitzero"`
// The participant record representing the end user in this session.
UserParticipantID string `json:"userParticipantId"`
}
An AI conversation session. Ties together a conversation, an agent, the user and agent participants, and the smooth-operator workflow thread. Corresponds to a row in the `conversation_sessions` table. The `threadId` field is the smooth-operator thread identifier (stored as `langgraph_thread_id` in the DB for historical reasons; renamed to `threadId` in the protocol).
type SessionEndedAt ¶
ISO 8601 timestamp when the session ended, or null if still active.
type SessionMetadata ¶
type SessionMetadata map[string]interface{}
Arbitrary key/value metadata attached to this session (e.g. browser info, campaign source).
type SessionStatus ¶
type SessionStatus string
const SessionStatusActive SessionStatus = "active"
const SessionStatusEnded SessionStatus = "ended"
const SessionStatusIdle SessionStatus = "idle"
type StreamChunk ¶
type StreamChunk struct {
// The per-node state snapshot.
Data StreamChunkData `json:"data"`
// Name of the workflow node that just completed and produced this chunk.
Node *string `json:"node,omitempty,omitzero"`
// Echoes the `requestId` from the originating `send_message` action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `stream_chunk`. Emitted each time a node in the smooth-operator workflow completes. Carries the node name and a filtered state snapshot. Clients use this to show per-node progress (e.g. `knowledge_search completed`, tool activity) in an agent team view. Distinct from `stream_token` which carries raw token deltas; a `stream_chunk` typically fires once per node while multiple `stream_token` events may fire within a single node's LLM call.
type StreamChunkData ¶
type StreamChunkData struct {
// Reserved for future use. When true, this is the last `stream_chunk` for the
// request. Currently clients should use `eventual_response` to detect stream
// completion.
Done *bool `json:"done,omitempty,omitzero"`
// Name of the workflow node that produced this state snapshot.
Node string `json:"node"`
// The request ID this chunk belongs to.
RequestID string `json:"requestId"`
// Filtered subset of the node's output state exposed to the client. Only
// safe-to-expose fields are included; server-internal state is stripped.
State StreamChunkDataState `json:"state"`
}
The per-node state snapshot.
type StreamChunkDataState ¶
type StreamChunkDataState struct {
// Non-null when the workflow has paused awaiting OTP verification. Clients should
// surface an OTP input UI.
PendingOTPVerification *StreamChunkDataStatePendingOTPVerification `json:"pendingOtpVerification,omitempty,omitzero"`
// Non-null when the workflow has paused awaiting user confirmation of a write
// operation. Clients should surface a confirmation UI.
PendingWriteConfirmation *StreamChunkDataStatePendingWriteConfirmation `json:"pendingWriteConfirmation,omitempty,omitzero"`
// Unstructured LLM output from this node, if any.
RawResponse interface{} `json:"rawResponse,omitempty,omitzero"`
// Parsed structured response from this node, if any.
StructuredResponse interface{} `json:"structuredResponse,omitempty,omitzero"`
}
Filtered subset of the node's output state exposed to the client. Only safe-to-expose fields are included; server-internal state is stripped.
type StreamChunkDataStatePendingOTPVerification ¶
type StreamChunkDataStatePendingOTPVerification map[string]interface{}
Non-null when the workflow has paused awaiting OTP verification. Clients should surface an OTP input UI.
type StreamChunkDataStatePendingWriteConfirmation ¶
type StreamChunkDataStatePendingWriteConfirmation map[string]interface{}
Non-null when the workflow has paused awaiting user confirmation of a write operation. Clients should surface a confirmation UI.
type StreamToken ¶
type StreamToken struct {
// Token event payload.
Data StreamTokenData `json:"data"`
// Echoes the `requestId` from the originating `send_message` action.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// The raw token text. Also present inside `data.token` for consumers that only
// inspect `data`.
Token *string `json:"token,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `stream_token`. A single LLM output token forwarded to the client in real time. Corresponds to smooth-operator's `AgentEvent::TokenDelta`. Clients accumulate tokens to display a live typing animation. After the node finishes, a `stream_chunk` event carries the complete state snapshot for that node.
type StreamTokenData ¶
type StreamTokenData struct {
// The request ID this token belongs to.
RequestID string `json:"requestId"`
// The raw token text.
Token string `json:"token"`
}
Token event payload.
type Transport ¶
type Transport interface {
// Connect opens the underlying connection. It must return once the transport is
// ready to Send/Receive, or with an error if it cannot connect.
Connect(ctx context.Context) error
// Send writes a single serialized frame. It returns an error if the transport is
// not open.
Send(frame []byte) error
// Receive returns the channel on which inbound frames are delivered. The channel
// is closed when the transport closes (cleanly or on error).
Receive() <-chan []byte
// Close shuts the transport down. Subsequent Sends return an error and Receive's
// channel is closed.
Close() error
// Err returns the terminal error that closed the transport, if any. It returns
// nil for a clean close.
Err() error
}
Transport is the injectable wire abstraction the Client talks to. It is deliberately decoupled from any concrete WebSocket implementation so the client can be unit-tested with an in-memory mock and run against a real socket in production.
A Transport must be safe for concurrent use: Send may be called from one goroutine while the receive loop delivers frames on another.
type TurnTimeoutError ¶
TurnTimeoutError is the error a turn settles with when no terminal eventual_response / error arrives within the configured turn timeout. The turn's Events() channel is closed and Wait/result return this error.
func (*TurnTimeoutError) Error ¶
func (e *TurnTimeoutError) Error() string
type UnknownEventError ¶
type UnknownEventError struct{ Type string }
UnknownEventError is returned when a frame carries an unrecognised `type`.
func (*UnknownEventError) Error ¶
func (e *UnknownEventError) Error() string
type Validator ¶
type Validator struct {
// contains filtered or unexported fields
}
Validator performs runtime JSON Schema validation of protocol messages against the schemas in spec/. It is a thin, optional layer: the wire types already round-trip, but a Validator lets a client or test assert that an instance conforms to its declared schema (catching drift between implementations).
Construct one with NewValidator, pointing at the spec/ directory.
func NewValidator ¶
NewValidator loads every schema under specDir and returns a Validator. The spec schemas use only internal $ref (#/$defs/...), so no network access is needed.
func (*Validator) ValidateActionRef ¶
ValidateActionRef resolves an action's Request schema (actions/<file>#/$defs/Request) and validates instance against it.
func (*Validator) ValidateEventRef ¶
ValidateEventRef validates instance against an event schema (events/<file>).
type VerifyOTPParams ¶
type VerifyOTPParams struct {
SessionID string `json:"sessionId"`
// RequestID must match the otp_verification_required event being answered.
RequestID string `json:"requestId"`
Code string `json:"code"`
}
VerifyOTPParams holds the caller-supplied fields for VerifyOTP.
type VerifyOTPRequest ¶
type VerifyOTPRequest struct {
// Action discriminator.
Action string `json:"action"`
// The one-time password code entered by the user.
Code string `json:"code"`
// Must match the `requestId` from the `otp_verification_required` event being
// responded to.
RequestID string `json:"requestId"`
// Session ID of the paused session.
SessionID string `json:"sessionId"`
}
Fields sent by the client to submit an OTP code.
type VerifyOTPResponse ¶
type VerifyOTPResponse map[string]interface{}
No dedicated response — outcome signalled by `otp_verified` or `otp_invalid` events.
type WebSocketTransport ¶
type WebSocketTransport struct {
// contains filtered or unexported fields
}
WebSocketTransport is the default Transport, backed by github.com/coder/websocket (a small, dependency-light, context-aware WebSocket library). It dials lazily in Connect and pumps inbound text frames onto Receive's channel.
func NewWebSocketTransport ¶
func NewWebSocketTransport(url string, opts *websocket.DialOptions) *WebSocketTransport
NewWebSocketTransport builds a default WebSocket transport for the given URL (e.g. "wss://realtime.prod.smooth-agent.dev"). Pass opts to customise the dial (headers, subprotocols, …); nil is fine for defaults.
func (*WebSocketTransport) Close ¶
func (t *WebSocketTransport) Close() error
Close shuts the connection down cleanly.
func (*WebSocketTransport) Connect ¶
func (t *WebSocketTransport) Connect(ctx context.Context) error
Connect dials the WebSocket and starts the read loop. The provided ctx bounds the dial; the transport keeps an internal context for the connection lifetime.
func (*WebSocketTransport) Err ¶
func (t *WebSocketTransport) Err() error
Err returns the terminal error, if any.
func (*WebSocketTransport) Receive ¶
func (t *WebSocketTransport) Receive() <-chan []byte
Receive returns the inbound frame channel.
func (*WebSocketTransport) Send ¶
func (t *WebSocketTransport) Send(frame []byte) error
Send writes a text frame.
type WriteConfirmationRequired ¶
type WriteConfirmationRequired struct {
// Confirmation prompt details.
Data WriteConfirmationRequiredData `json:"data"`
// Echoes the `requestId` from the originating `send_message` action. Must be
// included in the `confirm_tool_action` reply.
RequestID *string `json:"requestId,omitempty,omitzero"`
// Unix epoch milliseconds when the event was emitted.
Timestamp *int `json:"timestamp,omitempty,omitzero"`
// Event type discriminator.
Type string `json:"type"`
}
Event: `write_confirmation_required`. Emitted when the agent workflow pauses before running a state-mutating tool call that requires explicit user approval. Corresponds to smooth-operator's `AgentEvent::HumanInputRequired { Confirm }`. The client must surface a confirmation dialog and reply with a `confirm_tool_action` action using the same `requestId`. Until the client responds, the workflow remains paused.
type WriteConfirmationRequiredData ¶
type WriteConfirmationRequiredData struct {
// Details about the pending write that the user must approve or reject.
Data WriteConfirmationRequiredDataData `json:"data"`
// The request ID this confirmation belongs to.
RequestID string `json:"requestId"`
}
Confirmation prompt details.
type WriteConfirmationRequiredDataData ¶
type WriteConfirmationRequiredDataData struct {
// Human-readable description of the action the agent wants to perform, suitable
// for displaying in a confirmation dialog (e.g. `Delete contact John Doe
// (john@example.com)`).
ActionDescription string `json:"actionDescription"`
// Opaque identifier of the tool invocation awaiting confirmation. Provided for
// correlation; clients do not need to parse or display this.
ToolID string `json:"toolId"`
}
Details about the pending write that the user must approve or reject.