Metadata-Version: 2.4
Name: slie
Version: 1.0.0
Summary: An open-source agent harness: build, run, and operate AI agents on your own infrastructure.
Author: Tadej Rola
Author-email: Tadej Rola <tadej.rola@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Dist: deepagents>=0.7.6,<0.8
Requires-Dist: aiosqlite>=0.21
Requires-Dist: langgraph-checkpoint-sqlite>=3.1,<4
Requires-Dist: langchain-mcp-adapters>=0.3.2,<0.4
Requires-Dist: croniter>=6.2.4
Requires-Dist: fastapi>=0.133 ; extra == 'server'
Requires-Dist: uvicorn>=0.35 ; extra == 'server'
Requires-Dist: sse-starlette>=2.1 ; extra == 'server'
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/tadejrola/slie
Project-URL: Documentation, https://github.com/tadejrola/slie/tree/main/docs
Project-URL: Repository, https://github.com/tadejrola/slie
Project-URL: Issues, https://github.com/tadejrola/slie/issues
Provides-Extra: server
Description-Content-Type: text/markdown

# Slie

**An open-source agent harness: build, run, and operate AI agents on your own infrastructure.**

Slie 1.0 — MIT licensed. Use it commercially, modify it, embed it in something you sell,
redistribute it. There is no paid tier of this package and nothing in it expires.

There is also [**Slie Cloud**](#slie-cloud), a hosted platform built on this harness through
the same public API. It is a separate, commercial product; you never need it to run Slie.

## What Slie is

Slie is a Python framework for defining agents and operating them over their full lifecycle:

- **Define** agents as stored definitions — instructions, model, model parameters, runtime
  options, the MCP servers they may use, the agents they may delegate to, and the native
  features they opt into — created once and addressed by id, from the SDK or over the API.
- **Run** them anywhere — in-process through the Python SDK, or as a self-hosted service with an
  HTTP API and server-sent event streams, launched by the CLI.
- **Operate** them — first-class runs with history and a normalized event log, cancellation,
  human approval before an agent acts, memory that outlives a conversation, delegation to other
  agents as runs of their own, the tokens every run spent, and the files a run produced.

Slie uses [Deep Agents](https://github.com/langchain-ai/deepagents) as its initial execution
runtime, behind a strict boundary: the runtime is an implementation detail, never part of Slie's
public API.

## Quickstart

```bash
pip install slie          # or: uv add slie
```

Both paths below run a real model, so the API key its provider needs must be in the environment —
`ANTHROPIC_API_KEY` for the `anthropic:` models used here. Export it, or keep it in a file:

```bash
cp .env.example .env          # then fill in the key; .env is gitignored
uv run --env-file .env slie server
```

### Python SDK

[`examples/quickstart.py`](https://github.com/tadejrola/slie/blob/main/examples/quickstart.py) is this program plus the key check and exit
code a script needs. Run it with `uv run examples/quickstart.py`:

```python
import asyncio

import slie


async def main() -> None:
    app = slie.Slie()  # in memory; pass database="slie.db" for a SQLite file
    agent = await app.create_agent(
        name="haiku-writer",
        instructions="You write haiku. Reply with the poem and nothing else.",
        model="anthropic:claude-haiku-4-5",
    )
    run = await app.run(agent, "Write a haiku about hexagonal architecture.")
    print(run.result.text if run.result else run.error)


asyncio.run(main())
```

`app.run(...)` waits for the run to finish. `app.stream(agent, text)` starts the same run and
yields its [events](https://github.com/tadejrola/slie/blob/main/docs/events.md) as they happen instead. Consuming a stream to its terminal
event cleans up after itself; if you stop early, close it — `async with
contextlib.aclosing(app.stream(agent, text)) as events:` — so the run's event subscription is
released there and then.

An in-memory application needs no cleanup. **A SQLite-backed one must be closed** — `async with
slie.Slie(database="slie.db") as app:`, or `await app.aclose()`. Closing drains the runs still in
flight, then closes every SQLite file the application opened: aiosqlite serves each connection
from a non-daemon worker thread, so an application still referenced at interpreter shutdown hangs
the process instead of letting it exit.

### Self-hosted server

```bash
uv run slie server     # http://127.0.0.1:8340, storing in ./slie.db
```

The server binds localhost and the API is unauthenticated: exposing it is a reverse proxy's job
(ADR-0005). The OpenAPI document is at `/openapi.json`, browsable at `/docs`.

```bash
curl -sX POST http://127.0.0.1:8340/v1/agents \
  -H 'content-type: application/json' \
  -d '{"name": "researcher",
       "instructions": "Answer briefly.",
       "model": "anthropic:claude-haiku-4-5"}'
```

```json
{"id": "ag_ee48e978bed34cf6a92fa6d67f56b76b", "name": "researcher", "description": "",
 "instructions": "Answer briefly.", "model": "anthropic:claude-haiku-4-5",
 "model_parameters": {}, "runtime_options": {}, "mcp_servers": [], "delegates_to": [],
 "token_budget": 0, "time_budget_seconds": 0,
 "output_schema": {}, "guardrails": [], "features": []}
```

Start a run under it, then stream the run's events as they happen:

```bash
curl -sX POST http://127.0.0.1:8340/v1/agents/$AGENT/runs \
  -H 'content-type: application/json' \
  -d '{"input": "Describe hexagonal architecture in one sentence."}'

curl -N http://127.0.0.1:8340/v1/runs/$RUN/events
```

## What you can do with it

| | |
|---|---|
| [Events](https://github.com/tadejrola/slie/blob/main/docs/events.md) | Nineteen event types, streamed over SSE and resumable with `Last-Event-ID` |
| [Sessions](https://github.com/tadejrola/slie/blob/main/docs/sessions.md) | Several turns in one conversation, serialized per session |
| [Approvals](https://github.com/tadejrola/slie/blob/main/docs/approvals.md) | A run pauses so a human can `approve`, `edit`, `reject`, or `respond` |
| [Native features](https://github.com/tadejrola/slie/blob/main/docs/features.md) | `ask_user`, `follow_ups`, `planning`, `memory` — named on the agent, off by default |
| [Delegation](https://github.com/tadejrola/slie/blob/main/docs/delegation.md) | An agent hands work to another agent, reads back what it started, and the child is a run you can watch and cancel |
| [Structured output](https://github.com/tadejrola/slie/blob/main/docs/structured-output.md) | Give an agent a JSON Schema; runs come back with the parsed object |
| [Evaluation](https://github.com/tadejrola/slie/blob/main/docs/evaluation.md) | Turn real runs into a test suite and score an agent against it |
| [Replay](https://github.com/tadejrola/slie/blob/main/docs/replay.md) | Re-run a stored run against a changed agent and compare outcome and cost |
| [Cost and budgets](https://github.com/tadejrola/slie/blob/main/docs/cost.md) | Tokens recorded per run, and a budget enforced across a delegation tree |
| [Artifacts](https://github.com/tadejrola/slie/blob/main/docs/artifacts.md) | The files a run wrote, listed and fetchable after it ends |
| [Guardrails](https://github.com/tadejrola/slie/blob/main/docs/guardrails.md) | Refuse text on the way in and out; checks plug in behind a port |
| [MCP servers](https://github.com/tadejrola/slie/blob/main/docs/mcp.md) | Named by the agent, configured by you; stdio and remote HTTP alike |
| [Configuration](https://github.com/tadejrola/slie/blob/main/docs/configuration.md) | CLI flags, model parameters, runtime options, credentials |
| [HTTP API](https://github.com/tadejrola/slie/blob/main/docs/http-api.md) | Every endpoint, listing and paging, deletion, and the error contract |

Full documentation is in [`docs/`](https://github.com/tadejrola/slie/tree/main/docs/); design decisions are recorded in
[`docs/adr/`](https://github.com/tadejrola/slie/tree/main/docs/adr/).

## Architecture

Slie follows a hexagonal (ports & adapters) architecture:

```text
      Python SDK        HTTP API        CLI (launcher)
           └────────────────┼──────────────────┘
                            │
                   application services
                            │
                     domain (pure)
                            │
                    ports (protocols)
                            ▲
           ┌────────────────┼─────────────┐
     runtime adapter   storage adapters   ...
      (Deep Agents)   (in-memory, SQLite)
```

The dependency rule — inner layers never import outer ones, and only adapters may import the
runtime stack — is enforced in CI with [import-linter](https://import-linter.readthedocs.io/).

## Development

Slie uses [uv](https://docs.astral.sh/uv/) for everything.

```bash
uv sync --all-extras     # environment + dev tools (the test suite needs the [server] extra)
uv run pre-commit install --hook-type pre-commit --hook-type commit-msg --hook-type pre-push

uv run pytest --cov      # tests with coverage gate
uv run ruff check .      # lint (ALL rules, explicit ignores only)
uv run ruff format .     # format
uv run pyright           # strict type check
uv run lint-imports      # architecture contracts
uv run pre-commit run --all-files   # every hook over the whole tree, as CI runs them
```

Every guideline is enforced twice: locally by pre-commit hooks on each commit, and
authoritatively by CI. See [CONTRIBUTING.md](https://github.com/tadejrola/slie/blob/main/CONTRIBUTING.md).

## Slie Cloud

Slie has no identity model, on purpose: the actor on an approval is an opaque string it records
and never reads to make a decision. It binds localhost and expects something in front of it. That
leaves four jobs to whoever operates it — who may see a run, who may approve one, who did, and how
two teams share one deployment. Self-hosted, they are yours to build.

[Slie Cloud](https://github.com/tadejrola/slie-cloud) is a commercial product that does them, plus
the screens the people doing them need: an inbox of everything waiting, chat, an agent studio,
usage per agent, and an append-only record of who decided what.

It is **not** open source, and it is **not** required. It is a client of the HTTP API documented in
[docs/http-api.md](https://github.com/tadejrola/slie/blob/main/docs/http-api.md) — the same one you would write against — so nothing in this
repository is held back to make it necessary, and an agent, a run or an event means the same thing
on both sides.

## License

[MIT](https://github.com/tadejrola/slie/blob/main/LICENSE). That is the whole licence: no additional grant to negotiate, no commercial-use
clause, no contributor licence agreement.
