GitHub Storage
strands-github-storage is a Storage backend that persists each entry as a file in a GitHub repository, at the entry’s key path on a branch. Because the store is a git repository, its contents are browsable in the GitHub UI, diffable per change, and versioned in history.
It implements the SDK’s four-method Storage interface (write, read, delete, list), so it plugs in anywhere a Storage is accepted — session managers, context offloading, and file-backed memory stores. Available for both the Python and TypeScript SDKs.
Installation
Section titled “Installation”pip install strands-github-storagestrands-agents and PyGithub are installed as dependencies.
npm install strands-github-storage@strands-agents/sdk is a peer dependency; @octokit/rest is bundled.
Basic setup
Section titled “Basic setup”import asynciofrom strands_github_storage import GithubStorage
storage = GithubStorage( owner="myorg", repo="agent-memory", branch="main", # optional, defaults to "main" token="ghp_...", # required for writes and private repos)
async def main() -> None: await storage.write("facts/note.md", b"remember this") data = await storage.read("facts/note.md") # bytes | None keys = await storage.list("facts/") # ["facts/note.md"] await storage.delete("facts/note.md")
asyncio.run(main())import { GithubStorage } from 'strands-github-storage'
const storage = new GithubStorage({ owner: 'myorg', repo: 'agent-memory', branch: 'main', // optional, defaults to 'main' token: process.env.GITHUB_TOKEN, // required for writes and private repos})
await storage.write('facts/note.md', new TextEncoder().encode('remember this'))const bytes = await storage.read('facts/note.md') // Uint8Array | nullconst keys = await storage.list('facts/') // ['facts/note.md']await storage.delete('facts/note.md')Wiring into an agent
Section titled “Wiring into an agent”Pass it wherever a Storage is accepted so the agent’s persisted data lives in a browsable, versioned repo:
Use it as a session manager’s storage, so conversation sessions persist to a GitHub repo:
from strands import Agentfrom strands.session import SnapshotSessionManagerfrom strands_github_storage import GithubStorage
storage = GithubStorage(owner="myorg", repo="agent-sessions", token="ghp_...")agent = Agent(session_manager=SnapshotSessionManager("agent-sessions", storage=storage))Back a FileMemoryStore so an agent’s knowledge lives in a browsable, versioned repo:
import { Agent, MemoryManager } from '@strands-agents/sdk'import { FileMemoryStore } from '@strands-agents/sdk/vended-memory-stores/file-memory-store'import { GithubStorage } from 'strands-github-storage'
const memoryStore = new FileMemoryStore({ name: 'agent-memory', storage: new GithubStorage({ owner: 'myorg', repo: 'agent-memory', token }),})
const agent = new Agent({ model, memoryManager: new MemoryManager({ stores: [memoryStore] }) })Configuration
Section titled “Configuration”| Parameter | Required | Description |
|---|---|---|
owner | Yes | Repository owner (user or organization login). |
repo | Yes | Repository name. |
branch | No | Branch to read from and commit to. Defaults to main. |
token | For writes | GitHub token. Needed for any write and for reading private repos. |
githuboctokit | No | A pre-configured GitHub client, as an alternative to token (e.g. to add retry/throttling behavior). |
Behavior and limits
Section titled “Behavior and limits”- One commit per operation. Each
writeanddeleteis its own commit (update <key>/delete <key>). A burst of writes produces a burst of commits. - Single writer per branch. Commits advance the branch ref without a compare-and-swap retry, so a concurrent writer that moves the branch head surfaces GitHub’s non-fast-forward rejection as a
StorageErrorrather than being retried. readis limited to files under 1 MB — the ceiling of the GitHub contents API’s inline response. Markdown memory is far below this.listfails loud on truncation. GitHub’s git-tree API caps very large trees and does not paginate; rather than return a silent partial listing,listthrows aStorageError.- No built-in rate-limit handling. To add exponential backoff on
429/5xx, pass a pre-configured client via .githuboctokit