Table of Contents

Memory and Skills

Last updated:

Memory and skills give agents durable capability without putting every possible instruction into the base system prompt. Memory supplies user-specific context. Skills supply reusable knowledge, reference files, assets, and optional script-backed procedures.

Installed Skills showing the built-in Oscova Agents guide and import action.

Note

Progressive disclosure means loading detailed guidance only when the agent needs it instead of putting everything into the starting prompt.

Note

Skill means a folder with a SKILL.md file that declares a name and description, plus optional resources or scripts the model can load on demand.

Runtime boundaries

CrewService assembles active-agent context in this order: environment, ordinary-tool exposure, the agent's standing instruction, exposed agent tools, assigned skills, memory, Library, task list, and request-specific providers. Providers that are not applicable are omitted.

The standing instruction, memory prompt, skills prompt, and compaction prompt have separate responsibilities:

  • The agent's system instruction is rendered with user, time, agent, and shared-agent personal-context variables.
  • prompts/memory-system.md wraps the current persistent-memory snapshot.
  • prompts/skills.md advertises assigned skills and must retain the framework's {skills} placeholder.
  • prompts/compaction.md tells the chat reducer how to summarize older conversation messages.

Compaction does not replace persistent memory or skill disclosure. It preserves system messages and reduces non-system conversation history only when the configured history budget is crossed.

Memory and skills are added only when the definition is the active requested agent. A definition invoked through agent-as-tool keeps its instruction, ordinary tools, workspace policy, model, and compaction setting, but it does not receive memory or skills during that delegated build. Running the same definition directly makes it active and restores its configured memory and skills.

Persistent-memory contract

IAgentMemoryService owns user-scoped file memory:

Memory kind Public operations Runtime use
Long-term index Read, append, replace, and forget matching text Boot-loaded first and available through memory_save, memory_read, and memory_forget.
Long-term topic Read or append by lowercase kebab-case slug Loaded on demand through the memory tools.
Daily log Read relative or explicit dates, append for the user's local date, and list dates Today's and yesterday's logs are boot-loaded after the long-term index.
Conversation memory Search semantic chunks or retrieve one thread Host-owned memory_search and memory_get. This is not part of IAgentMemoryService.

AgentMemoryService is the framework's file-backed implementation. Callers provide per-user root resolution, the text-size limit, the user's current local date, and the backup service.

MemoryContextProvider reads the long-term index, today's daily log, and yesterday's daily log in that order. It creates an <agent_memory> block and renders SystemPrompt. If the prompt omits {{ agent_memory }}, the block is appended automatically.

The provider's default content budget is 2,000 tokens. Long-term memory gets first use of that budget. Today receives the remainder, then yesterday. An empty long-term index is represented explicitly as empty memory, so the provider still contributes its instructions and host-supplied memory tools even when no files contain entries.

The host memory tools expose these observable contracts:

  • memory_save writes a daily entry or a long-term index/topic entry.
  • memory_read accepts longterm, today, yesterday, yyyy-MM-dd, or a topic slug.
  • memory_forget removes matching lines from the long-term index and topic files.
  • memory_search searches indexed conversation chunks and caps requested results at 50.
  • memory_get retrieves indexed chunks for one thread.

A confidential active agent still receives its existing persistent-memory context and read operations, but the host omits memory_save. The omission happens before direct exposure or tool search, so an allowed name, pin, or policy cannot restore the function for that run.

The search and thread tools operate across the current user's conversation-memory store. Their agentId argument remains for compatibility and for local-only policy resolution. It is not an ownership boundary between agents.

Skill disclosure

Skills are assigned to an agent by name. At runtime, CrewService builds Microsoft Agent Framework's AgentSkillsProvider from the user's skills directory, applies SkillFileDiscoveryOptions, then filters the source case-insensitively to the definition's assigned names.

The provider implements progressive disclosure in this order:

  1. It advertises available names and descriptions, ordered by ordinal skill name, in the starting instructions.
  2. load_skill accepts an exact skill name and returns the complete SKILL.md plus authoritative <available_resources> and <available_scripts> lists.
  3. read_skill_resource accepts the exact skill and relative resource names and returns that resource's UTF-8 text.
  4. run_skill_script accepts exact skill and script names plus an optional JSON array of string arguments.

Oscova disables approval for the two read-only tools, load_skill and read_skill_resource. run_skill_script remains approval-required. Its approval covers the whole script invocation. Commands inside the script are not approved separately. All three functions are present when the provider has at least one assigned skill. A skill with no scripts advertises an empty scripts list rather than making up a script name.

The user execution mode controls both ordinary shell commands and file-skill scripts. Host is the default and uses Oscova's operating-system account permissions. Container Sandboxed runs them in Docker. Disabled exposes no script extensions or shell execution. A run snapshots this choice, and a later setting change makes subsequent shell launches in that run fail instead of switching targets.

Blank or unknown skill/resource/script names return model-readable Error: results. Resource-read failures and script failures are logged and propagate unless detailed script errors were deliberately enabled. Oscova leaves detailed skill errors disabled. Cancellation tokens flow through loads, reads, and script execution.

The framework builder caches the resolved skill list for the life of the built provider and deduplicates names with first occurrence winning. Import and settings flows invalidate cached agents so a later build sees filesystem changes.

File discovery and validation

SkillDiscoverer is the app's settings-time and import-time metadata authority. It searches the skills root and two child levels for SKILL.md, then requires:

  • YAML frontmatter delimited by ---.
  • A lowercase letter/digit/hyphen name no longer than 64 characters.
  • A description no longer than 1,024 characters.
  • A name that exactly matches the parent directory.

Candidate directories are sorted case-insensitively before parsing. Duplicate names therefore keep the first alphabetical directory, and the returned list is ordered by name.

Runtime file discovery uses the framework source with Oscova's narrower filters:

  • Resources: .md, .json, .yaml, .yml, .csv, .xml, and .txt, only as direct children of references/ or assets/.
  • Scripts: only direct children of scripts/. Disabled mode exposes no script extensions. Enabled modes use the framework defaults .py, .js, .sh, .ps1, .cs, and .csx.
  • Search depth: two, enough for the skill root and one support-directory level without exposing an arbitrary deep tree.

The file source normalizes relative paths and skips files that escape the skill directory, traverse through symlinks/reparse points, use disallowed extensions, or fail the configured directory filters. The configured skills root is trusted. Skill bodies, names, and descriptions are still inserted into model context as supplied. Treat imported skills as instruction-bearing code, and never enable script execution for an untrusted package.

Import and agent-authored writes

The framework-owned ISkillImportService contract and SkillImportService implementation accept one raw .md file or one .zip package beneath a caller-selected per-user skills root. Uploads are limited to 10 MB and expanded zip content to 30 MB. Archives are extracted through a containment-checked plan and must contain exactly one skill, either at the archive root or in one wrapper directory.

Import stages content beside the selected skills root, rejects path-shaped skill names, unsupported resource extensions, reserved Oscova provenance from ordinary imports, invalid metadata, and installed-name conflicts. SkillImportResult reports neutral compatibility facts for extra top-level paths and recognized frontmatter such as allowed-tools, user-invocable, and disable-model-invocation. The Host maps those facts into application warning sentences without changing the agent's tool policy.

Agent-authored creation and update use the same import pipeline instead of raw filesystem tools. The approval-gated authoring path may stamp trusted Oscova provenance. Updates are limited to skills with that provenance. Registry-installed, user-imported, and manually authored skills are rejected.

Tip

Use memory for user-specific facts and decisions. Use skills for reusable procedures, reference material, and domain knowledge that should be assigned deliberately.

Host-visible behavior

The host exposes different views of these systems:

  • Agent settings show assigned skills and the memory enable switch.
  • Skills settings show installed packages, execution mode, import validation, and import warnings.
  • Prompt settings edit memory, skills, and compaction instructions independently.
  • Chat tool activity shows memory and skill function calls and their returned evidence.
  • Chat Memory browses indexed conversation chunks only. It is not a browser for long-term topics or daily-log files.

If no assigned skills resolve, the framework provider contributes neither skill instructions nor skill tools. Invalid filesystem skills are skipped with logs during discovery, while explicit imports fail with a validation response. Memory search failures return a short host-safe message. Cancellation still propagates.