---
title: "Skills and memory"
description: "Skill, a directory of files the agent has, and Memory, text the agent loads into its prompt from storage."
source: "Guardian Agent SDK"
---
Skills and memory are files an agent reads. Their files are stored on the proxy, and the definition names them by content ID.

## Skill

{/* generated api guardian_agent.Skill */}

A skill the agent has: a directory of files.

Make one with `Guardian.skill`, which uploads the files to the proxy
and returns the skill with their CID.

**Attributes:**

- **name** (`str`) – The skill's name.
- **cid** (`str`) – The iroh collection CID of the skill's files, the same CID Viper
  gives a coding agent's skill, so editing any file gives the agent
  a new definition. The SDK never computes it: the proxy does, and
  refuses a definition naming files it doesn't hold.

{/* end generated */}

## Memory

{/* generated api guardian_agent.Memory */}

Text the agent loads into its prompt from storage.

Build one with `instructions` for memory the agent can't change,
which is configuration and recorded by its files' CID, or `learned`
for memory it writes as it works, recorded by where it lives and whose it
is, never by its contents.

**Attributes:**

- **path** (`str`) – Where the agent reads it, as the agent sees it.
- **backend** (`str`) – The kind of storage it's in, as the framework names it
  (`"filesystem"`, `"store"`, `"state"`).
- **writable** (`bool`) – Whether the agent can change it.
- **cid** (`str | None`) – For `instructions`: the iroh collection CID of its files.
- **scope** (`Literal['shared', 'namespace', 'thread'] | None`) – For `learned`: `"shared"` (one memory for every user
  and thread), `"namespace"` (one per namespace, such as per
  user) or `"thread"` (one per thread, held in its state).
- **namespace_hash** (`str | None`) – For a `"namespace"` scope: `sha256:<hex>` of the
  code that chooses the namespace.

**Functions:**

- [**instructions**](#memoryinstructions) – Memory the agent reads but can't change, such as an `AGENTS.md`.
- [**learned**](#memorylearned) – Memory the agent writes as it works.

### `Memory.instructions`

```python
instructions(path: str, *, backend: str, cid: str) -> Memory
```

Memory the agent reads but can't change, such as an `AGENTS.md`.

`Guardian.instructions` uploads its files and calls this; pass a
`cid` yourself only for files already stored on the proxy.

**Parameters:**

- **path** (`str`) – Where the agent reads it, as the agent sees it.
- **backend** (`str`) – The kind of storage it's in.
- **cid** (`str`) – The iroh collection CID of its files.

### `Memory.learned`

```python
learned(path: str, *, backend: str, namespace: Callable[..., Any] | None = None, thread: bool = False) -> Memory
```

Memory the agent writes as it works.

**Parameters:**

- **path** (`str`) – Where the agent reads it.
- **backend** (`str`) – The kind of storage it's in.
- **namespace** (`Callable[..., Any] | None`) – The function choosing whose memory loads, if each user
  (say) has their own; its source is fingerprinted. Without one,
  or `thread`, the memory is shared. It must hold no values its source
  doesn't show, so a closure, a function with default
  arguments, or one with attributes set on it is refused.
  Globals it reads are seen by name only, so keep what decides
  the namespace in its body.
- **thread** (`bool`) – Whether each thread has its own memory, held in that
  thread's state, so none is carried from one thread to the
  next. It names whose memory it is, not where it's kept: that
  is `backend`. Not with `namespace`.

**Raises:**

- `TypeError` – `namespace` isn't a plain function, or holds values
  its source doesn't show (a partial, method, callable object,
  closure, default argument or attribute), or is given with
  `thread`.
- `ValueError` – `namespace` is a lambda, or its source can't be read
  (a function defined in a REPL, say), so a change to it would
  go unseen.

{/* end generated */}