Writing To Memory logo

Writing To Memory

Organization
friday-platform
writing-to-memory

How to read and write Friday memory stores correctly: store selection, terse entry format, large-content artifact pattern, and what's auto-injected into the system prompt.

Overview

Publisherfriday-platform
Repositoryfriday-studio
Skill namewriting-to-memory
Stars
102
Forks
5
Bundled files
Instructions only
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by friday-platform on GitHub. Read the source before you install it.

Installation

Install the Writing To Memory AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/friday-platform/friday-studio/tree/main/packages/system/skills/writing-to-memory
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/friday-platform/friday-studio.git /tmp/friday-studio
mkdir -p .claude/skills
cp -r /tmp/friday-studio/packages/system/skills/writing-to-memory .claude/skills/writing-to-memory
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Writing To Memory in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Writing To Memory on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Writing To Memory is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Writing to Memory

Memory tool surface

Three verbs, one canonical name each across every caller (chat, FSM type: llm actions, type: atlas / type: user agents):

VerbToolNotes
Save an entrysave_memory_entry({ memoryName, text, metadata? })Appends; persists across sessions.
Read entrieslist_memory_entries({ memoryName, query?, since?, until?, metadata?, limit?, cursor? })Newest-first by default; truncate caps each entry's text at 500 chars.
Remove an entrydelete_memory_entry({ memoryName, entryId })Idempotent.

Same verb-first pattern for artifacts: create_artifact / get_artifact / parse_artifact / display_artifact.

Repair note: these tools were renamed from memory_save / memory_read / memory_remove (and artifacts_create / artifacts_get) in 2026-05. Installed Python agents that hard-coded the old names need a grep-and-replace — see @friday/repairing-workspaces-agents for the recipe.

Narrative is the only memory strategy

Friday memory is markdown narrative stores — append-only, auto-injected into agent prompts, queryable via list_memory_entries. There is no separate retrieval, dedup, or kv backend; if a user asks for "vector search over my notes" or "KV-style lookup", surface the limitation instead.

For everything narrative covers — preferences, standing instructions, durable facts, working notes, anything you want the agent to remember and reference next turn — declare a narrative store and you're done.

How memory is injected

At the start of every turn, the 20 most recent entries from each narrative store are injected into your system prompt as:

xml
<memory workspace="zesty_mushroom" store="preferences">
- Always archive newsletters from substack.com (2026-04-15)
- GitHub CI failures → keep unread
</memory>

Each block is labeled with workspace and store so you know exactly what you're reading. You do not need to call list_memory_entries to access this content — it's already there.

For explicit lookup, time-filtering, or reading beyond the 20-entry window:

list_memory_entries(memoryName="preferences", since="2026-01-01T00:00:00Z", limit=50)

To remove a stale entry: delete_memory_entry(memoryName, entryId).

Store selection

Check <memory_stores> in your workspace context for what's available. Pick the store that best matches the content — do not default to notes without considering the alternatives.

StoreTypeDefault lifecycleUse for
notesshort_termephemeral, session-bound — auto-deleted at session-completeIn-progress state, working context, things that don't need to persist
memorylong_termdurableFacts the agent should remember next turn / next session — what was built, decided, observed
preferenceslong_termdurableUser standing instructions, formatting rules, explicit preferences
customanyfollows type: default; override with ttl:Domain-specific; declared via upsert_memory_own

type: short_term is genuinely short-term: notes you write during a session don't survive past it unless you explicitly write the same content to a long_term store. type: long_term persists across sessions until explicitly removed via delete_memory_entry. Override per-store via memory.own[].ttl: <duration> in workspace.yml when you want a specific TTL different from the type default.

If the right store doesn't exist yet, call upsert_memory_own to declare it before writing. A store must exist in workspace.yml (or the active draft) before save_memory_entry will accept it.

Entry format

Write terse entries. Memory is injected on every turn — verbose entries waste tokens and dilute signal.

Rules:

  • One fact per entry. Never bundle unrelated things.
  • Keep entries under ~100 chars. Longer content belongs in an artifact (see below).
  • Write the fact directly — no preamble ("The user told me that...", "I noticed that...").
  • Suffix time-sensitive facts with (YYYY-MM-DD).
  • Never duplicate. Call list_memory_entries first if unsure whether a fact is already stored; update via delete_memory_entry + save_memory_entry rather than appending a conflicting entry.

✅ Good:

Always archive newsletters from substack.com
GitHub CI failures → keep unread
Q1 email analysis → art_abc123 (2026-04-29)
Prefers CSV over JSON for data exports

❌ Avoid:

The user mentioned that they would like newsletters from substack.com to be archived automatically in the future because they find them distracting

Large content → artifact reference pattern

Anything over ~500 chars (result sets, reports, structured data, analyses) must not go directly into memory — it will bloat every future turn's system prompt.

Step 1 — register the content as an artifact in one call.

If you're in the workspace-chat assistant (the main user-facing surface), use save_artifact for text content:

save_artifact(
  filename="q1-analysis.md",
  content="<full content>",
  title="Q1 email analysis",
  summary="..."
)
→ { success: true, id: "art_abc123", type: "file", summary: "..." }

If you're in a user agent (Python/TS SDK) calling the MCP server, use the MCP create_artifact tool, which accepts the inline data object:

create_artifact(
  data={type:"file", content:"<full content>", originalName:"q1-analysis.md"},
  title="Q1 email analysis",
  summary="..."
)
→ { id: "art_abc123", type: "file", summary: "..." }

Either way the storage layer hashes the bytes (SHA-256), sniffs the mime type from the magic bytes if you don't pass mimeType, and writes to the JetStream Object Store named by hash — identical bytes dedup automatically. No filesystem hop, no write_file → create_artifact(path) two-step.

For binary content (e.g. images returned by a tool), use the MCP create_artifact with contentEncoding: "base64" (user agent), or use run_code to write the bytes to scratch and then create_artifact({path}) (workspace-chat — save_artifact rejects binary-MIME filenames):

# MCP / user-agent path:
create_artifact(
  data={type:"file", content:"<base64>", contentEncoding:"base64", mimeType:"image/png", originalName:"chart.png"},
  ...
)

Step 2 — save a terse reference to memory:

save_memory_entry(memoryName="memory", text="Q1 email analysis → art_abc123 (2026-04-29)")

Step 3 — retrieve later: When you see → art_abc123 in an injected memory entry, call get_artifact(id="art_abc123") to load the full content on demand.

This keeps the injection window lean while making large results durable across sessions.

Memory references promote artifacts to durable

FSM-emitted artifacts default to ephemeral with a grace window (default 24h after job completion); a background sweeper deletes them once the window closes. An artifact stays durable iff something references it before the sweep: a save_memory_entry text containing the artifact ID, a display_artifact call, or an aiSummary.keyDetails[].url pointing at it.

So step 2 above isn't just bookkeeping — it's the durability decision. If you don't save_memory_entry a reference (or surface the artifact some other way), it'll be gone in 24h.

If you want something gone — intermediate working state — write the artifact and never reference it. The sweeper handles cleanup. Don't try to manage lifetimes manually.

Recent artifacts auto-inject into prompts

Per-session artifact context auto-injects into LLM prompts as <retrieved_content provenance="artifact:..." origin="..." fetched_at="..."> blocks at action start (chat: per-chat-session; FSM: per-FSM-session). The block carries each artifact's summary, not its content — the LLM sees a 1-line digest plus the artifactId. If a digest looks relevant, call parse_artifact(artifactId) to load the content.

Practical implication for summary field: when you create_artifact, write a useful 1-2 sentence summary. The LLM's later turns rely on it to decide whether to expand the artifact.

Availability

save_memory_entry, list_memory_entries, delete_memory_entry, the state_* tools, the artifacts_* tools, and webfetch are wired into every execution context with workspaceId auto-injected from the runtime scope. You never pass workspaceId — the runtime overrides it (defense in depth: a foreign workspaceId in args is replaced before the tool runs).

Authoring rule for FSM type: llm actions: do NOT redeclare these in the action's tools: array. They are auto-injected on top of any allowlist you provide. Listing save_memory_entry or create_artifact in tools: is harmless but adds noise. To genuinely lock an action down to "memory + artifacts only," declare tools: [] (empty) — the auto-injected built-ins still work, the workspace MCP catalog gets narrowed away.

ContextTool surfaceCall shape
Workspace-chat / conversationdirect tool callsave_memory_entry({ memoryName, text })
type: "llm" workspace agentsLLM tool callsave_memory_entry({ memoryName, text })
type: "atlas" SDK agentstools.execute(...){ memoryName, text }
FSM LLM action stepsLLM tool callsave_memory_entry({ memoryName, text })
type: "user" Python/TS agentsctx.tools.call(name, args)ctx.tools.call("save_memory_entry", { memoryName, text })

Stores must be declared in workspace.yml under memory.own (or reachable via an rw mount). Undeclared stores are rejected with the list of declared ones.

User-agent footgun: ctx.tools.call(...) raises ToolCallError on validation failure (e.g. store not declared, narrative-only constraint). Never swallow with except Exception — surface the error via err() or fall through to your own retry. The autopilot family of bugs all started with a swallowed ToolCallError masking a silent write loss.

Frequently asked questions

What does the Writing To Memory AI skill do?

How to read and write Friday memory stores correctly: store selection, terse entry format, large-content artifact pattern, and what's auto-injected into the system prompt.

Why use Writing To Memory on TypingMind?

Because you install it once and use it with any model. Writing To Memory is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Writing To Memory in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/friday-platform/friday-studio/tree/main/packages/system/skills/writing-to-memory. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Writing To Memory?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Writing To Memory?

As many as you like. As long as a model supports skills, you can use Writing To Memory with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Writing To Memory AI skill free?

It is published on GitHub by friday-platform. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇