Cyclium.Conversations.Dispatch (Cyclium v0.2.0)

Copy Markdown View Source

Creates and enqueues interactive episodes for conversation turns.

This is the library-level helper that eliminates boilerplate in consuming apps. It resolves the actor's interactive expectation, budget, and log strategy from persistent_term (set by the Actor DSL at startup) — no actor-specific knowledge needed.

Usage in consuming apps

# Direct call:
Cyclium.Conversations.Dispatch.send_message(conversation_id, "Hello", principal: user)

# Or wrap in a thin app-level module if you need customization:
defmodule MyApp.ConversationDispatch do
  def send_message(conversation_id, message, opts \\ []) do
    Cyclium.Conversations.Dispatch.send_message(conversation_id, message, opts)
  end
end

Summary

Functions

Resolve the interactive expectation for an actor from persistent_term.

Send a user message in a conversation. Creates an interactive episode and enqueues it.

Functions

resolve_interactive_expectation(actor_id)

Resolve the interactive expectation for an actor from persistent_term.

Scans persistent_term for expectations registered with the Interactive strategy template. Also resolves budget and log_strategy for that expectation.

Selection is deterministic:

  • zero matches → {:error, :no_interactive_expectation}
  • exactly one → {:ok, expectation_id, budget, log_strategy}
  • two or more → {:error, {:ambiguous_interactive_expectation, sorted_ids}}

When an actor declares more than one interactive expectation, the conversation record (which only carries actor_id) can't say which one a turn belongs to, so resolution refuses to guess — pass :expectation_id to send_message/3.

send_message(conversation_id, message, opts \\ [])

Send a user message in a conversation. Creates an interactive episode and enqueues it.

Resolves the actor's interactive expectation automatically from the conversation's actor_id — no hardcoded expectation IDs needed.

Options

  • :principal — map with user info (e.g. %{"type" => "user", "id" => "user_123"})
  • :budget — override budget (default: resolved from actor's expectation)
  • :log_strategy — override log strategy (default: resolved from actor's expectation)
  • :expectation_id — explicitly select the interactive expectation to use.

Resolution order: this :expectation_id opt, then the expectation pinned on the conversation (conversation.expectation_id), then auto-resolution. For an actor with multiple interactive expectations and no pin, auto-resolution errors with {:ambiguous_interactive_expectation, ids}.

Returns {:ok, episode} or {:error, reason}.