Lightning.AiAssistant (Lightning v2.13.5)
View SourceThe AI assistant context module for Lightning workflows.
This module provides a comprehensive interface for managing AI-powered chat sessions within the Lightning platform. It handles two main types of AI assistance:
- Job-specific assistance - Helps users with coding tasks, debugging, and adaptor-specific guidance for individual workflow jobs
- Workflow template generation - Assists in creating complete workflow templates from natural language descriptions
Summary
Functions
Associates a workflow with a chat session.
Creates a new chat session for job-specific AI assistance.
Creates a new chat session for workflow template generation.
Checks if the AI assistant feature is enabled via application configuration.
Checks if the Apollo AI service endpoint is reachable and responding.
Finds all pending user messages in a chat session.
Retrieves a chat session by ID with all related data preloaded.
Checks if additional sessions are available beyond the current count.
Returns paginated chat sessions with metadata for improved user experience.
Records that a user has read and accepted the AI assistant disclaimer.
Adds job-specific context to a chat session for enhanced AI assistance.
Queries the AI assistant for job-specific code assistance.
Queries the AI service for workflow template generation.
Saves a message to an existing chat session.
Returns the maximum allowed length for chat session titles.
Updates the status of a specific message within a chat session.
Checks if a user has acknowledged the AI assistant disclaimer recently.
Functions
@spec associate_workflow( Lightning.AiAssistant.ChatSession.t(), Lightning.Workflows.Workflow.t() ) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, Ecto.Changeset.t()}
Associates a workflow with a chat session.
Links a generated workflow to the session that created it, enabling tracking and future modifications through the same conversation context.
Parameters
session
- The%ChatSession{}
that generated the workflowworkflow
- The%Workflow{}
struct to associate
Returns
{:ok, session}
- Successfully linked workflow to session{:error, changeset}
- Association failed with validation errors
Examples
{:ok, updated_session} = AiAssistant.associate_workflow(session, new_workflow)
@spec create_session( Lightning.Workflows.Job.t(), Lightning.Accounts.User.t(), String.t() ) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, Ecto.Changeset.t()}
Creates a new chat session for job-specific AI assistance.
Initializes a new session with:
- Generated UUID
- Association with the specified job and user
- Auto-generated title from the initial message content
- Job's expression and adaptor context
- The initial user message
Parameters
job
- The%Job{}
struct this session will assist withuser
- The%User{}
creating the sessioncontent
- Initial message content that will become the session title
Returns
{:ok, session}
- Successfully created session with initial message{:error, changeset}
- Validation errors during creation
Examples
case AiAssistant.create_session(job, current_user, "Help debug my HTTP request") do
{:ok, session} ->
# Session created successfully
{:error, changeset} ->
# Handle validation errors
end
@spec create_workflow_session( Lightning.Projects.Project.t(), Lightning.Accounts.User.t(), String.t() ) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, Ecto.Changeset.t()}
Creates a new chat session for workflow template generation.
Initializes a session specifically for creating workflow templates:
- Associates with a project rather than a specific job
- Sets session type to "workflow_template"
- Includes the initial user message describing the desired workflow
Parameters
project
- The%Project{}
struct where the workflow will be createduser
- The%User{}
requesting the workflow templatecontent
- Description of the desired workflow functionality
Returns
{:ok, session}
- Successfully created workflow session{:error, changeset}
- Validation errors during creation
Examples
case AiAssistant.create_workflow_session(project, user, "Create a daily data sync from Salesforce to PostgreSQL") do
{:ok, session} ->
# Ready to generate workflow template
{:error, changeset} ->
# Handle errors
end
@spec enabled?() :: boolean()
Checks if the AI assistant feature is enabled via application configuration.
Verifies that both the Apollo endpoint URL and API key are properly configured, which are required for AI functionality.
Returns
true
if AI assistant is properly configured and enabled, false
otherwise.
Examples
if AiAssistant.enabled?() do
# Show AI assistant UI elements
else
# Hide AI features or show configuration message
end
@spec endpoint_available?() :: boolean()
Checks if the Apollo AI service endpoint is reachable and responding.
Performs a connectivity test to ensure the external AI service is available before attempting to make actual queries.
Returns
true
if the Apollo endpoint responds successfully, false
otherwise.
Examples
case AiAssistant.endpoint_available?() do
true ->
# Proceed with AI queries
false ->
# Show service unavailable message
end
@spec find_pending_user_messages(Lightning.AiAssistant.ChatSession.t()) :: [ Lightning.AiAssistant.ChatMessage.t() ]
Finds all pending user messages in a chat session.
Retrieves messages that have been sent by users but are still waiting for processing or AI responses. Useful for identifying stuck or failed requests.
Parameters
session
- The%ChatSession{}
to search
Returns
List of %ChatMessage{}
structs with :role
of :user
and :status
of :pending
.
Examples
pending_messages = AiAssistant.find_pending_user_messages(session)
if length(pending_messages) > 0 do
# Handle stuck messages
end
Retrieves a chat session by ID with all related data preloaded.
Fetches a complete chat session including:
- All non-cancelled messages ordered by creation time
- User information for each message
- Session metadata
- Project information (for workflow template sessions)
Parameters
id
- UUID string of the session to retrieve
Returns
A ChatSession
struct with preloaded :messages
and nested :user
data.
For workflow template sessions, the :project
association is also preloaded.
Raises
Ecto.NoResultsError
if no session exists with the given ID.
Examples
# Job session
session = AiAssistant.get_session!("123e4567-e89b-12d3-a456-426614174000")
IO.puts("Session has # {length(session.messages)} messages")
# Workflow template session (includes project)
session = AiAssistant.get_session!("workflow-session-id")
IO.puts("Workflow for project: # {session.project.name}")
@spec has_more_sessions?( Lightning.Projects.Project.t() | Lightning.Workflows.Job.t(), integer() ) :: boolean()
Checks if additional sessions are available beyond the current count.
This is a convenience function to determine if there are more sessions to load without fetching the actual data. Useful for "Load More" UI patterns.
Parameters
resource
- A%Project{}
or%Job{}
structcurrent_count
- Number of sessions already loaded
Returns
true
if more sessions exist, false
otherwise.
Examples
if AiAssistant.has_more_sessions?(project, 20) do
# Show "Load More" button
end
@spec list_sessions( Lightning.Projects.Project.t() | Lightning.Workflows.Job.t(), :asc | :desc, keyword() ) :: %{ sessions: [Lightning.AiAssistant.ChatSession.t()], pagination: LightningWeb.Live.AiAssistant.PaginationMeta.t() }
Returns paginated chat sessions with metadata for improved user experience.
Retrieves chat sessions associated with either a Project (workflow template sessions) or a Job (job-specific sessions). Results are paginated and include total counts and navigation metadata.
Parameters
resource
- A%Project{}
,%Job{}
, or%Snapshot.Job{}
struct to filter sessions bysort_direction
- Sort order, either:asc
or:desc
(default::desc
)opts
- Keyword list of options::offset
- Number of records to skip (default: 0):limit
- Maximum number of records to return (default: 20)
Returns
A map containing:
:sessions
- List ofChatSession
structs with preloaded data:pagination
-PaginationMeta
struct with navigation information
Examples
# Get recent sessions for a project
%{sessions: sessions, pagination: meta} =
AiAssistant.list_sessions(project, :desc, offset: 0, limit: 10)
# Get older sessions for a job
%{sessions: sessions, pagination: meta} =
AiAssistant.list_sessions(job, :asc, offset: 10, limit: 5)
@spec mark_disclaimer_read(Lightning.Accounts.User.t()) :: {:ok, Lightning.Accounts.User.t()}
Records that a user has read and accepted the AI assistant disclaimer.
Updates the user's preferences with a timestamp indicating when they acknowledged the AI assistant terms and conditions.
Parameters
user
- The%User{}
who read the disclaimer
Returns
{:ok, user}
- Successfully recorded disclaimer acceptance.
Examples
{:ok, updated_user} = AiAssistant.mark_disclaimer_read(current_user)
@spec put_expression_and_adaptor( Lightning.AiAssistant.ChatSession.t(), String.t(), String.t() ) :: Lightning.AiAssistant.ChatSession.t()
Adds job-specific context to a chat session for enhanced AI assistance.
Enriches a session with the job's expression code and adaptor information, enabling the AI to provide more targeted and relevant assistance.
Parameters
session
- The%ChatSession{}
to enhanceexpression
- The job's expression code as a stringadaptor
- The adaptor name/identifier for the job
Returns
An updated ChatSession
struct with :expression
and :adaptor
fields populated.
The adaptor is resolved through Lightning.AdaptorRegistry
.
Examples
enhanced_session = AiAssistant.put_expression_and_adaptor(
session,
"fn(state) => { return {...state, processed: true}; }",
"@openfn/language-http"
)
@spec query(Lightning.AiAssistant.ChatSession.t(), String.t(), map()) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, String.t() | Ecto.Changeset.t()}
Queries the AI assistant for job-specific code assistance.
Sends a user query to the Apollo AI service along with job context (expression and adaptor) and conversation history. The AI provides targeted assistance for coding tasks, debugging, and adaptor-specific guidance.
Parameters
session
- The job-specific%ChatSession{}
with expression and adaptor contextcontent
- User's question or request for assistance
Returns
{:ok, session}
- AI responded successfully, session updated with response{:error, reason}
- Query failed, reason is either a string error message or changeset
Examples
case AiAssistant.query(session, "Why is my HTTP request failing?") do
{:ok, updated_session} ->
# AI provided assistance, check session.messages for response
{:error, "Request timed out. Please try again."} ->
# Handle timeout
{:error, changeset} ->
# Handle validation errors
end
@spec query_workflow( Lightning.AiAssistant.ChatSession.t(), String.t(), String.t() | nil ) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, String.t() | Ecto.Changeset.t()}
Queries the AI service for workflow template generation.
Sends a request to generate or modify workflow templates based on user requirements. Can include validation errors from previous attempts to help the AI provide corrections.
Parameters
session
- The workflow template%ChatSession{}
content
- User's description of desired workflow functionality or modificationserrors
- Optional string containing validation errors from previous workflow attempts
Returns
{:ok, session}
- Workflow template generated successfully{:error, reason}
- Generation failed, reason is either a string error message or changeset
Examples
# Initial workflow request
{:ok, session} = AiAssistant.query_workflow(
session,
"Create a workflow that syncs Salesforce contacts to a Google Sheet daily"
)
# Request with error corrections
{:ok, session} = AiAssistant.query_workflow(
session,
"Fix the validation errors",
"Invalid cron expression: '0 0 * * 8'"
)
@spec save_message(Lightning.AiAssistant.ChatSession.t(), map(), map(), map() | nil) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, Ecto.Changeset.t()}
Saves a message to an existing chat session.
Adds a new message to the session's message history and updates the session. For assistant messages, this also triggers AI usage tracking and limit enforcement.
Parameters
session
- The target%ChatSession{}
message
- Map containing message data with keys like:role
,:content
,:user
usage
- Map containing AI usage metrics (default:%{}
)meta
- Optional metadata to update on the session (default:nil
)
Returns
{:ok, session}
- Successfully saved message and updated session{:error, changeset}
- Validation or database errors
Examples
# Save user message
{:ok, updated_session} = AiAssistant.save_message(session, %{
role: :user,
content: "How do I handle errors?",
user: current_user
})
# Save assistant response with usage tracking
{:ok, updated_session} = AiAssistant.save_message(session, %{
role: :assistant,
content: "Here's how to handle errors..."
}, %{tokens_used: 150, cost: 0.003})
@spec title_max_length() :: non_neg_integer()
Returns the maximum allowed length for chat session titles.
Examples
iex> Lightning.AiAssistant.title_max_length()
40
@spec update_message_status( Lightning.AiAssistant.ChatSession.t(), Lightning.AiAssistant.ChatMessage.t(), atom() ) :: {:ok, Lightning.AiAssistant.ChatSession.t()} | {:error, Ecto.Changeset.t()}
Updates the status of a specific message within a chat session.
Changes the status of an individual message (e.g., from :pending
to :success
or :error
)
and returns the refreshed session with updated data.
Parameters
session
- The%ChatSession{}
containing the messagemessage
- The specific%ChatMessage{}
to updatestatus
- New status atom (e.g.,:pending
,:success
,:error
,:cancelled
)
Returns
{:ok, session}
- Successfully updated message, returns refreshed session{:error, changeset}
- Update failed with validation errors
Examples
# Mark a pending message as successful
{:ok, updated_session} = AiAssistant.update_message_status(
session,
pending_message,
:success
)
# Mark a message as cancelled
{:ok, updated_session} = AiAssistant.update_message_status(
session,
message,
:cancelled
)
@spec user_has_read_disclaimer?(Lightning.Accounts.User.t()) :: boolean()
Checks if a user has acknowledged the AI assistant disclaimer recently.
Verifies that the user has read and accepted the AI assistant terms and conditions within the last 24 hours. This ensures users are aware of AI limitations and usage terms.
Parameters
user
- The%User{}
struct to check
Returns
true
if disclaimer was read within 24 hours, false
otherwise.
Examples
if AiAssistant.user_has_read_disclaimer?(current_user) do
# User can access AI features
else
# Show disclaimer dialog
end