Memory
Memories: named notes any agent of their scope can attach.
company = noclick.Memory.from_name("company", create_if_missing=True)
company.save("refunds", "Within 30 days, to the original card.", description="Our refund rules")
support = noclick.Agent.from_name("support", create_if_missing=True, instructions="...",
memories=[company]) # it reads company
closer = noclick.Agent.from_name("closer", create_if_missing=True, instructions="...",
memories=[company.writable()]) # it reads and writes itEvery agent also has a memory of its own, agent.memory, which it always
reads and writes. A memory attached to it is read-only unless attached with
writable(); every turn starts with the names and descriptions of every
entry it can read, its own memory's first.
class MemoryNamed notes any agent of its scope can attach: the account's (every user's
agents may read them) or one user's. Its entries are what agent.memory
holds: a name, a one-line description, Markdown content and a version.
A memory of the account keeps two layers, as an account agent's own memory does: its own entries, and each user's, which only that user's conversations see. A user's memory keeps one, its user's.
- Like every live object, it also has hydrate(), refresh() and raw.
| id | str | |
| name | str | None | Its name, unique in its scope ( |
| description | str | None | One line saying what it holds. |
| agent_id | str | None | The agent whose own memory this is ( |
| attached_to | list[dict[str, Any]] | The agents that attach it besides: each one's |
| entry_count | int | None | How many entries it holds, in all its layers. |
| user_id | str | None | |
| created_at | Any | |
| updated_at | Any |
createclassmethodasync
noclick.Memory.create(name, *, description=None, user=..., client=None) -> MemoryCreate an empty memory called name (1-64 letters, digits and
. _ -), unique to its user, or to the account outside as_user (a
taken name raises noclick.Conflict with existing_id).
NoneWho the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
None)The new, empty memory.
company = noclick.Memory.create("company", description="What every agent should know")
company.save("tone", "Warm and brief.", description="How we write")from_nameclassmethod
noclick.Memory.from_name(
name, *, create_if_missing=False, description=None, user=..., client=None
) -> MemoryA lazy reference to the memory called name. Acting for a user,
that user's own memory is found first, then the account's. With
create_if_missing=True the current (or given) user's is created on
first use.
FalseNoneWho the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
None)A memory that loads (or is created) the first time it's used. Nothing is sent yet.
company = noclick.Memory.from_name("company", create_if_missing=True)
support = noclick.Agent.from_name("support", create_if_missing=True,
instructions="Answer billing questions.", memories=[company])from_idclassmethod
noclick.Memory.from_id(memory_id, *, client=None, user=...) -> MemoryA lazy reference to a memory by id, such as an agent's own (agent.memory_id).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
None)Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
A memory that loads the first time you read a field. Nothing is sent yet.
support = noclick.Agent.from_name("support")
own = noclick.Memory.from_id(support.memory_id)
print(own.entry_count)getclassmethodasync
noclick.Memory.get(memory_id, *, user=..., client=None) -> MemoryLoad a memory by id now; an unknown id raises noclick.NotFound.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
None)The memory, loaded: who attaches it and how many entries it holds.
company = noclick.Memory.get("5d1c9a3e-7b2f-4e60-8a19-3c4d6e8f0b21")
print(company.name, company.entry_count, company.attached_to)listclassmethodasync
noclick.Memory.list(
*, limit=None, user_filter=None, user=..., client=None
) -> list[Memory]The current user's named memories and the account's (or those user_filter covers).
An agent's own memory isn't listed: it's agent.memory.
Return at most this many.
None)Which users a read covers: noclick.ALL_USERS, noclick.NO_USER, a User, or your id for one. It filters without acting as that user.
None)Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
None)Every matching memory, newest first, fetched page by page.
for memory in noclick.Memory.list():
print(memory.name, memory.entry_count, memory.user_id) # user_id is None for the account'slist_pageclassmethodasync
noclick.Memory.list_page(
*, cursor=None, limit=None, user_filter=None, user=..., client=None
) -> PageOne page of named memories; pass next_cursor back as cursor.
The next_cursor of the page before; omit it for the first page.
None)Return at most this many.
None)Which users a read covers: noclick.ALL_USERS, noclick.NO_USER, a User, or your id for one. It filters without acting as that user.
None)Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
None)A page whose data holds the memories and whose next_cursor is None on the last page.
page = noclick.Memory.list_page(limit=50)
for memory in page.data:
print(memory.name)writable
memory.writable() -> MemoryLinkThis memory, for an agent's memories=, with writes: the agent may save to it and forget from it,
not only read it. Only a call acting for the memory's own scope can attach it so.
What memories= takes for a memory the agent writes.
team = noclick.Memory.from_name("team-notes", create_if_missing=True)
noclick.Agent.from_name("scribe", create_if_missing=True, instructions="Keep the team's notes.",
memories=[team.writable()])updateasync
memory.update(*, name=None, description=None) -> MemoryRename it, or change its description. An agent's own memory takes no name.
NoneNoneThis memory, as it is now.
noclick.Memory.from_name("company").update(name="handbook")deleteasync
memory.delete() -> TrashItemDelete the memory and every entry in it: it goes to the trash, restorable for 30 days. While an agent
attaches it (attached_to), this raises noclick.Conflict: take it out of the agents' memories
first. An agent's own memory goes only with its agent (noclick.Conflict).
noclick.Memory.from_name("old-notes").delete()entriesasync
memory.entries(*, user=...) -> list[MemoryEntry]The entries of one layer: the account's outside as_user, else the user's.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
Each entry's name, description, version and when it last changed, by name; content is None
here, so read an entry for its body.
for entry in noclick.Memory.from_name("company").entries():
print(entry.name, entry.description)searchasync
memory.search(query, *, limit=None, user=...) -> list[MemoryEntry]Search the memory the way an agent does: a user's entries and the account's. An entry matches when
its name, description or content holds any of the query's words (refund finds refunds), or its
name or description holds the query.
Return at most this many.
None)Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The best matches first (10 unless limit says otherwise, at most 100), with their content.
for entry in noclick.Memory.from_name("company").search("refund policy"):
print(entry.name, entry.content)readasync
memory.read(name, *, user=...) -> MemoryEntryOne entry in full; a name with no entry raises noclick.NotFound.
Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The entry with its content and the version to pass back when you change it.
tone = noclick.Memory.from_name("company").read("tone")
print(tone.version, tone.content)saveasync
memory.save(name, content, *, description=None, version=None, user=...) -> MemoryEntryWrite an entry, creating it if the name is new. description is the
line every agent attaching the memory sees each turn (required for a new
entry, kept when you leave it out). With version, the save only lands
if the entry is still at that version, else noclick.Conflict.
NoneNoneWho the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
The entry as saved, with its new version.
company = noclick.Memory.from_name("company", create_if_missing=True)
company.save("tone", "Warm and brief, no jargon.", description="How we write")forgetasync
memory.forget(name, *, version=None, user=...) -> NoneForget an entry. With version, only if it is still at that version (else noclick.Conflict).
NoneWho the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).
None once it's gone; a name with no entry raises noclick.NotFound.
noclick.Memory.from_name("company").forget("old-pricing")MemoryLink
class MemoryLinkA memory attached with writes (memory.writable()): the agent may change it as well as read it.
| memory | Any | |
| writes | bool |