protocol

package
v0.0.0-...-3342487 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: MIT Imports: 12 Imported by: 0

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

View Source
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

View Source
var ErrTransportClosed = errors.New("smooth-agent: transport closed")

ErrTransportClosed is returned by Send when the transport is no longer open.

Functions

func IsKnownEventType

func IsKnownEventType(t EventType) bool

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

type CheckpointMetadata map[string]string

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 New

func New(opts Options) (*Client, error)

New constructs a Client. It does not open the transport; call Connect.

func (*Client) Close

func (c *Client) Close() error

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) Connect

func (c *Client) Connect(ctx context.Context) error

Connect opens the underlying transport and starts the dispatch loop.

func (*Client) CreateConversationSession

CreateConversationSession starts a new conversation session and returns the session descriptor carried in the immediate_response.

func (*Client) GetMessages

GetMessages fetches a page of conversation messages.

func (*Client) GetSession

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) Ping

func (c *Client) Ping(ctx context.Context) (int, error)

Ping issues a keepalive ping and returns the server timestamp from the pong.

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 MessageFromName

type MessageFromName *string

Display name of the sender.

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 MessageToName

type MessageToName *string

Display name of the recipient.

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

Wait blocks until the turn produces its terminal eventual_response, the turn fails (error event / transport close / timeout), or ctx is cancelled.

type MessageUpdatedAt

type MessageUpdatedAt *time.Time

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 ParticipantEmail

type ParticipantEmail *string

Email address if known.

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 ParticipantPhone

type ParticipantPhone *string

Phone number in E.164 format if known.

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

type ProtocolError struct {
	Code      string
	Message   string
	RequestID string
}

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

type SessionEndedAt *time.Time

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

type TurnTimeoutError struct {
	RequestID string
	Timeout   time.Duration
}

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

func NewValidator(specDir string) (*Validator, error)

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

func (v *Validator) ValidateActionRef(file string, instance any) error

ValidateActionRef resolves an action's Request schema (actions/<file>#/$defs/Request) and validates instance against it.

func (*Validator) ValidateEventRef

func (v *Validator) ValidateEventRef(file string, instance any) error

ValidateEventRef validates instance against an event schema (events/<file>).

func (*Validator) ValidateRef

func (v *Validator) ValidateRef(ref string, instance any) error

ValidateRef validates instance against the schema named by ref (a $schema_ref). instance must be a value decoded from JSON (map[string]any, []any, etc.).

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL