Tendwell
Self-hosted, local-first AgentOps for production health. Tendwell is an agent that watches your production signals and operational knowledge, reasons over them with a local LLM, and explains what it finds in plain language - then, only when you allow it, proposes remediations that a human approves and a tamper-evident audit log records.
It is built for the teams that cannot send production data to someone else's cloud: security-conscious and regulated environments. By default nothing leaves your infrastructure - not the metrics, not the runbooks, not the model.
- Local-first by default. No egress out of the box, including the LLM and embeddings. Point a backend off-host and Tendwell warns you, loudly, at startup.
- The LLM never executes. It can only propose. Deterministic validation and a human approval gate sit between any proposal and any change. Every step is an append-only, hash-chained audit event that cannot be silenced.
- Bring your own everything. Any OpenAI-compatible model (Ollama, vLLM, llama.cpp, LocalAI, LiteLLM), pluggable data sources, and - for actions - your own executor. The open core ships no real executor, so it cannot mutate anything until you wire one in.
Free and Apache-2.0. Not a SaaS. Not tied to any cloud, vendor, or monitoring stack.
See it work in under a minute
The instant demo runs against a synthetic production scenario with a stub model - no model download, no external services, no egress:
git clone https://github.com/bmoldo/tendwell
cd tendwell
docker compose up
You get a real health report immediately. The SLO evaluation and the cited runbooks are real; only the narrative is a stub until you add a model:
[CRITICAL] Production health
2 SLO(s) breached.
SLOs:
- availability [breached]: error_rate=0.057, healthy below 0.01
- latency [breached]: latency_p99=0.92, healthy below 0.5
Citations:
- error-rate-runbook.md
- latency-postmortem.md
For genuine model-driven narrative, add the Ollama profile - this pulls a small model once (a few hundred MB to ~1 GB, the honest one-time cost):
docker compose --profile model up
Then point it at your own stack: edit a config to use the Prometheus source and your local model. See the quickstart.
How it works
A deployment is one YAML file plus injected secrets; the code carries zero environment-specific values. Four layers sit behind stable interfaces, so you can swap any of them without touching the core:
- Data sources - where live signal comes from. Prometheus, Loki, and a
generic HTTP/JSON adapter today, normalized into one result shape. A failing
source degrades an SLO to
unknown; it never crashes the run. - LLM backend - any OpenAI-compatible endpoint via a configurable
base_url. Small models that are weak at native tool calls fall back to a prompt-based ReAct loop with strict parsing. - Context store - runbooks and postmortems embedded locally and retrieved by relevance. Citations come only from retrieved chunks, so the model cannot invent a source.
- Output / action surface - how findings are served and, only when you explicitly enable it, how gated actions are taken.
The agent is deliberately hybrid: a deterministic pre-fetch evaluates every SLO without the LLM, so even a weak model that fails every tool call still produces a correct status. The model adds interpretation and correlation on top.
The security model is the product
For a regulated buyer this is the part that matters. Mutating production runs through four separated stages, with a human and deterministic checks between the model and any change:
- Propose - the LLM emits a structured proposal. It records intent and executes nothing.
- Validate - deterministic checks (allowlist, argument schema, scope, rate limit, circuit breaker, kill switch) run before a human is ever paged.
- Approve - a human approves out-of-band, with identity and time captured. The model has no tool, endpoint, or path to approve.
- Execute - a separate, non-LLM executor acts per target, with write-scoped credentials held only for that run. Partial failure is first-class.
Read-only is the default and the open core ships no real executor: with no action surface configured, the agent is structurally unable to change anything. Audit logging is append-only, hash-chained, and cannot be disabled. See the security model.
Documentation
- Quickstart - zero to a working Tendwell.
- Configuration reference - every field and what is locked by design.
- Security model - the full version of the above.
- Bring your own LLM - any OpenAI-compatible runtime, plus the compatibility matrix.
- Add a data source - implement the
DataSourceinterface. - Register an executor - wire a real executor with the safety contract.
- Contributing.
- Deploy: a Helm chart and a Terraform module.
Development
uv sync --dev
uv run ruff check . && uv run ruff format --check .
uv run mypy tendwell
uv run pytest
License
Apache 2.0. See LICENSE. The free core stays genuinely capable; it is
never crippled to sell an upgrade.
Metadata
Release files for tendwell 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tendwell-0.0.1.tar.gz | 323.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tendwell-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 400.2 kB
Release files / tendwell-0.0.1.tar.gz
| Download URL | tendwell-0.0.1.tar.gz |
|---|---|
| Size | 323.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9a79cd0ecc71937ccacd7402c1c787333772b0eb1d252fa898ab06809dc1fd5d
|
|
BLAKE2b-256 checksum How to use checksums |
f3c53e348e1625be20f573f1d4fab49e74cee07b5828779629167476a6462e34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / tendwell-0.0.1-py3-none-any.whl
| Download URL | tendwell-0.0.1-py3-none-any.whl |
|---|---|
| Size | 76.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8561205fe73b208137139651d6f7837200bc39f25ba6b6c25c14366c40c6e735
|
|
BLAKE2b-256 checksum How to use checksums |
3120604eb13578a7b757bb2be498bbeec8fc24d4e693384dbc82a2dea950cc09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.18 {"installer":{"name":"uv","version":"0.11.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for tendwell 0.0.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.