An AI-powered therapeutic chat service built with the Ash Framework and Phoenix.
This repository contains the companion code for a series of blog posts published on AppSignal exploring the Ash Framework ecosystem, including:
- Ash Core - Domains and Resources
- Ash Oban - Background job processing for AI responses
- Ash Notification - Real-time client notifications
- Ash AI - Structured AI response handling
- Ash TypeScript RPC - Type-safe frontend integration
This series is written by Shankar Dhanasekaran, author of Domain Modelling with Ash Framework, a comprehensive guide to building robust Elixir applications with Ash.
This project demonstrates how to build a complete business domain using Ash's declarative approach to modeling resources, relationships, and actions.
AshTherapy is a demo application that showcases the power of the Ash Framework by implementing a therapeutic chat service where:
- Users can start conversations with specific goals or motives
- They exchange messages with an AI companion
- All interactions are tracked and persisted through Ash resources
The application is built around three core Ash resources in the AshTherapy.Therapy domain:
- User - Represents users of the service
- Conversation - Represents therapy sessions with goals and status tracking
- Message - Represents individual messages in a conversation (sent by either user or AI)
All business logic, validations, and database operations are defined declaratively using Ash's DSL, following the principle: "Declare once, derive the rest".
- Elixir 1.15 or later
- PostgreSQL 14.17 or later
- Node.js (for asset compilation)
-
Clone the repository and install dependencies:
git clone https://github.com/devcarrots/ash_therapy cd ash_therapy mix deps.get -
Setup the database:
mix ash.setup
This command will:
- Create the database
- Run all migrations (generated from Ash resources)
- Run seeds if any
-
Install and build assets:
mix assets.setup mix assets.build
-
Start the Phoenix server:
mix phx.server
Or start with an interactive Elixir shell:
iex -S mix phx.server
Now you can visit
localhost:4000from your browser.
You can interact with the Ash resources directly through IEx to understand how the domain works:
iex -S mixuser =
AshTherapy.Therapy.User
|> Ash.Changeset.for_create(:register_user, %{name: "Nisha"})
|> Ash.create!()conversation =
AshTherapy.Therapy.Conversation
|> Ash.Changeset.for_create(:start_conversation, %{
goal: "I want to handle work stress",
user_id: user.id
})
|> Ash.create!()user_message =
AshTherapy.Therapy.Message
|> Ash.Changeset.for_create(:send_message, %{
content: "I feel anxious every Monday morning.",
conversation_id: conversation.id
})
|> Ash.create!()ai_message =
AshTherapy.Therapy.Message
|> Ash.Changeset.for_create(:send_message, %{
content: "That sounds difficult. What usually triggers this feeling?",
conversation_id: conversation.id,
role: :ai
})
|> Ash.create!()full_conversation =
AshTherapy.Therapy.Conversation
|> Ash.Query.for_read(:get_conversation_with_messages, %{id: conversation.id})
|> Ash.read!()
|> List.first()
# Inspect the conversation and its messages
full_conversation.messageslib/
├── ash_therapy/
│ ├── therapy.ex # Ash Domain
│ └── therapy/
│ ├── user.ex # User resource
│ ├── conversation.ex # Conversation resource
│ └── message.ex # Message resource
├── ash_therapy_web/
│ ├── controllers/
│ ├── components/
│ └── ...