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.

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.mdwraps the current persistent-memory snapshot.prompts/skills.mdadvertises assigned skills and must retain the framework's{skills}placeholder.prompts/compaction.mdtells 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_savewrites a daily entry or a long-term index/topic entry.memory_readacceptslongterm,today,yesterday,yyyy-MM-dd, or a topic slug.memory_forgetremoves matching lines from the long-term index and topic files.memory_searchsearches indexed conversation chunks and caps requested results at 50.memory_getretrieves 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:
- It advertises available names and descriptions, ordered by ordinal skill name, in the starting instructions.
load_skillaccepts an exact skill name and returns the completeSKILL.mdplus authoritative<available_resources>and<available_scripts>lists.read_skill_resourceaccepts the exact skill and relative resource names and returns that resource's UTF-8 text.run_skill_scriptaccepts 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 ofreferences/orassets/. - 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.