# Installation

> Install the core plus the workflow, agent, or Kafka packages you need.

Source: https://docs.pyrula.io/getting-started/install/

## Build from source

`pyrula` isn't on PyPI yet, so build it from source. You need Python 3.11 through 3.15 (GIL
builds; free-threaded `python3.14t` isn't supported), a Rust toolchain and
[uv](https://docs.astral.sh/uv/):

```bash
git clone https://github.com/pyrula-io/pyrula
cd pyrula
uv sync        # builds both Rust extensions (release) and installs every package
```

The first build takes a few minutes. Rebuild with `uv sync`, not `maturin develop`: the next
`uv sync` undoes a `maturin develop` build. `.python-version` pins 3.13; pass
`uv sync --python 3.12` for another version.

```bash
uv run python -c "from pyrula.workflows import workflow; print('ok')"
uv run pyrula --help
```

Then follow the [Quickstart](https://docs.pyrula.io/getting-started/quickstart.md), with `uv run` in front of its
commands.

## Packages

Each runtime is its own package on top of the core, installed through an extra of `pyrula`:

| Package | Install | Import |
|---|---|---|
| Core | `pip install pyrula` | `pyrula` |
| Workflows | `pip install "pyrula[workflows]"` | `pyrula.workflows` |
| Agents | `pip install "pyrula[agents]"` | `pyrula.agents` |
| Kafka | `pip install "pyrula[kafka]"` | `pyrula.kafka` |
| Cloud client | `pip install "pyrula[cloud]"` | `pyrula.cloud` |
| Everything | `pip install "pyrula[all]"` | all of the above; provider SDKs and framework adapters are separate extras (below) |

`pip install pyrula-agents` and `pip install "pyrula[agents]"` install the same thing. Bare
`pyrula` has no dependencies. `pyrula dev` and the run browser ship with every runtime.

## Extras

Combine extras in one install, as in `"pyrula[agents,postgres]"`. A missing optional library
raises an `ImportError` that names the extra.

| Extra | Adds | Through |
|---|---|---|
| `postgres` | `asyncpg`, `alembic`, `sqlalchemy`, `greenlet` | `pyrula-workflows[postgres]` |
| `s3` | `boto3` for the S3 fixture store | `pyrula-workflows[s3]` |
| `otel` | OpenTelemetry API, SDK and OTLP exporter | `pyrula-workflows[otel]` |
| `msk` | AWS MSK IAM signer | `pyrula-kafka[msk]` |
| `litellm` | the provider SDK | `pyrula-agents[litellm]` |
| `gemini` | `google-genai`, for `GeminiLLM` | `pyrula-agents[gemini]` |
| `bedrock` | `boto3`, for `BedrockLLM` | `pyrula-agents[bedrock]` |
| `langchain`, `langgraph` | the integration libraries | `pyrula-agents[langchain]`, `pyrula-agents[langgraph]` |
| `pydantic-ai` | the integration library | `pyrula-agents[pydantic-ai]` |

`"pyrula[all]"` installs `workflows`, `agents`, `kafka` and `cloud` with `postgres` and
`otel`. It leaves out litellm, gemini, bedrock, langchain, langgraph, pydantic-ai, and the AWS
extras (`msk`, `s3`); add the ones your app uses. `pyrula init --langgraph` and
`pyrula init --pydantic-ai` print the install line when their library is missing.

## Requirements

- Python 3.11 through 3.15 with the GIL, on Linux, macOS or Windows (x86_64 and ARM64). The
  Windows ARM64 wheel is built but not run in CI.
- A store for runs that outlive the process: a SQLite file (one host, Linux and macOS) or
  Valkey 7.2+ or Redis 6.0+ (several hosts). [Choosing a store](https://docs.pyrula.io/getting-started/choosing-a-store.md)
  compares them.
- Optional: Postgres 15+ for the event archive, alongside a Valkey store.

The [Quickstart](https://docs.pyrula.io/getting-started/quickstart.md) needs no server, broker, API key or account.

## Durability config

`open_store()` opens the store `PYRULA_STORE_URL` names, so scripts, the CLI and the scaffolded
app share it:

```python
from pyrula.workflows import open_store

store = open_store(default="sqlite:///.pyrula/dev.db")
```

| Variable | Value |
|---|---|
| `PYRULA_STORE_URL` | `sqlite:///relative.db`, `sqlite:////absolute.db`, `valkey://` or `redis://` (either scheme works for both servers). A password goes in the URL: `redis://:password@host:6379`. |
| `PYRULA_VALKEY_NAMESPACE` | Key namespace, default `default`. Give each environment its own when they share an instance. |
| `PYRULA_POSTGRES_DSN` | The archive database for a Valkey store. |

```bash
export PYRULA_STORE_URL=redis://localhost:6379
export PYRULA_POSTGRES_DSN=postgresql://user:pass@localhost:5432/pyrula_events
```

Give Pyrula its own Valkey instance with `maxmemory-policy noeviction` and persistence on
(`appendonly yes` or an RDB `save` schedule). An `allkeys-*` policy deletes in-flight run
journals, so the store raises `ConfigurationError` under it; a `volatile-*` policy gets a
warning, since it can drop only finished-run history and a few short-lived keys. Without
persistence, a server restart loses every in-flight run.

Managed services (ElastiCache, Memorystore, Azure Managed Redis, Redis Cloud, Render) default to
an evicting policy. [Managed Valkey and Redis](https://docs.pyrula.io/getting-started/managed-valkey.md) has the fix for
each, and `pyrula dev --check --store URL` runs the same check before you deploy.
