strands-pixeltable
Pixeltable memory and read-only table tools for Strands Agents. Pixeltable is the table and embedding store (docs, source). Strands tool and memory interfaces are documented at strandsagents.com.
PixeltableMemoryStoreimplementsstrands.memory.MemoryStore.MemoryManagersearches it with the store's embedding index and can write notes and messages into it.pixeltable_toolsbuilds@toolfunctions:remember,recall,list_tables,describe_table,query_table, andsimilarity_search.
Requires Python 3.11+ (Pixeltable's floor), strands-agents 1.61.0+, and Pixeltable 0.7.8+.
Install
pip install strands-pixeltable
Local embeddings, with no API key:
pip install "strands-pixeltable[local]"
Memory
import asyncio
from strands import Agent
from strands.memory import MemoryManager
from strands_pixeltable import PixeltableMemoryStore, sentence_transformer_embedding
embed = sentence_transformer_embedding() # sentence-transformers/all-MiniLM-L6-v2
store = PixeltableMemoryStore(table_name="strands.memory", embedding=embed)
async def main() -> None:
await store.add("The user prefers aisle seats.")
for hit in await store.search("seat preference"):
print(hit.metadata["score"], hit.content)
asyncio.run(main())
agent = Agent(
memory_manager=MemoryManager(stores=[store], add_tool_config=True),
)
MemoryManager registers search_memory. add_tool_config=True also registers add_memory. With the default injection=True, retrieved rows are prepended to the model input and are not written into the conversation history.
The table is created on first use. Columns are memory_id (primary key), content, kind (note or message), role, metadata, session_id, and created_at. The store adds a btree index on session_id and an embedding index named content_embedding on content. store.table is that table.
add_messages stores each message containing text as "<role>: <text>", joining multiple text blocks with newlines. A message tracking_id becomes the primary key msg:<tracking_id>, so a retry does not insert a second row. Tool-only messages are skipped.
extraction=True opts into Strands background extraction. This store implements add_messages, so the manager writes the raw messages here and does not make a separate extraction model call. The default is off.
session_id= on the store filters search to that session. Pass session_id="" in the search options to search every session. A note's metadata["session_id"] overrides the store default for that row.
embedding must be a module-level Pixeltable UDF or a .using() binding. Omit it to use the local MiniLM model. Reopening a table that already has content_embedding does not load the model. The index is fixed at creation; if_exists="replace" builds a new table. replace fails when the table has views or snapshots.
Tools
import pixeltable as pxt
from strands import Agent
from strands.memory import MemoryManager
from strands_pixeltable import PixeltableMemoryStore, pixeltable_tools, sentence_transformer_embedding
embed = sentence_transformer_embedding()
pxt.create_dir("handbook", if_exists="ignore")
docs = pxt.create_table(
"handbook.docs",
{"topic": pxt.String, "text": pxt.String},
if_exists="ignore",
)
if docs.count() == 0:
docs.insert([{"topic": "expenses", "text": "Meals during business travel are reimbursed up to 60 EUR per day."}])
docs.add_embedding_index("text", string_embed=embed, if_exists="ignore")
memory = PixeltableMemoryStore(table_name="handbook.memory", embedding=embed)
agent = Agent(
system_prompt="Answer from the handbook. Remember durable facts about the user.",
tools=pixeltable_tools(["handbook.docs"], memory=memory),
memory_manager=MemoryManager(stores=[memory], add_tool_config=True),
)
print(agent("Can I expense a 75 EUR dinner? Remember that I travel monthly."))
tables is required. It is an allowlist of table paths or directory prefixes, matched case-insensitively. ["*"] is the whole catalog. ["*", "handbook.docs"] is rejected.
remember/recallwrite and search the memory store only.list_tables/describe_tablereport allowlisted tables, columns, and indexes.query_tableselects rows.whereis a JSON object of equality filters ({"status": "open"}). Timestamp, date, and UUID values are ISO strings.similarity_searchrunscolumn.similarity. Passqueryfor text orimagefor a file path or URL. The column needs an embedding index for that modality. Passidxwhen the column has more than one embedding index.
query_table and similarity_search do not insert, update, or delete. Default columns skip media, array, binary, and computed columns that are not stored. Explicitly selecting an unstored computed column is rejected so reading does not execute its function. A named media column is returned as a file URL. Version handles (docs:3) are refused.
max_rows (20) and max_chars (8000) bound query, similarity, and recall results, including their JSON envelope and metadata. truncated is true when a cap drops data; if even a shortened row cannot fit, the result list is empty. A budget too small for the result envelope raises ValueError.
examples/agent_with_memory.py builds the same agent. It stores a note and searches without a model. RUN_AGENT=1 invokes the model.
Development
pip install -e ".[dev]"
pytest tests/
ruff check . && ruff format --check .
mypy strands_pixeltable
Tests use a hash embedding and do not need an API key.
License
Apache 2.0
Metadata
Release files for strands-pixeltable 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| strands_pixeltable-0.1.0.tar.gz | 30.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| strands_pixeltable-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 52.5 kB
Release files / strands_pixeltable-0.1.0.tar.gz
| Download URL | strands_pixeltable-0.1.0.tar.gz |
|---|---|
| Size | 30.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5861be5fcf895111a9569001264dd507116b5c1203381277f4427ee409be662c
|
|
BLAKE2b-256 checksum How to use checksums |
71da48b925a30238331b1478e9619f09314c6a4d88502b0ff20f3dc283333e64
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency logRelease files / strands_pixeltable-0.1.0-py3-none-any.whl
| Download URL | strands_pixeltable-0.1.0-py3-none-any.whl |
|---|---|
| Size | 22.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0a2c94519a1783c9e04a7d66da0f64688a68d2b921c009ca31517c070da0e25b
|
|
BLAKE2b-256 checksum How to use checksums |
82e83e2253cbbfdd6a7448bbc8b2b5e4cd5110327703356a79a0a480560db61b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.
Transparency log