diff --git a/apps/docs/smfs/providers/daytona.mdx b/apps/docs/smfs/providers/daytona.mdx index 73f8c435..b393a748 100644 --- a/apps/docs/smfs/providers/daytona.mdx +++ b/apps/docs/smfs/providers/daytona.mdx @@ -125,9 +125,16 @@ The recommended pattern: your agent code uses `@supermemory/bash` for memory and ```python agent.py import os + from supermemory import create_bash from daytona_sdk import Daytona, DaytonaConfig - # 1. Set up code execution (Daytona sandbox) + # 1. Set up memory (SMFS bash tool — runs in your code, not the sandbox) + bash = create_bash( + api_key=os.environ["SUPERMEMORY_API_KEY"], + container_tag="agent_memory", + ) + + # 2. Set up code execution (Daytona sandbox) config = DaytonaConfig( api_key=os.environ["DAYTONA_API_KEY"], api_url="https://app.daytona.io/api", @@ -135,31 +142,19 @@ The recommended pattern: your agent code uses `@supermemory/bash` for memory and daytona = Daytona(config) sandbox = daytona.create() - # 2. Install SMFS inside the sandbox - sandbox.process.exec( - "curl -fsSL https://smfs.ai/install | sh" - ) + # 3. Read memory from your orchestrating code + profile = bash.exec("cat /profile.md") + print(profile.stdout) - # 3. Log in and mount - sandbox.process.exec( - f"~/.local/bin/smfs login --key {os.environ['SUPERMEMORY_API_KEY']}" - ) - sandbox.process.exec( - "~/.local/bin/smfs mount agent_memory --ephemeral" - ) - - # 4. Your agent can now use the filesystem - response = sandbox.process.exec("cat agent_memory/profile.md") + # 4. Execute code in the sandbox + response = sandbox.process.exec("python3 -c 'print(\"Hello from Daytona!\")'") print(response.result) - # 5. Semantic search - response = sandbox.process.exec( - "~/.local/bin/smfs grep 'preferred language'" - ) - print(response.result) + # 5. Semantic search across memory + results = bash.exec("sgrep 'preferred language'") + print(results.stdout) # 6. Clean up - sandbox.process.exec("~/.local/bin/smfs unmount agent_memory") daytona.delete(sandbox) ``` @@ -169,6 +164,10 @@ The recommended pattern: your agent code uses `@supermemory/bash` for memory and If your Daytona sandbox has unrestricted network access, you can install and mount SMFS directly inside it. This gives the agent a real filesystem it can navigate with standard Unix commands. + + Some Daytona datacenter IPs are blocked by upstream firewalls. If `smfs login` or `smfs mount` fails with a TLS connection error from inside the sandbox, switch to the **Bash Tool** pattern above — it runs in your orchestrating code where network access is unrestricted. + + ```python from daytona_sdk import Daytona, DaytonaConfig import os diff --git a/apps/docs/smfs/providers/e2b.mdx b/apps/docs/smfs/providers/e2b.mdx index 7baf4f3c..f86490e4 100644 --- a/apps/docs/smfs/providers/e2b.mdx +++ b/apps/docs/smfs/providers/e2b.mdx @@ -112,44 +112,31 @@ The recommended pattern: your agent code uses `@supermemory/bash` for memory and ```python agent.py import os + from supermemory import create_bash from e2b_code_interpreter import Sandbox - # 1. Create an E2B sandbox + # 1. Set up memory (SMFS bash tool — runs in your code, not the sandbox) + bash = create_bash( + api_key=os.environ["SUPERMEMORY_API_KEY"], + container_tag="agent_memory", + ) + + # 2. Set up code execution (E2B sandbox) sandbox = Sandbox.create(timeout=300) - # 2. Install SMFS inside the sandbox - sandbox.commands.run("curl -fsSL https://smfs.ai/install | sh") + # 3. Read memory from your orchestrating code + profile = bash.exec("cat /profile.md") + print(profile.stdout) - # 3. Fix FUSE permissions (required in E2B sandboxes) - sandbox.commands.run("sudo chmod 666 /dev/fuse") - sandbox.commands.run( - "echo 'user_allow_other' | sudo tee -a /etc/fuse.conf > /dev/null" - ) + # 4. Execute code in the sandbox + execution = sandbox.run_code("print('Hello from E2B!')") + print(execution.text) - # 4. Log in and mount - sandbox.commands.run( - f"~/.local/bin/smfs login --key {os.environ['SUPERMEMORY_API_KEY']}" - ) - sandbox.commands.run( - "bash -c '~/.local/bin/smfs mount agent_memory --ephemeral" - " --path /home/user/memory --foreground > /tmp/smfs.log 2>&1" - " & sleep 5 && echo MOUNTED'", - timeout=15, - ) + # 5. Semantic search across memory + results = bash.exec("sgrep 'preferred language'") + print(results.stdout) - # 5. Your agent can now use the filesystem - sandbox.commands.run("cat /home/user/memory/profile.md") - - # 6. Semantic search - sandbox.commands.run( - "~/.local/bin/smfs grep 'preferred language'" - ) - - # 7. Clean up - sandbox.commands.run( - "~/.local/bin/smfs unmount agent_memory 2>/dev/null", - timeout=10, - ) + # 6. Clean up sandbox.kill() ``` @@ -201,6 +188,11 @@ sandbox.commands.run( result = sandbox.commands.run("cat /home/user/memory/profile.md") print(result.stdout) +# Write to memory (use sudo — FUSE mount is owned by root) +sandbox.commands.run( + "sudo bash -c 'echo \"User prefers Python\" > /home/user/memory/notes.md'" +) + # Semantic grep works inside the mount result = sandbox.commands.run("~/.local/bin/smfs grep 'deadlines'") print(result.stdout) @@ -210,6 +202,10 @@ sandbox.commands.run("~/.local/bin/smfs unmount agent_memory 2>/dev/null", timeo sandbox.kill() ``` + + The FUSE mount is owned by root. Writing files requires `sudo` (e.g., `sudo bash -c 'echo "..." > /path/file'`). Reads work without sudo. + + ## Custom E2B template with SMFS pre-installed For faster startup, bake SMFS and the FUSE fixes into a custom E2B template: