Custom Skills for Skill Memory
Define how your agent remembers by writing SKILL.md files
Every skill in a learning space has a SKILL.md that tells the learner how to organize information. By writing different SKILL.md files, you define different memory algorithms — each with its own rules for what to capture, how to name files, and how to structure entries.
How It Works
When a session completes, Acontext's learning pipeline:
- Reads each skill's
SKILL.mdto understand its purpose and rules - Decides which skills are relevant to the session outcome
- Creates or updates files following the instructions you wrote
This means you control the memory format. The learner is just the executor.
Example Skills
social-contacts
One file per person — captures who the user knows, relationship context, and preferences for interacting with them.
project-runbooks
One file per project — captures deployment steps, architecture decisions, and recurring issues.
api-error-patterns
Accumulated patterns organized by error category — captures what went wrong and how to fix it.
Walkthrough: Using social-contacts
Create the SKILL.md file
Create a file called SKILL.md with the following content:
---
name: "social-contacts"
description: "Track people the user interacts with — one file per person"
---
# Social Contacts
Maintain a file for each person the user mentions or interacts with.
## File Structure
One file per person, named [first-last].md (lowercase, hyphenated).
Each file has: # [Full Name], ## Basics (Relationship, Role, Company), ## Notes.
## Guidelines
- One person per file — do not combine people
- Only record information explicitly mentioned by the user
- Update existing entries when corrections are provided
- Keep entries factual and conciseZip and upload the skill
import os, zipfile, io
from acontext import AcontextClient, FileUpload
client = AcontextClient(api_key=os.getenv("ACONTEXT_API_KEY"))
# Read the SKILL.md you created
with open("SKILL.md", "r") as f:
skill_md = f.read()
buf = io.BytesIO()
with zipfile.ZipFile(buf, "w") as zf:
zf.writestr("SKILL.md", skill_md)
buf.seek(0)
skill = client.skills.create(
file=FileUpload(filename="social-contacts.zip", content=buf.read()),
)
print(f"Created skill: {skill.name} ({skill.id})")import { AcontextClient, FileUpload } from '@acontext/acontext';
import * as fs from 'fs';
import JSZip from 'jszip';
const client = new AcontextClient({
apiKey: process.env.ACONTEXT_API_KEY,
});
const skillMd = fs.readFileSync("SKILL.md", "utf-8");
const zip = new JSZip();
zip.file("SKILL.md", skillMd);
const zipBuffer = await zip.generateAsync({ type: "nodebuffer" });
const skill = await client.skills.create({
file: new FileUpload({ filename: "social-contacts.zip", content: zipBuffer }),
});
console.log(`Created skill: ${skill.name} (${skill.id})`);Add the skill to a learning space
space = client.learning_spaces.create()
client.learning_spaces.include_skill(space.id, skill_id=skill.id)
skills = client.learning_spaces.list_skills(space.id)
for s in skills:
print(f" {s.name}: {s.description}")const space = await client.learningSpaces.create();
await client.learningSpaces.includeSkill({ spaceId: space.id, skillId: skill.id });
const skills = await client.learningSpaces.listSkills(space.id);
for (const s of skills) {
console.log(` ${s.name}: ${s.description}`);
}Run a session with mock messages
session = client.sessions.create()
client.learning_spaces.learn(space.id, session_id=session.id)
messages = [
{"role": "user", "content": "Set up a meeting with Alice Chen — she's our new product manager at Acme Corp. She prefers morning slots."},
{"role": "assistant", "content": "I've scheduled a meeting with Alice Chen for tomorrow at 10 AM."},
{"role": "user", "content": "Also remind me that Bob Martinez from the DevOps team helped us fix the staging deploy issue last week."},
{"role": "assistant", "content": "Noted — Bob Martinez from DevOps helped resolve the staging deployment issue."},
]
for msg in messages:
client.sessions.store_message(session.id, blob=msg)const session = await client.sessions.create();
await client.learningSpaces.learn({ spaceId: space.id, sessionId: session.id });
const messages = [
{ role: "user", content: "Set up a meeting with Alice Chen — she's our new product manager at Acme Corp. She prefers morning slots." },
{ role: "assistant", content: "I've scheduled a meeting with Alice Chen for tomorrow at 10 AM." },
{ role: "user", content: "Also remind me that Bob Martinez from the DevOps team helped us fix the staging deploy issue last week." },
{ role: "assistant", content: "Noted — Bob Martinez from DevOps helped resolve the staging deployment issue." },
];
for (const msg of messages) {
await client.sessions.storeMessage(session.id, msg);
}Learning is asynchronous. After the session's tasks complete, the learner reads your SKILL.md and creates files like alice-chen.md and bob-martinez.md following your rules.
Inspect what the learner created
client.learning_spaces.wait_for_learning(space.id, session_id=session.id)
skills = client.learning_spaces.list_skills(space.id)
for s in skills:
if s.name == "social-contacts":
for f in s.file_index:
if f.path == "SKILL.md":
continue
print(f"\n--- {f.path} ---")
content = client.skills.get_file(skill_id=s.id, file_path=f.path)
print(content.content.raw)await client.learningSpaces.waitForLearning({ spaceId: space.id, sessionId: session.id });
const updatedSkills = await client.learningSpaces.listSkills(space.id);
for (const s of updatedSkills) {
if (s.name === "social-contacts") {
for (const f of s.fileIndex) {
if (f.path === "SKILL.md") continue;
console.log(`\n--- ${f.path} ---`);
const content = await client.skills.getFile({ skillId: s.id, filePath: f.path });
console.log(content.content?.raw);
}
}
}Expected output — files created by the learner following your SKILL.md rules:
# Alice Chen
## Basics
- Relationship: colleague
- Role: Product Manager
- Company: Acme Corp
## Notes
- Prefers morning meeting slots# Bob Martinez
## Basics
- Relationship: colleague
- Role: DevOps team
## Notes
- Helped resolve a staging deployment issueFull Code
Next Steps
Last updated on