Memory & Skills
Agents have persistent storage that survives across conversations and restarts. This is split into file memory for human-readable notes, typed memory for searchable records, and skills for structured capabilities.
Workspace layout
Section titled “Workspace layout”workspace/├── memory/│ ├── MEMORY.md # Long-term memory│ └── 2026-02-23.md # Daily notes (date-stamped)├── skills/│ └── my-skill/│ └── SKILL.md # Skill definition├── images/ # Generated images├── HEARTBEAT.md # Periodic task instructions (optional)└── ... # Any other files the agent createsThe workspace path defaults to /opt/baal-agent/workspace and is configured via the WORKSPACE_PATH environment variable.
Memory system
Section titled “Memory system”The agent has two memory paths. File memory is edited with normal file tools. Typed memory is written and searched with dedicated tools.
Long-term memory
Section titled “Long-term memory”workspace/memory/MEMORY.md stores persistent knowledge that the agent should always have access to: user preferences, project context, important facts, and recurring patterns.
The agent is instructed (via its system prompt) to save important information here. For example, if a user says “I prefer Python over JavaScript,” the agent might append that to MEMORY.md so it remembers in future conversations.
Daily notes
Section titled “Daily notes”workspace/memory/YYYY-MM-DD.md files hold session-specific notes tied to a particular day. These are useful for tracking ongoing work, temporary context, and daily task lists.
Only today’s daily notes are loaded into context. Older daily notes remain on disk and can be read on demand, but are not injected automatically.
Typed memory
Section titled “Typed memory”Typed memory records are stored in the agent SQLite database with:
kind— category such asuser_fact,repo_convention,test_command, ordecisioncontent— compact declarative memory textsource— where the record came from- optional
metadata - archive state and timestamps
The agent can create records with remember_fact and retrieve them with
search_memory. Recent active records are injected under Typed Memory on each
turn, after being passed through the same prompt-injection scanner used for
file memory.
How memory is loaded
Section titled “How memory is loaded”On each conversation turn, the context builder reads:
memory/MEMORY.md— included under a “Long-term Memory” headingmemory/<today>.md— included under a “Today’s Notes” heading- recent typed memory records — included under a “Typed Memory” heading
These are injected as dynamic context near the end of the message list (just before the latest user message) to preserve KV cache efficiency. See Context & Compaction for details.
Before memory, daily notes, user profile, project context files, skill summaries,
or active TODO context are injected, Baal scans them for obvious prompt-injection
payloads. Hidden HTML instructions, attempts to override system/developer
instructions, secret exfiltration snippets, and tool-policy bypass attempts are
redacted with a [BLOCKED: ...] marker.
Skills system
Section titled “Skills system”Skills are structured capability definitions that teach the agent how to perform specific tasks. Each skill lives in its own directory under workspace/skills/.
Skill format
Section titled “Skill format”workspace/skills/my-skill/└── SKILL.mdA SKILL.md file can use either format:
Frontmatter format (recommended):
---name: "Data Analysis"description: "Analyze CSV data and generate charts"requires_tools: ["read_file", "execute_code"]platforms: ["api", "telegram"]---
## Instructions
When asked to analyze data:1. Read the CSV file2. Identify key metrics3. Generate a summary with charts...Legacy format (heading + first paragraph):
# Data Analysis
Analyze CSV data and generate charts.
## Instructions...How skills are loaded
Section titled “How skills are loaded”The context builder scans workspace/skills/*/SKILL.md and extracts a summary for each skill:
- From frontmatter: uses the
nameanddescriptionfields - If present,
requires_toolshides the skill unless all required tools are available - If present,
platformshides the skill unless the current channel matches - From legacy format: uses the directory name and the first non-heading paragraph
These summaries are included in the dynamic context as a bullet list:
## Available Skills
- **Data Analysis**: Analyze CSV data and generate charts (read `workspace/skills/data-analysis/SKILL.md` for details)- **Web Scraping**: Extract structured data from websites (read `workspace/skills/web-scraping/SKILL.md` for details)The agent sees the summary of every skill on every turn, but the full skill content is only loaded when the agent explicitly reads the SKILL.md file. This keeps the context small while making skills discoverable.
Skill summaries are cached and invalidated when a SKILL.md file is added,
removed, or changes size/mtime, so large skill directories do not need to be
fully rescanned on every prompt build.
Skill telemetry
Section titled “Skill telemetry”The runtime records skill lifecycle events in the durable event log:
skill.consideredwhen a turn builds the visible skill listskill.loadedwhen the agent readsworkspace/skills/<id>/SKILL.mdskill.draft.proposedwhen a high-tool-count task produces a reusable skill draft
Draft proposals are telemetry only in this phase. The agent does not automatically write or update skill files from the proposal.
Skill directory contents
Section titled “Skill directory contents”A skill directory can contain any files the agent needs — not just SKILL.md. For example, a skill might include template files, configuration snippets, or reference data. The SKILL.md file serves as the entry point.
Heartbeat
Section titled “Heartbeat”The heartbeat system allows agents to perform periodic background work. If HEARTBEAT_INTERVAL is set to a value greater than 0 (default: 1800 seconds / 30 minutes), the agent checks workspace/HEARTBEAT.md at that interval.
If the file contains actionable content (non-empty, non-comment lines or unchecked checkboxes), the agent runs a turn to process the instructions. Results are delivered to the owner as pending messages.
The heartbeat file supports:
- Plain text instructions
- Markdown task lists (
- [ ] taskfor pending,- [x] taskfor completed) - Comments (
<!-- ... -->) and headings are ignored when checking for actionable content
File watchers
Section titled “File watchers”Agents can also poll workspace/watchers.json from the same scheduler loop.
Each watcher records its first observed file or directory state, then triggers
a background job when that path changes:
[ { "id": "docs", "path": "docs/research", "task": "Review changed research notes and summarize any new decisions.", "enabled": true, "debounce": 60 }]Watcher jobs run with IDs like watcher:docs. State is stored in
workspace/.watcher_state.json; deleting that file resets the first-observed
baseline. Watcher checks emit runtime events named watcher.checked,
watcher.skipped, watcher.triggered, and watcher.error.