ash-framework

Comprehensive Ash framework guidelines for Elixir applications. Use when working with Ash resources, domains, actions, queries, changesets, policies, calculations, or aggregates. Covers code interfaces, error handling, validations, changes, relationships, and authorization. Read documentation before using Ash features - do not assume prior knowledge.

16 stars

Best use case

ash-framework is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Comprehensive Ash framework guidelines for Elixir applications. Use when working with Ash resources, domains, actions, queries, changesets, policies, calculations, or aggregates. Covers code interfaces, error handling, validations, changes, relationships, and authorization. Read documentation before using Ash features - do not assume prior knowledge.

Teams using ash-framework should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/ash-framework/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/ash-framework/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/ash-framework/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How ash-framework Compares

Feature / Agentash-frameworkStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Comprehensive Ash framework guidelines for Elixir applications. Use when working with Ash resources, domains, actions, queries, changesets, policies, calculations, or aggregates. Covers code interfaces, error handling, validations, changes, relationships, and authorization. Read documentation before using Ash features - do not assume prior knowledge.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Ash Framework Guidelines

Ash is a declarative framework for modeling domains with resources. **Read documentation before using features.**

## Code Interfaces

Define code interfaces on domains - avoid direct `Ash.get!/2` calls in LiveViews/Controllers:

```elixir
# In domain
resource Post do
  define :get_post, action: :read, get_by: [:id]
  define :list_posts, action: :read
  define :create_post, action: :create, args: [:title]
end

# Usage - prefer query option over manual Ash.Query building
posts = MyApp.Blog.list_posts!(
  query: [filter: [status: :published], sort: [published_at: :desc], limit: 10],
  load: [author: :profile, comments: [:author]]
)

post = MyApp.Blog.get_post!(id, load: [comments: [:author]])
```

**Authorization functions** are auto-generated: `can_create_post?(actor)`, `can_update_post?(actor, post)`.

**Using scopes**: Pass `scope: socket.assigns.scope` in LiveViews; use `context` parameter in hooks.

## Actions

- Create specific, well-named actions (not generic CRUD)
- Put business logic inside action definitions
- Use `before_action/after_action` for same-transaction logic
- Use `before_transaction/after_transaction` for external calls

```elixir
actions do
  create :sign_up do
    argument :invite_code, :string, allow_nil?: false
    change set_attribute(:joined_at, &DateTime.utc_now/0)
    change relate_actor(:creator)
  end
end
```

## Querying

**Important**: `Ash.Query.filter/2` is a macro - you must `require Ash.Query`:

```elixir
require Ash.Query

Post
|> Ash.Query.filter(status == :published)
|> Ash.Query.sort(published_at: :desc)
|> Ash.Query.load([:author, :comments])
|> Ash.Query.limit(10)
|> Ash.read!()
```

## Error Handling

- Use `!` variations (`Ash.create!`, `Domain.action!`) when expecting success
- Prefer `!` over pattern matching `{:ok, result} = ...`
- Error classes: `Forbidden` > `Invalid` > `Framework` > `Unknown`

## Validations

```elixir
# Built-in validations
validate compare(:age, greater_than_or_equal_to: 18)
validate match(:email, ~r/@/)
validate one_of(:status, [:active, :pending])

# Conditional validation
validate present(:phone) do
  where eq(:contact_method, "phone")
end

# Skip if prior validations failed
validate expensive_check() do
  only_when_valid? true
end
```

**Avoid redundant validations** - don't duplicate attribute constraints (`allow_nil? false` already validates presence).

## Changes

```elixir
# Built-in changes
change set_attribute(:status, "pending")
change relate_actor(:creator)
change atomic_update(:counter, expr(counter + 1))

# Custom change module
defmodule MyApp.Changes.Slugify do
  use Ash.Resource.Change

  def change(changeset, _opts, _context) do
    title = Ash.Changeset.get_attribute(changeset, :title)
    slug = title |> String.downcase() |> String.replace(~r/[^a-z0-9]+/, "-")
    Ash.Changeset.change_attribute(changeset, :slug, slug)
  end
end
```

**Prefer custom modules** over anonymous functions for changes, validations, preparations.

## Preparations

Modify queries before execution:

```elixir
prepare build(sort: [created_at: :desc])
prepare build(filter: [deleted: false])

# Conditional preparation
prepare build(filter: [visible: true]) do
  where argument_equals(:include_hidden, false)
end
```

## Data Layers

```elixir
use Ash.Resource,
  domain: MyApp.Blog,
  data_layer: AshPostgres.DataLayer  # or :embedded, Ash.DataLayer.Ets

postgres do
  table "posts"
  repo MyApp.Repo
end
```

## Migrations

Run `mix ash.codegen <name>` after modifying resources. Use `--dev` during development, final name at end.

## Testing

- Test through code interfaces
- Use `authorize?: false` when auth isn't the focus
- Use `Ash.can?` to test policies
- Use raising `!` functions

**Prevent deadlocks** - use unique values for identity fields in concurrent tests:

```elixir
%{email: "test-#{System.unique_integer([:positive])}@example.com"}
```

## References

- **Authorization & Policies**: See [references/policies.md](references/policies.md)
- **Relationships**: See [references/relationships.md](references/relationships.md)
- **Calculations & Aggregates**: See [references/calculations.md](references/calculations.md)

Related Skills

athena-framework

16
from diegosouzapw/awesome-omni-skill

Use this skill when working with Athena Framework for Crystal. Athena is a modular ecosystem of independent, reusable components including: Framework (ATH) for web apps, DependencyInjection (ADI) for IoC containers, Routing (ART) for HTTP routing, Serializer (ASR) for object serialization, Validator (AVD) for validation, Console (ACON) for CLI tools, EventDispatcher (AED) for event-driven architecture, and more. Use for building Crystal web applications, REST APIs, CLI tools, or integrating individual components.

argentic-framework-development

16
from diegosouzapw/awesome-omni-skill

Expert knowledge for building AI agents with Argentic - a Python microframework for async MQTT-based agents with multi-LLM support, custom tools, and multi-agent orchestration

api-framework-express

16
from diegosouzapw/awesome-omni-skill

Express.js routes, middleware, error handling, request/response patterns

agent-framework-azure-ai-py

16
from diegosouzapw/awesome-omni-skill

Build Azure AI Foundry agents using the Microsoft Agent Framework Python SDK (agent-framework-azure-ai). Use when creating persistent agents with AzureAIAgentsProvider, using hosted tools (code int...

Advanced Playwright E2E Framework

16
from diegosouzapw/awesome-omni-skill

Enterprise-grade Playwright test automation framework using 8-layer architecture with Page Object Model, Module Pattern, custom fixtures, API testing layer, structured logging, data generators, multi-browser support, Docker, CI/CD pipelines, and custom HTML reporting.

Actix-web Framework

16
from diegosouzapw/awesome-omni-skill

High-performance Rust web framework with actor model foundation.

account-health-framework

16
from diegosouzapw/awesome-omni-skill

Use to score accounts, flag risks, and standardize remediation triggers.

9d-framework

16
from diegosouzapw/awesome-omni-skill

9D product development framework

agricultural-easement-negotiation-frameworks

16
from diegosouzapw/awesome-omni-skill

Expert in negotiating utility easements with farmers including farm operation impact assessment (crop production, livestock, equipment), compensation structure design (one-time vs. recurring, mitigation works), and multi-generational farm psychology. Use when negotiating transmission line, pipeline, or drainage easements with agricultural landowners. Key terms include agricultural easement, farm operation impacts, tower placement, crop loss, irrigation impacts, easement compensation, farm succession

microsoft-agent-framework

16
from diegosouzapw/awesome-omni-skill

Expert guidance for implementing AI agents and multi-agent workflows using Microsoft Agent Framework. Use when adding AI agent capabilities, implementing multi-agent orchestration patterns, integrating MCP tools, or building intelligent automation systems. Emphasizes gathering up-to-date information from official documentation before implementation.

data-quality-frameworks

16
from diegosouzapw/awesome-omni-skill

Implement data quality validation with Great Expectations, dbt tests, and data contracts. Use when building data quality pipelines, implementing validation rules, or establishing data contracts.

agent-os-framework

16
from diegosouzapw/awesome-omni-skill

Generate standardized .agent-os directory structure with product documentation, mission, tech-stack, roadmap, and decision records. Enables AI-native workflows.