Loading the notebook…
Loading the notebook…
Notebooks · Provider API features · 63
Every path is confined to root_dir (default .shipit_workspace/memories); paths that escape the sandbox are rejected. This notebook drives the tool directly to demonstrate each command offline, then attaches it to an…
Its imports and arguments are checked against shipit-agent 3.0. The outputs were saved when it was written, for an earlier release.
from pathlib import Path
import sys
ROOT = (
Path.cwd().resolve().parent
if Path.cwd().name == "notebooks"
else Path.cwd().resolve()
)
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))The tool's run(context, **kwargs) takes a ToolContext (which requires a prompt)
and the command arguments. We point root_dir at a temp directory so the demo is
self-contained. Construction does not create the directory — the first create
does.
import tempfile
from pathlib import Path
from shipit_agent import ClaudeMemoryTool
from shipit_agent.tools.base import ToolContext
tmp = Path(tempfile.mkdtemp(prefix="shipit_memories_"))
memory = ClaudeMemoryTool(root_dir=tmp)
ctx = ToolContext(prompt="memory demo")
print("memory tool name:", memory.name)
print("sandbox root:", memory.root_dir)create — write a memory fileout = memory.run(ctx, command="create", path="user_prefs.md",
file_text="# Preferences\n- Likes: dark mode\n- Stack: Python\n")
print(out.text)view — list the directory and show the file (with line numbers)print(memory.run(ctx, command="view", path=".").text)
print("---")
print(memory.run(ctx, command="view", path="user_prefs.md").text)str_replace — edit one unique occurrenceout = memory.run(ctx, command="str_replace", path="user_prefs.md",
old_str="dark mode", new_str="dark mode + high contrast")
print(out.text)
print(memory.run(ctx, command="view", path="user_prefs.md").text)insert — add a line after a given line number (0 = start of file)out = memory.run(ctx, command="insert", path="user_prefs.md",
insert_line=3, insert_text="- Timezone: UTC")
print(out.text)
print(memory.run(ctx, command="view", path="user_prefs.md").text)rename — move/rename a fileout = memory.run(ctx, command="rename", old_path="user_prefs.md", new_path="profile.md")
print(out.text)
print(memory.run(ctx, command="view", path=".").text)delete — remove a filePath confinement is enforced everywhere: a traversal like ../../etc/passwd is
rejected before touching the filesystem.
print(memory.run(ctx, command="delete", path="profile.md").text)
print(memory.run(ctx, command="view", path=".").text)
print("---")
print("escape attempt:", memory.run(ctx, command="view", path="../../../etc/passwd").text)Pass the tool to an Agent so the model can call it on its own — writing durable
notes in one session and reading them back in the next. Point all sessions at the
same root_dir and memory persists across runs.
from shipit_agent import Agent
from shipit_agent.llms.base import LLMResponse
from shipit_agent.models import ToolCall
class ScriptedLLM:
"""Offline LLM: session 1 writes a memory, session 2 reads it back."""
def __init__(self, responses):
self._responses = list(responses)
self._i = 0
def complete(self, *, messages, tools=None, system_prompt=None,
metadata=None, **kwargs):
if self._i < len(self._responses):
resp = self._responses[self._i]
self._i += 1
return resp
return LLMResponse(content="done")
shared_root = Path(tempfile.mkdtemp(prefix="shipit_shared_memory_"))
# Session 1: the agent records a learning into memory.
session1 = Agent(
llm=ScriptedLLM([
LLMResponse(tool_calls=[ToolCall(name="claude_memory", arguments={
"command": "create",
"path": "learnings.md",
"file_text": "The user prefers concise answers.\n",
})]),
LLMResponse(content="Noted your preference for next time."),
]),
tools=[ClaudeMemoryTool(root_dir=shared_root)],
)
print("session 1:", session1.run("Remember: I like concise answers.").output)# Session 2: a fresh agent (same root_dir) reads the memory back.
session2 = Agent(
llm=ScriptedLLM([
LLMResponse(tool_calls=[ToolCall(name="claude_memory", arguments={
"command": "view", "path": "learnings.md",
})]),
LLMResponse(content="I recalled that you prefer concise answers."),
]),
tools=[ClaudeMemoryTool(root_dir=shared_root)],
)
result2 = session2.run("What do you remember about me?")
print("session 2:", result2.output)
# The recalled memory is visible in the tool message of session 2.
for m in result2.messages:
if getattr(m, "role", None) == "tool" and m.name == "claude_memory":
print("recalled memory ->", m.content)ClaudeMemoryTool is one tool with a command arg: view / create /
str_replace / insert / delete / rename, all sandboxed under root_dir.ToolContext(prompt=...) for tests, or attach it to an
Agent for the model to manage its own durable memory.root_dir and learnings persist across sessions.