ex_athena ships two file-based context mechanisms that let projects teach the agent things without code changes: memory (rules the agent should always know) and skills (instructions the agent loads on demand).
Both are auto-discovered at Loop.run/2 start. Both can be disabled
or overridden per-call.
Memory — AGENTS.md / CLAUDE.md
Drop an AGENTS.md (preferred) or CLAUDE.md at your project root
and ex_athena prepends its contents as a user-context message at the
very front of every conversation:
project root/
AGENTS.md # project-wide rules (committed)
AGENTS.local.md # personal scratch (gitignore this one)
src/...Plus a global personal file at ~/.config/ex_athena/AGENTS.md for
cross-project preferences.
Load order (each level is a separate user-context message):
- User —
~/.config/ex_athena/AGENTS.md - Project —
<cwd>/AGENTS.md(orCLAUDE.mdas a fallback) - Local override —
<cwd>/AGENTS.local.md
AGENTS.md wins over CLAUDE.md at the same level — matches opencode
for cross-tool compatibility.
Why user-context, not system?
The Claude Code paper notes that Claude Code delivers memory as
user-context (probabilistic compliance) rather than as a system prompt
(deterministic compliance). We copy the pattern: each loaded file
becomes a %Message{role: :user, name: "memory"} placed at the front
of the conversation.
The compactor pins these messages — Compactors.Summary extends its
effective pinned-prefix by meta[:memory_count] so memory messages
survive every compaction cycle.
Disable or override
# Skip memory entirely
ExAthena.run("hi", tools: :all, memory: false)
# Provide an explicit list (e.g. dynamically constructed for a tenant)
ExAthena.run("hi",
tools: :all,
memory: [
ExAthena.Messages.user("...your custom rules...")
|> Map.put(:name, "memory")
])Skills — SKILL.md with progressive disclosure
A skill is a directory containing a SKILL.md markdown file. The
file's frontmatter is auto-injected into the system prompt; the body
loads only when the model decides it needs the skill.
project root/
.exathena/skills/
deploy/SKILL.md
audit/SKILL.mdPlus the user-level home at ~/.config/ex_athena/skills/<name>/SKILL.md.
SKILL.md shape
---
name: deploy
description: Ship the staging branch to production
allowed-tools: [bash, read]
disable-model-invocation: false
---
# How to deploy
1. Run `mix test` and ensure it passes.
2. Run `bin/deploy` and wait for the green check.
3. Tail `prod-logs` for two minutes; abort + revert on errors.Required: name, description. Optional:
allowed-tools— restricts which tools can run while the skill is active (PR3a's:active_skillspermission scoping).disable-model-invocation— hides the skill from the catalog. The host can still pre-attach viaSkills.preload/3.
Two activation paths
Sentinel auto-load. When the model writes [skill: deploy] in its
response, the loop intercepts it (after extracting tool calls, before
the next iteration) and appends the skill body as a system-role message.
Idempotent — already-loaded skills are no-ops:
Model says: "I'll [skill: deploy] this branch."
↓
Loop appends a system message tagged `name: "skill:deploy"` containing
the SKILL.md body. The model sees it on the next iteration.Pre-load. The host knows up-front which skills the agent will need:
ExAthena.run("ship it",
tools: :all,
preload_skills: ["deploy", "audit"])Pre-loaded skill messages sit at the front of the conversation alongside memory; the compactor pins them.
Catalog rendering
When skills are present, ex_athena appends a section to the system prompt:
## Available Skills
Use `[skill: <name>]` in your response to load a skill's full instructions.
- `audit` — Audit perms.
- `deploy` — Ship the staging branch to production~50 tokens per skill in the catalog. Bodies stay on disk until the model asks for them.
Disable or override
# Skip discovery entirely
ExAthena.run("hi", tools: :all, skills: false)
# Provide an explicit map (e.g. constructed from a database)
ExAthena.run("hi",
tools: :all,
skills: %{
"deploy" => %ExAthena.Skills.Skill{
name: "deploy",
description: "Ship",
body: "...",
path: "<dynamic>"
}
})Auto-memory writes (light)
The agent can append to memory files via the existing Write tool.
The path ~/.config/ex_athena/AGENTS.md is allowlisted by default for
this case — no special tool needed.
See also
ExAthena.MemoryExAthena.Skills- Compaction pipeline — memory + pre-loaded skills are pinned across compactions.
- Permissions —
allowed-toolsfrontmatter scopes the active permission set.