Parlora (Parlora v0.1.0)

Copy Markdown View Source

An Elixir framework for building real-time voice AI agents.

Connect speech-to-speech models to your application's services and agent backends through browser WebRTC, phone calls, or local audio devices. People can keep talking while backend work runs and correct a request during the conversation.

Your application policy interprets requests and corrections. Parlora coordinates tasks, filters outdated task results before delivery to the voice provider, and manages audio queues, playback controls, lifecycle deadlines, and cleanup. Your application owns business rules, authorization, confirmations, and storage.

Choose a channel, speech provider, backend, and Parlora.ContextPolicy for each session. All audio passes through Parlora. The provider handles speech and delegates application work; the backend executes that work independently. Supported integrations and the runnable tutorials are in the README and first-session guide.

Starting a session

{:ok, session} = Parlora.start_session(
  channel: {Parlora.Channels.LocalAudio, []},
  provider: {Parlora.Providers.OpenAI, api_key: key},
  backend: backend,
  context_policy: {MyApp.OrderPolicy, []},
  instructions: "Help the caller with their order.",
  event_sink: self()
)

backend is your configured adapter tuple. Jido, Sagents, and Legion are optional; an application can implement Parlora.Backend directly. See Getting started for dependencies and a complete setup path.

Startup is asynchronous. Keep the event sink alive and wait for {:parlora_event, %Parlora.Event{source: :session, type: :ready}} before inviting speech. Handle failures and the session :closed event in the same receiver. Call close/2 when finished; monitor the PID if you need to wait for its exit.

Sessions are in memory. Persist business data in your application and reconcile uncertain operations before retrying. Correcting or cancelling work cannot undo an external effect, and provider acceptance does not prove a result was heard.

Summary

Functions

Submits a structured context update to the voice provider.

Requests cancellation of a backend request without changing playback.

Requests bounded shutdown using :cancel (default) or :finish.

Applies a supported input or output control.

Arms one opt-in progress deadline on a ready session. See Parlora.SessionHealth. Reusing an ID with the same options never restarts its deadline.

Resolves or cancels the active expectation without replaying application work.

Returns current conversation context, including transcripts and task inputs.

Starts an asynchronously initialized session.

Operational observations. See Parlora.Status for fields and clarification privacy.

Subscribes a process to future {:parlora_event, event} messages.

Replaces application context and requests interpretation of the new state.

Functions

append_context(session, update)

@spec append_context(pid(), Parlora.ContextUpdate.t()) ::
  :ok | {:error, Parlora.Error.t()}

Submits a structured context update to the voice provider.

Supported update kinds depend on provider capabilities. Admission, provider acknowledgment, generated speech, and playback are separate observations.

cancel(session, request_id, reason, id \\ ID.new())

@spec cancel(pid(), String.t(), term(), String.t()) ::
  :ok | {:error, Parlora.Error.t()}

Requests cancellation of a backend request without changing playback.

Cancellation may be advisory. Reuse an explicit command ID when reconciling an uncertain admission; do not assume cancellation reverses external work.

close(session, policy \\ :cancel)

@spec close(pid(), atom()) :: :ok | {:error, Parlora.Error.t()}

Requests bounded shutdown using :cancel (default) or :finish.

:cancel stops local work; :finish allows work to drain until the shutdown deadline. Observe session :closed for final outcomes. External work may still require reconciliation. Monitor the session PID to wait for process termination.

control(session, control, id \\ ID.new())

@spec control(pid(), term(), String.t()) :: :ok | {:error, Parlora.Error.t()}

Applies a supported input or output control.

Controls include {:input_muted, boolean}, {:suppress_output, boolean}, and {:clear_output, :next}. Mute, suppression, clearing, and backend cancellation are independent. Reuse the command ID when reconciling an uncertain admission.

expect_progress(session, id, timeout_ms, options \\ [])

@spec expect_progress(pid(), String.t(), pos_integer(), keyword()) ::
  :ok | {:error, Parlora.Error.t()}

Arms one opt-in progress deadline on a ready session. See Parlora.SessionHealth. Reusing an ID with the same options never restarts its deadline.

resolve_progress(session, id, outcome \\ :completed)

@spec resolve_progress(pid(), String.t(), :completed | :cancelled) ::
  :ok | {:error, Parlora.Error.t()}

Resolves or cancels the active expectation without replaying application work.

snapshot(session)

@spec snapshot(pid()) :: Parlora.ContextSnapshot.t() | {:error, Parlora.Error.t()}

Returns current conversation context, including transcripts and task inputs.

start_session(options)

@spec start_session(keyword()) :: {:ok, pid()} | {:error, term()}

Starts an asynchronously initialized session.

Required options are :channel, :provider, :backend, and :context_policy, each a {module, keyword_options} tuple. Optional session settings include :instructions, :history, :context, :event_sink, :audio_format, and :limits. The default format is mono PCM16LE at 24 kHz; use Parlora.AudioFormat.pcmu/0 for phone audio.

Provider audio limits are applied automatically, with explicit :limits overriding them. Returning {:ok, pid} does not establish readiness; observe the session :ready event. See the adapter reference for option, history, and capability requirements.

status(session)

@spec status(pid()) :: Parlora.Status.t() | {:error, Parlora.Error.t()}

Operational observations. See Parlora.Status for fields and clarification privacy.

subscribe(session, subscriber \\ self())

@spec subscribe(pid(), pid()) :: :ok | {:error, Parlora.Error.t()}

Subscribes a process to future {:parlora_event, event} messages.

Defaults to the caller. Events are live observations, not a durable replay log.

update_context(session, context)

@spec update_context(pid(), map()) :: :ok | {:error, Parlora.Error.t()}

Replaces application context and requests interpretation of the new state.