Metadata-Version: 2.4
Name: astrocyte
Version: 0.14.0
Summary: Open-source memory framework for AI agents
Project-URL: Documentation, https://astrocyteai.github.io/astrocyte/
Project-URL: Homepage, https://github.com/AstrocyteAI/astrocyte
Project-URL: Issues, https://github.com/AstrocyteAI/astrocyte/issues
Project-URL: PyPI, https://pypi.org/project/astrocyte/
Project-URL: Repository, https://github.com/AstrocyteAI/astrocyte
Author-email: Calvin Cheng <linchuan.cheng@gmail.com>
License-Expression: Apache-2.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: h2>=4.3.0
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Provides-Extra: all
Requires-Dist: astrocyte-elasticsearch<1,>=0.1.0; extra == 'all'
Requires-Dist: astrocyte-ingestion-github<1,>=0.1.0; extra == 'all'
Requires-Dist: astrocyte-ingestion-kafka<1,>=0.1.0; extra == 'all'
Requires-Dist: astrocyte-ingestion-redis<1,>=0.1.0; extra == 'all'
Requires-Dist: astrocyte-integration-tavus<1,>=0.1.0; extra == 'all'
Requires-Dist: astrocyte-neo4j<1,>=0.1.0; extra == 'all'
Requires-Dist: astrocyte-postgres<2,>=0.8.0; extra == 'all'
Requires-Dist: astrocyte-qdrant<1,>=0.1.0; extra == 'all'
Requires-Dist: deepeval>=2.0; extra == 'all'
Requires-Dist: fastapi>=0.115; extra == 'all'
Requires-Dist: fastmcp>=3.0; extra == 'all'
Requires-Dist: openai>=1.0; extra == 'all'
Requires-Dist: opentelemetry-api>=1.20; extra == 'all'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'all'
Requires-Dist: pgqueuer>=0.26.3; extra == 'all'
Requires-Dist: prometheus-client>=0.20; extra == 'all'
Requires-Dist: sentence-transformers>=2.2; extra == 'all'
Requires-Dist: snowballstemmer>=2.2; extra == 'all'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'all'
Provides-Extra: bench
Requires-Dist: aiobotocore>=2.13; extra == 'bench'
Requires-Dist: astrocyte-ingestion-github<1,>=0.1.0; extra == 'bench'
Requires-Dist: astrocyte-ingestion-kafka<1,>=0.1.0; extra == 'bench'
Requires-Dist: astrocyte-ingestion-redis<1,>=0.1.0; extra == 'bench'
Requires-Dist: astrocyte-postgres<2,>=0.8.0; extra == 'bench'
Requires-Dist: dateparser>=1.2; extra == 'bench'
Requires-Dist: deepeval>=2.0; extra == 'bench'
Requires-Dist: fastapi>=0.115; extra == 'bench'
Requires-Dist: fastmcp>=3.0; extra == 'bench'
Requires-Dist: openai>=1.0; extra == 'bench'
Requires-Dist: pgqueuer>=0.26.3; extra == 'bench'
Requires-Dist: pre-commit>=4.0; extra == 'bench'
Requires-Dist: pytest-asyncio>=0.23; extra == 'bench'
Requires-Dist: pytest-cov>=6.0; extra == 'bench'
Requires-Dist: pytest-timeout>=2.2; extra == 'bench'
Requires-Dist: pytest-xdist>=3.5; extra == 'bench'
Requires-Dist: pytest>=8.0; extra == 'bench'
Requires-Dist: ruff>=0.4; extra == 'bench'
Requires-Dist: snowballstemmer>=2.2; extra == 'bench'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'bench'
Provides-Extra: default
Requires-Dist: astrocyte-postgres<2,>=0.8.0; extra == 'default'
Provides-Extra: dev
Requires-Dist: deepeval>=2.0; extra == 'dev'
Requires-Dist: fastapi>=0.115; extra == 'dev'
Requires-Dist: fastmcp>=3.0; extra == 'dev'
Requires-Dist: pgqueuer>=0.26.3; extra == 'dev'
Requires-Dist: pre-commit>=4.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.2; extra == 'dev'
Requires-Dist: pytest-xdist>=3.5; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: snowballstemmer>=2.2; extra == 'dev'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'dev'
Provides-Extra: documents
Requires-Dist: astrocyte-ingestion-document<1,>=0.1.0; extra == 'documents'
Provides-Extra: elasticsearch
Requires-Dist: astrocyte-elasticsearch<1,>=0.1.0; extra == 'elasticsearch'
Provides-Extra: eval
Requires-Dist: deepeval>=2.0; extra == 'eval'
Requires-Dist: snowballstemmer>=2.2; extra == 'eval'
Provides-Extra: gateway
Requires-Dist: fastapi>=0.115; extra == 'gateway'
Requires-Dist: uvicorn[standard]>=0.30; extra == 'gateway'
Provides-Extra: github
Requires-Dist: astrocyte-ingestion-github<1,>=0.1.0; extra == 'github'
Provides-Extra: kafka
Requires-Dist: astrocyte-ingestion-kafka<1,>=0.1.0; extra == 'kafka'
Provides-Extra: mcp
Requires-Dist: fastmcp>=3.0; extra == 'mcp'
Provides-Extra: neo4j
Requires-Dist: astrocyte-neo4j<1,>=0.1.0; extra == 'neo4j'
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.20; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.20; extra == 'otel'
Provides-Extra: poll
Requires-Dist: astrocyte-ingestion-github<1,>=0.1.0; extra == 'poll'
Provides-Extra: postgres
Requires-Dist: astrocyte-postgres<2,>=0.8.0; extra == 'postgres'
Provides-Extra: prometheus
Requires-Dist: prometheus-client>=0.20; extra == 'prometheus'
Provides-Extra: qdrant
Requires-Dist: astrocyte-qdrant<1,>=0.1.0; extra == 'qdrant'
Provides-Extra: redis
Requires-Dist: astrocyte-ingestion-redis<1,>=0.1.0; extra == 'redis'
Provides-Extra: rerank
Requires-Dist: sentence-transformers>=2.2; extra == 'rerank'
Provides-Extra: s3-ingest
Requires-Dist: astrocyte-ingestion-s3<1,>=0.1.0; extra == 's3-ingest'
Provides-Extra: stream
Requires-Dist: astrocyte-ingestion-kafka<1,>=0.1.0; extra == 'stream'
Requires-Dist: astrocyte-ingestion-redis<1,>=0.1.0; extra == 'stream'
Provides-Extra: tavus
Requires-Dist: astrocyte-integration-tavus<1,>=0.1.0; extra == 'tavus'
Provides-Extra: worker
Requires-Dist: pgqueuer>=0.26.3; extra == 'worker'
Description-Content-Type: text/markdown

![Astrocyte](https://raw.githubusercontent.com/AstrocyteAI/astrocyte/main/docs/public/logo.svg)

# Astrocyte

**Open-source memory framework for AI agents.**
Retain, recall, and synthesize — with pluggable backends, built-in governance, and 18 framework integrations.

[![PyPI](https://img.shields.io/pypi/v/astrocyte)](https://pypi.org/project/astrocyte/)
[![Python](https://img.shields.io/pypi/pyversions/astrocyte)](https://pypi.org/project/astrocyte/)
[![License](https://img.shields.io/github/license/AstrocyteAI/astrocyte)](https://github.com/AstrocyteAI/astrocyte/blob/main/LICENSE)
[![Docs](https://img.shields.io/badge/docs-astrocyte-blue)](https://astrocyteai.github.io/astrocyte/)

---

## What is Astrocyte?

Astrocyte gives AI agents **persistent memory** — store what matters, retrieve what's relevant, synthesize answers from accumulated knowledge. It sits between your agents and their storage, providing:

- **Three operations:** `retain()`, `recall()`, `reflect()` — one API for every agent and every backend
- **Pluggable backends:** storage providers (pgvector, Pinecone, Qdrant, Neo4j) or engine providers (Mystique, Mem0, Zep, Letta)
- **Built-in governance:** PII scanning, rate limits, token budgets, circuit breakers, access control, observability
- **18 framework integrations:** LangGraph, CrewAI, OpenAI, Claude Agent SDK, Google ADK, AutoGen, and more
- **MCP server:** Any MCP-capable agent (Claude Code, Cursor, Windsurf) gets memory with zero code

## Quick start

```bash
pip install astrocyte
```

```python
from astrocyte import Astrocyte

brain = Astrocyte.from_config("astrocyte.yaml")

# Store a memory
await brain.retain("Calvin prefers dark mode", bank_id="user-123")

# Recall relevant memories
hits = await brain.recall("What are Calvin's preferences?", bank_id="user-123")

# Synthesize an answer from memory
result = await brain.reflect("Summarize what we know about Calvin", bank_id="user-123")
```

## Agent framework integrations

Astrocyte works with every major agent framework through thin middleware — one integration per framework, works with every memory backend.

| Framework | Module |
|---|---|
| LangGraph / LangChain | `astrocyte.integrations.langgraph` |
| CrewAI | `astrocyte.integrations.crewai` |
| OpenAI Agents SDK | `astrocyte.integrations.openai_agents` |
| Claude Agent SDK | `astrocyte.integrations.claude_agent_sdk` |
| Google ADK | `astrocyte.integrations.google_adk` |
| Pydantic AI | `astrocyte.integrations.pydantic_ai` |
| AutoGen / AG2 | `astrocyte.integrations.autogen` |
| Smolagents (HuggingFace) | `astrocyte.integrations.smolagents` |
| LlamaIndex | `astrocyte.integrations.llamaindex` |
| Semantic Kernel | `astrocyte.integrations.semantic_kernel` |
| DSPy | `astrocyte.integrations.dspy` |
| CAMEL-AI | `astrocyte.integrations.camel_ai` |
| BeeAI (IBM) | `astrocyte.integrations.beeai` |
| Strands Agents (AWS) | `astrocyte.integrations.strands` |
| LiveKit Agents | `astrocyte.integrations.livekit` |
| Haystack (deepset) | `astrocyte.integrations.haystack` |
| Microsoft Agent Framework | `astrocyte.integrations.microsoft_agent` |
| MCP (Claude Code, Cursor) | `astrocyte.mcp` |

## MCP server

Any MCP-capable agent gets memory with zero code integration:

```json
{
  "mcpServers": {
    "memory": {
      "command": "astrocyte-mcp",
      "args": ["--config", "astrocyte.yaml"]
    }
  }
}
```

## Built-in governance

Neuroscience-inspired policies that protect every operation — regardless of backend:

- **PII barriers** — regex, NER, or LLM-based scanning with redact/reject/warn actions
- **Rate limits & quotas** — token bucket rate limiting and daily quotas per bank
- **Circuit breakers** — automatic degraded mode when backends go down
- **Access control** — per-bank read/write/forget/admin permissions
- **Observability** — OpenTelemetry spans and Prometheus metrics on every operation
- **Data governance** — classification levels, compliance profiles (GDPR, HIPAA, PDPA)

## Multi-bank orchestration

Query across personal, team, and org banks with cascade, parallel, or first-match strategies:

```python
hits = await brain.recall(
    "What are Calvin's preferences and team policies?",
    banks=["personal", "team", "org"],
    strategy="cascade",
)
```

## Memory portability

Export and import memories between providers — no vendor lock-in:

```python
await brain.export_bank("user-123", "./backup.ama.jsonl")
await brain.import_bank("user-123", "./backup.ama.jsonl")
```

## Evaluation

Benchmark memory quality with built-in suites and DeepEval LLM-as-judge:

```python
from astrocyte.eval import MemoryEvaluator

evaluator = MemoryEvaluator(brain)
results = await evaluator.run_suite("basic", bank_id="eval-bank")
print(f"Recall precision: {results.metrics.recall_precision:.2%}")
```

## Benchmarks

Astrocyte includes adapters for two academic memory benchmarks plus built-in eval suites.

| Benchmark | What it tests | Dataset |
|---|---|---|
| **LoCoMo** (ECAI 2025) | Long-term conversational memory — single-hop, multi-hop, temporal, open-domain QA | [snap-research/locomo](https://github.com/snap-research/locomo) |
| **LongMemEval** | Long-context memory extraction, reasoning, temporal ordering | [xiaowu0162/LongMemEval](https://github.com/xiaowu0162/LongMemEval) |

### Quick start

The PageIndex bench (M9+) requires Postgres + a real LLM provider; secrets are
loaded via [Doppler](https://www.doppler.com/) (`DOPPLER_TOKEN` set in your
environment or `doppler login` once locally). The Makefile already runs
`doppler run --` for every bench target.

```bash
# Full LoCoMo run (200 stratified questions by default, ~$1 in API costs)
make bench-locomo

# Quick variant — cap to ~50 questions for fast iteration
make bench-locomo LOCOMO_MAX_Q=5

# LongMemEval (200 samples by default; ~$5 in API costs)
make bench-longmemeval
make bench-longmemeval LME_MAX_SAMPLES=50      # quick

# Parallel run on two Postgres containers (locomo on :5433, lme on :5434)
make bench-parallel
```

Results land under `benchmark-results/pageindex/{locomo,lme}/` and are
automatically uploaded to the R2 archive (see `make bench-archive-*` targets).

### Dataset management

Datasets are cloned to `datasets/` (gitignored) on first benchmark run. To manage manually:

```bash
make fetch-datasets       # Fetch all datasets
make clean-datasets       # Remove downloaded datasets
make clean-results        # Remove benchmark results
```

See [`docs/_design/evaluation.md`](../docs/_design/evaluation.md) for the full evaluation specification.

## Development

From [`astrocyte-py/`](.) with the dev extra:

```bash
uv sync --extra dev
uv run ruff check astrocyte/ tests/
uv run python -m pytest tests/ -x --tb=short
```

**Git hooks (Ruff via [pre-commit](https://pre-commit.com))** — reduces CI lint failures. From the **repository root** (parent of `astrocyte-py/`):

```bash
uv sync --extra dev --directory astrocyte-py
uv run --project astrocyte-py pre-commit install
```

Hooks run automatically on `git commit`; run on all files anytime with:

```bash
uv run --project astrocyte-py pre-commit run --all-files
```

**CodeQL** is not run in pre-commit (too slow for every commit). Enable **Code scanning** under the repo’s **Settings → Code security** so GitHub runs CodeQL on pushes/PRs using the default or advanced setup.

## Documentation

**[astrocyteai.github.io/astrocyte](https://astrocyteai.github.io/astrocyte/)**

- [Quick Start](https://astrocyteai.github.io/astrocyte/end-user/quick-start/)
- [Architecture](https://astrocyteai.github.io/astrocyte/design/architecture/)
- [Provider SPI](https://astrocyteai.github.io/astrocyte/plugins/provider-spi/)
- [Integration guides](https://astrocyteai.github.io/astrocyte/plugins/agent-framework-middleware/) (one per framework)

## License

Apache 2.0 — see [LICENSE](https://github.com/AstrocyteAI/astrocyte/blob/main/LICENSE).
