docs: Added documentation for the new memory system
+1
@@ -38,6 +38,7 @@ Coming from [AIChat](https://github.com/sigoden/aichat)? Follow the [migration g
|
|||||||
* [Macros](Macros): Automate repetitive tasks and workflows with Coyote "scripts" (macros).
|
* [Macros](Macros): Automate repetitive tasks and workflows with Coyote "scripts" (macros).
|
||||||
* [RAG](RAG): Retrieval-Augmented Generation for enhanced information retrieval and generation.
|
* [RAG](RAG): Retrieval-Augmented Generation for enhanced information retrieval and generation.
|
||||||
* [Sessions](Sessions): Manage and persist conversational contexts and settings across multiple interactions.
|
* [Sessions](Sessions): Manage and persist conversational contexts and settings across multiple interactions.
|
||||||
|
* [Memory](Memory): Persistent file-based memory that survives across sessions. Bootstrap with `coyote --init-memory [global|workspace]`.
|
||||||
* [Roles](Roles): Customize model behavior for specific tasks or domains.
|
* [Roles](Roles): Customize model behavior for specific tasks or domains.
|
||||||
* [Skills](Skills): Modular knowledge or capability packs the LLM can load and unload mid-conversation. Multiple skills compose; instructions stack, tools and MCPs union.
|
* [Skills](Skills): Modular knowledge or capability packs the LLM can load and unload mid-conversation. Multiple skills compose; instructions stack, tools and MCPs union.
|
||||||
* [Agents](Agents): Leverage AI agents to perform complex tasks and workflows, including sub-agent spawning, teammate messaging, and user interaction tools.
|
* [Agents](Agents): Leverage AI agents to perform complex tasks and workflows, including sub-agent spawning, teammate messaging, and user interaction tools.
|
||||||
|
|||||||
+207
@@ -0,0 +1,207 @@
|
|||||||
|
# Memory
|
||||||
|
|
||||||
|
Coyote can maintain a **persistent memory file system** that survives across sessions. Memory captures cross-session
|
||||||
|
facts about you, your project, and your preferences, complementing [Sessions](Sessions) (which handle
|
||||||
|
within-conversation state) and [Skills](Skills) (which are static knowledge packs).
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
The fastest path is the bootstrap command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Workspace memory (per-project)
|
||||||
|
cd /path/to/your/project
|
||||||
|
coyote --init-memory workspace
|
||||||
|
# → creates ./COYOTE.md with a skeleton
|
||||||
|
|
||||||
|
# Global memory (per-user, applies everywhere)
|
||||||
|
coyote --init-memory global
|
||||||
|
# → creates <config_dir>/memory/MEMORY.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Then edit the file with anything you want the LLM to remember:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Project Memory
|
||||||
|
|
||||||
|
This project is a Rust CLI tool. I prefer terse responses and concrete code examples.
|
||||||
|
```
|
||||||
|
|
||||||
|
Run coyote in that directory and the memory content is injected into every system prompt automatically. The LLM will see and use the `memory__*` tools to update it over time (when function calling is on).
|
||||||
|
|
||||||
|
That's it for "lite mode." For structured memory, see below.
|
||||||
|
|
||||||
|
> Memory is **opt-in by file presence** for the read path. If no marker exists on disk, no workspace memory is injected and global memory is loaded only if the global marker exists. `--init-memory` is the explicit consent signal.
|
||||||
|
|
||||||
|
> **Write-side exception (git repos only):** if the LLM calls `memory__write(scope=workspace)` and no marker exists, coyote auto-bootstraps a structured layout at the git root and adds `.coyote/memory/` to `.gitignore`. See [Git-Repo Auto-Bootstrap](#git-repo-auto-bootstrap) below. Outside a git repo this fails with a hint to run `coyote --init-memory workspace`.
|
||||||
|
|
||||||
|
> **Re-running is safe.** `--init-memory` refuses to overwrite an existing marker — it prints `Memory marker already exists at '...'` and exits without touching the file. Useful in setup scripts.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
Memory has two scopes:
|
||||||
|
|
||||||
|
- **Global** (user-level): `~/.config/coyote/memory/` - facts about you that apply everywhere
|
||||||
|
- **Workspace** (project-level): `<workspace>/COYOTE.md` (lite) or `<workspace>/.coyote/memory/` (structured)
|
||||||
|
|
||||||
|
Memory is **opt-in by workspace**: coyote walks up from your current directory looking for a memory marker. If none is
|
||||||
|
found, no workspace memory is loaded. Global memory is loaded if it exists.
|
||||||
|
|
||||||
|
When both a `.coyote/memory/MEMORY.md` and a `COYOTE.md` exist at the same level, the structured layout wins.
|
||||||
|
|
||||||
|
### Git-Repo Auto-Bootstrap
|
||||||
|
|
||||||
|
If the LLM tries to write workspace memory and no marker exists in any ancestor, coyote checks for a git repository before erroring:
|
||||||
|
|
||||||
|
- **Git root found** (ancestor contains a `.git` directory or file, worktrees and submodules included): coyote creates
|
||||||
|
`<git_root>/.coyote/memory/MEMORY.md` with an empty index, appends `.coyote/memory/` to `<git_root>/.gitignore`
|
||||||
|
(idempotent; no duplicate if you already have it, including the trailing-slash-less form), and emits a `WARN`-level
|
||||||
|
log line so you know it happened. The write then proceeds.
|
||||||
|
- **No git root**: the write fails with an error pointing you at `coyote --init-memory workspace`.
|
||||||
|
|
||||||
|
The rationale: if you're in a git repo, the natural anchor for workspace-wide memory is the repo root, and the
|
||||||
|
gitignore entry keeps the LLM's drill files out of version control by default. If you're not in a git repo, the
|
||||||
|
bootstrap location is genuinely ambiguous, so coyote requires explicit consent via `--init-memory`.
|
||||||
|
|
||||||
|
This only affects the write path. The read path remains opt-in: until a marker exists, no workspace memory is injected.
|
||||||
|
|
||||||
|
## Two Halves: Read and Write
|
||||||
|
|
||||||
|
Memory has two independent halves:
|
||||||
|
|
||||||
|
| Half | Requires | Behavior |
|
||||||
|
|-----------|--------------------------|-----------------------------------------------------------------|
|
||||||
|
| **Read** | Nothing | Memory content is injected into the system prompt every session |
|
||||||
|
| **Write** | Function calling support | The LLM uses `memory__*` tools to curate memory autonomously |
|
||||||
|
|
||||||
|
If your model lacks function calling, memory degrades to read-only: you maintain the files manually, the LLM sees them.
|
||||||
|
In read-only mode coyote injects all known drill files (up to the without-tools cap) so the model has full context
|
||||||
|
without needing tools.
|
||||||
|
|
||||||
|
## Structured Mode
|
||||||
|
|
||||||
|
For non-trivial memory, use the structured layout:
|
||||||
|
|
||||||
|
```
|
||||||
|
<workspace>/.coyote/memory/
|
||||||
|
├── MEMORY.md # index (always injected)
|
||||||
|
├── project_compliance.md
|
||||||
|
├── feedback_terse.md
|
||||||
|
└── reference_dashboards.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Each drill file has YAML frontmatter:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: project_compliance
|
||||||
|
description: Compliance constraints driving the auth rewrite
|
||||||
|
type: project
|
||||||
|
---
|
||||||
|
|
||||||
|
We must store session tokens server-side per the 2026 audit. ...
|
||||||
|
```
|
||||||
|
|
||||||
|
`MEMORY.md` is what gets injected on every prompt. It serves two purposes:
|
||||||
|
1. **An index** of available drill files (one line per file: name + description)
|
||||||
|
2. **A home for universal facts** the LLM should always see (user identity, hard rules, binding feedback)
|
||||||
|
|
||||||
|
Drill files are fetched on demand by the LLM via `memory__read`. Keep them focused; for facts that should always be
|
||||||
|
visible, write them directly in `MEMORY.md` instead.
|
||||||
|
|
||||||
|
## Memory Types
|
||||||
|
|
||||||
|
| Type | Purpose | Example |
|
||||||
|
|-------------|---------------------------------------------------|------------------------------------------------|
|
||||||
|
| `user` | Persistent facts about you | "Senior Rust dev, terse responses preferred" |
|
||||||
|
| `feedback` | Past corrections that should bind future behavior | "Never use `as any`; got burned in incident X" |
|
||||||
|
| `project` | Workspace-specific facts | "API freeze begins 2026-03-05" |
|
||||||
|
| `reference` | Pointers to external systems | "Bugs tracked in Linear project INGEST" |
|
||||||
|
|
||||||
|
The `type:` field is informational, meaning coyote does not change behavior based on it. It exists so the LLM can
|
||||||
|
categorize its own writes and so you can grep by category.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
When function calling is enabled, coyote exposes:
|
||||||
|
|
||||||
|
- `memory__read(name)`: read a specific drill file by its slug
|
||||||
|
- `memory__write(name, description, content, scope, type)`: create or replace a drill file (`scope`: `global` |
|
||||||
|
`workspace`)
|
||||||
|
- `memory__list()`: see all known drill files with metadata
|
||||||
|
- `memory__lint()`: health-check (orphans, broken `[[wikilinks]]`, oversized files >2K chars)
|
||||||
|
|
||||||
|
The LLM is instructed to update `MEMORY.md` whenever it writes a new file. Two silent promotions can happen on a
|
||||||
|
`memory__write(scope=workspace)`:
|
||||||
|
|
||||||
|
- **Lite -> structured**: if the workspace is in lite mode (`COYOTE.md` only), the new file goes into
|
||||||
|
`<workspace>/.coyote/memory/` and `COYOTE.md` is left untouched.
|
||||||
|
- **None -> structured (git only)**: if no marker exists anywhere, coyote auto-bootstraps at the git root. See
|
||||||
|
[Git-Repo Auto-Bootstrap](#git-repo-auto-bootstrap).
|
||||||
|
|
||||||
|
## Toggles
|
||||||
|
|
||||||
|
Memory can be disabled at multiple levels (most specific wins):
|
||||||
|
|
||||||
|
1. **CLI flag**: `coyote --no-memory ...` (per-invocation; sets `false` at the app layer)
|
||||||
|
2. **Graph agents**: memory is always off
|
||||||
|
3. **Agent config**: `memory: false` in the agent's `config.yaml`
|
||||||
|
4. **Session**: `memory: false` in the saved session frontmatter (also settable via the session's `set_memory` API)
|
||||||
|
5. **Role config**: `memory: false` in role frontmatter
|
||||||
|
6. **AppConfig**: `memory: false` in global config
|
||||||
|
7. **Workspace presence** (read side): absence of `COYOTE.md` and `.coyote/memory/`. On the write side,
|
||||||
|
`memory__write(scope=workspace)` inside a git repo can auto-create `.coyote/memory/` (see
|
||||||
|
[Git-Repo Auto-Bootstrap](#git-repo-auto-bootstrap) for more information).
|
||||||
|
|
||||||
|
Resolution cascade for the boolean flag: **agent > session > role > app**, with the first explicit value winning.
|
||||||
|
No value means "no opinion, defer to next layer." If the flag resolves to true but no memory exists on disk anywhere,
|
||||||
|
memory stays off (no empty injection).
|
||||||
|
|
||||||
|
## Caps
|
||||||
|
|
||||||
|
Two cap constants control how much memory content is injected:
|
||||||
|
|
||||||
|
| Field (in AppConfig) | Default | When |
|
||||||
|
|----------------------------|--------------|----------------------------------------------------------------------------|
|
||||||
|
| `memory_cap_with_tools` | 6,000 chars | Function calling on. Only indexes injected, drill bodies fetched on demand |
|
||||||
|
| `memory_cap_without_tools` | 12,000 chars | Function calling off. Indexes plus drill bodies up to the cap |
|
||||||
|
|
||||||
|
In without-tools mode, drill files are appended alphabetically until the cap is exhausted; any omitted files are
|
||||||
|
reported via a truncation marker in the injection block.
|
||||||
|
|
||||||
|
If the `MEMORY.md` indexes alone exceed the cap, coyote injects them fully and logs a warning. A partial index would
|
||||||
|
confuse the LLM more than going over budget by a few hundred chars.
|
||||||
|
|
||||||
|
## When NOT to Use Memory
|
||||||
|
|
||||||
|
- **One-shot prompts**: no recurring context, memory is overhead
|
||||||
|
- **Privacy-sensitive sessions**: memory persists on disk in plaintext
|
||||||
|
- **Throwaway scripts using coyote as a library**: the script is the context
|
||||||
|
|
||||||
|
For session-specific suppression without changing config, use `--no-memory` or set `memory: false` on a Session before
|
||||||
|
saving it.
|
||||||
|
|
||||||
|
## Comparison
|
||||||
|
|
||||||
|
| | Memory | [Sessions](Sessions) | [Skills](Skills) | [RAG](RAG) | [Vault](Vault) |
|
||||||
|
|-------------|---------------------|----------------------|------------------|--------------------|----------------|
|
||||||
|
| Scope | Cross-session facts | One conversation | Knowledge packs | Document retrieval | Secrets |
|
||||||
|
| Lifecycle | Evolves over time | Per-conversation | Static, curated | Indexed, retrieved | Long-lived |
|
||||||
|
| Encrypted | No (plaintext) | No | No | No | Yes |
|
||||||
|
| LLM writes? | Yes (with tools) | No | No | No | No |
|
||||||
|
|
||||||
|
## Privacy & Security
|
||||||
|
|
||||||
|
Memory files are **plaintext markdown on disk**. Anything you (or the LLM) writes there is readable to anyone with
|
||||||
|
access to your home directory.
|
||||||
|
|
||||||
|
**Never store secrets in memory.** Use [Vault](Vault) for credentials and API keys. The default memory instructions
|
||||||
|
explicitly tell the LLM not to write secrets, but treat that as a defense-in-depth measure, not a guarantee.
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Sessions](Sessions): per-conversation state
|
||||||
|
- [Skills](Skills): modular knowledge packs
|
||||||
|
- [Roles](Roles): model behavior customization (supports `memory: false`)
|
||||||
|
- [RAG](RAG): document retrieval (complementary, not redundant)
|
||||||
|
- [Vault](Vault): encrypted secret storage
|
||||||
+3
@@ -6,6 +6,9 @@ Think of them kind of like a baby: That baby can grow up to do anything! Be a re
|
|||||||
The only difference is that with roles, we're explicitly telling the LLM what we want it to be. Also: the LLM is already
|
The only difference is that with roles, we're explicitly telling the LLM what we want it to be. Also: the LLM is already
|
||||||
grown up so we don't have to wait!
|
grown up so we don't have to wait!
|
||||||
|
|
||||||
|
> Roles can disable the memory system for their scope by setting `memory: false` in their frontmatter.
|
||||||
|
> See [Memory](Memory) for the full toggle cascade.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
+3
@@ -7,6 +7,9 @@ answers and ask follow-up questions and the model will know what you're referrin
|
|||||||
|
|
||||||
Sessions can be temporary, or can be saved so you can continue conversations at a later time.
|
Sessions can be temporary, or can be saved so you can continue conversations at a later time.
|
||||||
|
|
||||||
|
> Sessions persist *one conversation*. For facts that should survive across all sessions (e.g., user preferences,
|
||||||
|
> project constraints, accumulated feedback), see [Memory](Memory).
|
||||||
|
|
||||||
Saved sessions are stored in the `sessions` subdirectory of the Coyote configuration directory. The location of the
|
Saved sessions are stored in the `sessions` subdirectory of the Coyote configuration directory. The location of the
|
||||||
`sessions` directory varies by system, so you can use the following command to find the `sessions` directory if you need
|
`sessions` directory varies by system, so you can use the following command to find the `sessions` directory if you need
|
||||||
it:
|
it:
|
||||||
|
|||||||
+3
@@ -5,6 +5,9 @@ the user), a skill is a capability the model layers onto whatever role/agent/ses
|
|||||||
Multiple skills can be loaded at once. They compose, meaning their instructions stack, their tool whitelists union, and
|
Multiple skills can be loaded at once. They compose, meaning their instructions stack, their tool whitelists union, and
|
||||||
their declared MCP servers get acquired automatically.
|
their declared MCP servers get acquired automatically.
|
||||||
|
|
||||||
|
> Skills are *static* curated knowledge packs. For *evolving* facts the LLM curates over time across sessions,
|
||||||
|
> see [Memory](Memory).
|
||||||
|
|
||||||
Common uses:
|
Common uses:
|
||||||
|
|
||||||
- **Methodology overlays** ("how to do git surgery", "how to review code").
|
- **Methodology overlays** ("how to do git surgery", "how to review code").
|
||||||
|
|||||||
+5
@@ -45,6 +45,11 @@
|
|||||||
- [Limitations](Graph-Agents#limitations--gotchas)
|
- [Limitations](Graph-Agents#limitations--gotchas)
|
||||||
|
|
||||||
## Knowledge & Automation
|
## Knowledge & Automation
|
||||||
|
- [Memory](Memory)
|
||||||
|
- [Quick Start](Memory#quick-start)
|
||||||
|
- [Structured Mode](Memory#structured-mode)
|
||||||
|
- [Tools](Memory#tools)
|
||||||
|
- [Toggles](Memory#toggles)
|
||||||
- [RAG](RAG)
|
- [RAG](RAG)
|
||||||
- [Macros](Macros)
|
- [Macros](Macros)
|
||||||
- [Roles](Roles)
|
- [Roles](Roles)
|
||||||
|
|||||||
Reference in New Issue
Block a user