Memory & Skills
Octos has a layered memory system and an extensible skill framework. Memory gives the agent persistent context across sessions. Skills give the agent new tools and capabilities.
Bootstrap Files
These files are loaded into the system prompt at startup. Create them with octos init.
| File | Purpose |
|---|---|
.octos/AGENTS.md | Agent instructions and guidelines |
.octos/SOUL.md | Personality and values |
.octos/USER.md | User information and preferences |
.octos/TOOLS.md | Tool-specific guidance |
.octos/IDENTITY.md | Custom identity definition |
Bootstrap files are hot-reloaded – edit them and the agent picks up changes without a restart.
Memory System
Octos uses a 3-layer memory architecture that combines automatic recording with agent-driven knowledge management:
┌──────────────────────────────────────────────────────────────────┐
│ System Prompt (every turn) │
│ │
│ 1. Episodic Memory ─── top 6 relevant past task experiences │
│ 2. Memory Context ─── MEMORY.md + recent 7 days daily notes │
│ 3. Entity Bank ─── one-line abstracts of all known entities │
│ │
│ Tools: save_memory / recall_memory (entity bank CRUD) │
└──────────────────────────────────────────────────────────────────┘
Layer 1: Episodic Memory (automatic)
Every completed task is automatically recorded as an episode in episodes.redb, a persistent embedded database. Each episode stores:
- Summary — LLM-generated, truncated to 500 chars
- Outcome — Success, Failure, Blocked, or Cancelled
- Files modified — list of file paths touched during the task
- Key decisions — notable choices made during execution
- Working directory — scope for directory-scoped retrieval
At the start of each new task, the agent queries the episode store for up to 6 relevant past experiences using:
- Hybrid search (default when embedding is configured): combines BM25 keyword matching (30% weight) with HNSW vector similarity (70% weight)
- Keyword search (fallback when no embedder): matches query terms against episode summaries, scoped to the same working directory
Embedding configuration (in config.json):
{
"embedding": {
"provider": "openai",
"api_key_env": "OPENAI_API_KEY",
"base_url": null
}
}
When configured, the agent embeds each episode summary in a fire-and-forget background task and stores the vector alongside the episode. At query time, the task instruction is embedded and used for vector search. When omitted, the system falls back to BM25-only keyword matching.
Layer 2: Long-Term Memory & Daily Notes (file-based)
Long-term memory (.octos/memory/MEMORY.md) holds persistent facts and notes that survive across all sessions. Edit this file manually or via the write_file tool — it is injected verbatim into the system prompt on every turn.
Daily notes (.octos/memory/YYYY-MM-DD.md) provide a rolling window of recent activity. The last 7 days of daily notes are automatically included in the agent’s context. These files are created manually or via the write_file tool — the memory-refresh pipeline below consolidates into MEMORY.md, not the daily notes.
MEMORY.md can be edited by hand, but once the refresh pipeline has migrated it, every blank-line-separated block must keep its trailing ^m… id. Adding an un-id’d block by hand makes the parser treat the file as mixed and fail closed, pausing consolidation until it’s repaired — so for new facts prefer octos memory remember.
Automatic Memory Refresh (capture + consolidation)
Octos ships an automatic memory pipeline that reads durable facts out of your conversations and consolidates them into MEMORY.md — so long-term memory grows without you hand-editing files. It is on by default.
Where it runs. The background sweep runs only inside the long-running process that owns the profile’s refresh lock — octos serve or octos gateway. Plain octos chat never runs background passes (it would contend the lock). The pipeline has three parts:
- Capture — during a turn, a lightweight
memory_notetool + capture policy let the agent jot candidate facts. - Extraction sweep — on a timer, idle sessions are scanned and durable facts are extracted (delta cursors mean each message is read at most once, so nothing is re-charged on later sweeps).
- Consolidation — extracted candidates are merged into
MEMORY.md(each entry gets a stable id like^m4k2abq), stale entries are archived, and the file is kept under a size cap.
Manual control — octos memory:
octos memory refresh # Run one extraction+consolidation pass now
octos memory status # Lock holder, staging backlog, daily budgets
octos memory remember "..." # Stage a fact locally (no LLM at write; consolidation applies it)
octos memory forget "..." # Free-text forget → confirm flow
octos memory forget --id ^m4k2abq # Hard-delete an exact MEMORY.md entry
refresh works even when the background sweep is disabled, but refuses while a running service holds the lock (stop it first, or let it sweep).
Configuration (all optional; sensible defaults apply) lives under memory.refresh in config.json:
{
"memory": {
"max_inject_tokens": 2500,
"refresh": {
"enabled": true,
"extract_model": null,
"consolidate_model": null,
"min_idle_minutes": 30,
"max_session_age_days": 10,
"max_sessions_per_pass": 2,
"max_extractions_per_day": 20,
"max_consolidations_per_day": 12,
"max_daily_tokens": 200000,
"consolidate_interval_minutes": 30,
"max_memory_file_tokens": 8000
}
}
}
enabledis tri-state: absent means ON (the product default). Setfalse— orOCTOS_MEMORY_REFRESH_ENABLED=0— to opt out entirely (no capture tool, no per-turn re-read, no sweep). A host-level opt-out is inherited by sub-profiles.extract_model/consolidate_modeldefault to the profile’s provider; point them at a cheap model to keep refresh costs low.- Daily budgets (
max_extractions_per_day,max_consolidations_per_day,max_daily_tokens) are per-profile and reset on local-date rollover; durable state lives inmemory/refresh_state.json.
Layer 3: Entity Bank (tool-driven)
The entity bank is a structured knowledge store at .octos/memory/bank/entities/. Each entity is a markdown file containing everything the agent knows about a specific topic.
How it works:
- Abstracts in prompt — The first non-heading line of each entity becomes a one-line abstract. All abstracts are injected into the system prompt, giving the agent a compact index of everything it knows.
- Full pages on demand — The agent uses the
recall_memorytool to load the full content of a specific entity when it needs more detail. - Agent-managed — The agent decides when to create and update entities using the
save_memorytool.
Memory tools:
save_memory— Create or update an entity page. The agent is instructed to firstrecall_memoryfor existing content, then merge new information before saving (no data loss).recall_memory— Load the full content of a named entity. If the entity doesn’t exist, returns a list of all available entities.
Availability: memory tools (
save_memory,recall_memory) are part of the full tool set sent to the model every turn — no activation step is needed. (Earlier versions deferred them behind anactivate_toolsmeta-tool; that scheme was removed in RFC-0.)
File Layout
.octos/
├── config.json # Configuration (versioned, auto-migrated)
├── cron.json # Cron job store
├── AGENTS.md # Agent instructions
├── SOUL.md # Personality
├── USER.md # User info
├── HEARTBEAT.md # Background tasks
├── sessions/ # Chat history (JSONL)
├── memory/ # Memory files
│ ├── MEMORY.md # Long-term memory (manual or write_file)
│ ├── 2025-02-10.md # Daily note (manual or write_file)
│ └── bank/
│ └── entities/ # Entity bank (managed by save/recall tools)
│ ├── yuechen.md # Entity: "who is the user"
│ └── octos.md # Entity: "what is this project"
├── skills/ # Custom skills
├── episodes.redb # Episodic memory DB (auto-populated)
└── history/
└── chat_history # Readline history
Built-in System Skills
Octos bundles 3 system skills at compile time:
| Skill | Description |
|---|---|
cron | Cron tool usage examples (always-on) |
skill-store | Skill installation and management |
skill-creator | Guide for creating custom skills |
Workspace skills in .octos/skills/ override built-in skills with the same name.
Bundled App Skills
Eight app skills ship as compiled binaries alongside Octos. They are automatically bootstrapped into .octos/skills/ on gateway startup – no installation required.
News Fetch
Tool: news_fetch | Always active: Yes
Fetches headlines and full article content from Google News RSS, Hacker News API, Yahoo News, Substack, and Medium. The agent synthesizes raw data into a formatted digest.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
categories | array | all | News categories to fetch |
language | "zh" / "en" | "zh" | Output language |
Categories: politics, world, business, technology, science, entertainment, health, sports
Configuration:
/config set news_digest.language en
/config set news_digest.hn_top_stories 50
/config set news_digest.max_deep_fetch_total 30
Deep Search
Tool: deep_search | Timeout: 600 seconds
Multi-round web research tool. Performs iterative searches, parallel page crawling, reference chasing, and generates structured reports saved to ./research/<query-slug>/.
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | (required) | Research topic or question |
depth | 1–3 | 2 | Research depth level |
max_results | 1–10 | 8 | Results per search round |
search_engine | string | auto | perplexity, duckduckgo, brave, you |
Depth levels:
- 1 (Quick): single search round, ~1 minute, up to 10 pages
- 2 (Standard): 3 search rounds + reference chasing, ~3 minutes, up to 30 pages
- 3 (Thorough): 5 search rounds + aggressive link chasing, ~5 minutes, up to 50 pages
Deep Crawl
Tool: deep_crawl | Requires: Chrome/Chromium in PATH
Recursively crawls a website using headless Chrome via CDP. Renders JavaScript, follows same-origin links via BFS, extracts clean text.
| Parameter | Type | Default | Description |
|---|---|---|---|
url | string | (required) | Starting URL |
max_depth | 1–10 | 3 | Maximum link-following depth |
max_pages | 1–200 | 50 | Maximum pages to crawl |
path_prefix | string | none | Only follow links under this path |
Output is saved to crawl-<hostname>/ with numbered markdown files.
Configuration:
/config set deep_crawl.page_settle_ms 5000
/config set deep_crawl.max_output_chars 100000
Send Email
Tool: send_email
Sends emails via SMTP or Feishu/Lark Mail API (auto-detected from available environment variables).
| Parameter | Type | Default | Description |
|---|---|---|---|
to | string | (required) | Recipient email address |
subject | string | (required) | Email subject |
body | string | (required) | Email body (plain text or HTML) |
html | boolean | false | Treat body as HTML |
attachments | array | none | File attachments (SMTP only) |
SMTP environment variables:
export SMTP_HOST="smtp.gmail.com"
export SMTP_PORT="465"
export SMTP_USERNAME="your-email@gmail.com"
export SMTP_PASSWORD="your-app-password"
export SMTP_FROM="your-email@gmail.com"
Weather
Tools: get_weather, get_forecast | API: Open-Meteo (free, no key required)
| Parameter | Type | Default | Description |
|---|---|---|---|
city | string | (required) | City name in English |
days | 1–16 | 7 | Forecast days (forecast only) |
Clock
Tool: get_time
Returns current date, time, day of week, and UTC offset for any IANA timezone.
| Parameter | Type | Default | Description |
|---|---|---|---|
timezone | string | server local | IANA timezone name (e.g., Asia/Shanghai, US/Eastern) |
Account Manager
Tool: manage_account
Manages sub-accounts under the current profile. Actions: list, create, update, delete, info, start, stop, restart.
Platform Skills (ASR/TTS)
Platform skills provide on-device voice transcription and synthesis. They require the OminiX backend running on Apple Silicon (M1/M2/M3/M4).
Voice Transcription
Tool: voice_transcribe
| Parameter | Type | Default | Description |
|---|---|---|---|
audio_path | string | (required) | Path to audio file (WAV, OGG, MP3, FLAC, M4A) |
language | string | "Chinese" | "Chinese", "English", "Japanese", "Korean", "Cantonese" |
Voice Synthesis
Tool: voice_synthesize
| Parameter | Type | Default | Description |
|---|---|---|---|
text | string | (required) | Text to synthesize |
output_path | string | auto | Output file path |
language | string | "chinese" | "chinese", "english", "japanese", "korean" |
speaker | string | "vivian" | Voice preset |
Available voices: vivian, serena, ryan, aiden, eric, dylan (EN/ZH), uncle_fu (ZH only), ono_anna (JA), sohee (KO)
Voice Cloning
Tool: voice_clone_synthesize
Synthesizes speech using a cloned voice from a 3–10 second reference audio sample.
| Parameter | Type | Default | Description |
|---|---|---|---|
text | string | (required) | Text to synthesize |
reference_audio | string | (required) | Path to reference audio |
language | string | "chinese" | Target language |
Podcast Generation
Tool: generate_podcast
Creates multi-speaker podcast audio from a script of {speaker, voice, text} objects.
Custom Skill Installation
Installing from GitHub
# Install all skills from a repo
octos skills install user/repo
# Install a specific skill
octos skills install user/repo/skill-name
# Install from a specific branch
octos skills install user/repo --branch develop
# Force overwrite existing
octos skills install user/repo --force
# Install into a specific profile
octos skills --profile my-bot install user/repo
The installer tries to download a pre-built binary from the skill registry (SHA-256 verified), falls back to cargo build --release if a Cargo.toml is present, or runs npm install if a package.json is present.
Managing Skills
octos skills list # List installed skills
octos skills info skill-name # Show detailed info
octos skills update skill-name # Update a specific skill
octos skills update all # Update all skills
octos skills remove skill-name # Remove a skill
octos skills search "web scraping" # Search the online registry
Skill Resolution Order
Profile gateways load skills from these directories (highest priority first):
~/.octos/profiles/<profile>/data/skills/(profile-scoped custom skills)<octos_home>/bundled-app-skills/(bundled app skills)<octos_home>/platform-skills/(admin-loaded platform skills)
Standalone project runs can also load <project>/.octos/plugins/ and
<project>/.octos/skills/. The old HOME-rooted global directories are
migration-only and are no longer part of the normal scan path.
Skill Authoring
A custom skill lives in .octos/skills/<name>/ and contains:
.octos/skills/my-skill/
├── SKILL.md # Required: instructions + frontmatter
├── manifest.json # Required for tool skills: tool definitions
├── main # Compiled binary (or script)
└── .source # Auto-generated: tracks install source
SKILL.md Format
---
name: my-skill
version: 1.0.0
author: Your Name
description: A brief description of what this skill does
always: false
requires_bins: curl,jq
requires_env: MY_API_KEY
---
# My Skill Instructions
Instructions for the agent on how and when to use this skill.
## When to Use
- Use this skill when the user asks about...
## Tool Usage
The `my_tool` tool accepts:
- `query` (required): The search query
- `limit` (optional): Maximum results (default: 10)
Frontmatter fields:
| Field | Description |
|---|---|
name | Skill identifier (must match directory name) |
version | Semantic version |
author | Skill author |
description | Short description |
always | If true, included in every system prompt. If false, available on demand. |
requires_bins | Comma-separated binaries checked via which. Skill is unavailable if any are missing. |
requires_env | Comma-separated environment variables. Skill is unavailable if any are unset. |
manifest.json Format
For skills that provide executable tools:
{
"name": "my-skill",
"version": "1.0.0",
"description": "My custom skill",
"tools": [
{
"name": "my_tool",
"description": "Does something useful",
"timeout_secs": 60,
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query"
},
"limit": {
"type": "integer",
"description": "Maximum results",
"default": 10
}
},
"required": ["query"]
}
}
],
"entrypoint": "main"
}
The tool binary receives JSON input on stdin and must output JSON on stdout:
// Input (stdin)
{"query": "test", "limit": 5}
// Output (stdout)
{"output": "Results here...", "success": true}