# Centaur, a self-hosted Slack agent platform with two release trains

> A platform that answers in Slack and runs each conversation in its own Kubernetes sandbox, with a Rust control plane, Python tool plugins and 1Password-backed credential injection. The quickstart still points at one contributor's home directory.

**paradigmxyz/centaur** — Centaur is frontier, agentic infrastructure that you own. Centaur is like Claude Tag, but open source and on steroids.

- Repository: https://github.com/paradigmxyz/centaur
- Website: https://centaur.run
- Stars: 1,350 · Forks: 256
- Language: Python
- License: NOASSERTION
- Published: 2026-09-18 · Updated: 2026-09-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/paradigmxyz-centaur

## The expected checkout path is one contributor's home directory

The local setup section states the expected checkout path directly, and it is an absolute macOS home directory belonging to one person rather than a generic location:

```bash
/Users/magelinskaas/paradigmxyz/centaur
```

The clone instructions that follow do not fill in a real remote either:

```bash
git clone <repo-url>
cd centaur
```

So the one path in the document is a machine-specific leftover, and the command a first-time reader would paste still contains an unsubstituted placeholder. Neither line can be run as written, and there is no instruction anywhere in that section to replace the path with your own. It is a small thing, but it sits in the first-run path, which is exactly where a placeholder does the most damage: a reader who trusts it ends up with a directory that does not exist and a clone that points nowhere.

## Two release trains shipped within ninety minutes of each other

The release list is the clearest signal about how this project versions itself. On 2026-10-02 there is a tag named v2026.10.2 with the release title Centaur v2026.10.2 at 22:27 UTC, a tag named centaur-0.1.162 forty minutes earlier at 21:45, and centaur-0.1.161 another forty-eight minutes before that at 20:57. Two numbering schemes, a calendar version and a 0.1 patch line, published on the same evening within ninety minutes of each other.

Nothing in the file explains which one to track. The calendar tag reads like a release train and the 0.1 tags read like the package version, and for anyone automating a deploy the practical consequence is the same either way: there is no single obvious pin, so a deployment that tracks a branch name is taking a different risk than one that pins a tag and has to know which scheme the maintainers consider canonical. The three tags also share a day with the most recent commit, which means the release process is running continuously rather than on a schedule.

## Local boot wants 1Password, a Slack app, k3s and just before anything runs

The quickstart is short because it delegates the hard parts to four other tools. A command runner is installed through a package manager:

```bash
brew install just
```

A first local boot then needs five secrets exported into the shell:

```bash
export OP_SERVICE_ACCOUNT_TOKEN=...
export OP_VAULT=...
export SLACK_BOT_TOKEN=...
export SLACK_SIGNING_SECRET=...
export SLACKBOT_API_KEY=...
```

Two of those belong to 1Password rather than to Slack: the service account token lets the proxy resolve 1Password-backed runtime secrets, and the vault variable names the 1Password vault to read from. Three belong to Slack, and the file says which is which: the bot user OAuth token becomes the bot token, the signing secret verifies incoming requests, and the API key is what the Slackbot uses to call back into Centaur. The Slack app itself has to be created by hand at api.slack.com/apps. Once the variables exist they are turned into local Kubernetes secrets and the stack starts with `just bootstrap-secrets` followed by `just up`. Teams ingress is available too, behind a `teamsbot.enabled` flag, with its own app credentials.

## An optional static bearer token with full control plane access is one variable away

Two more environment variables sit alongside the five, and both are about authority rather than connectivity. `CENTAUR_APIRS_ADMIN_API_KEY` is described as an optional static bearer token with full access to api-rs, and `CENTAUR_JWT_SIGNING_SECRET` signs the short-lived Console and sandbox tokens that api-rs accepts. Both paths therefore exist: short-lived signed tokens, or one static key that bypasses them. That is a deliberate escape hatch for local work, and it is written down plainly enough that a deployment should decide which one it means.

The credential boundary is the other half. Agents are meant to use approved services without raw API keys in their environment, which is what the outbound proxy is for, and it works through the tool layer rather than the model. Tools are Python plugins, each a five-file directory:

```text
tools/my_tool/
├── __init__.py
├── client.py
├── cli.py
├── .env.example
└── pyproject.toml
```

Each runtime tool should declare a project scripts entry so that sandbox startup installs it as a local command shim, and agents find them with:

```bash
centaur-tools list
my-tool --help
```

Note the `.env.example` in every tool directory, sitting next to a design that keeps keys out of the sandbox. The two are reconciled by the proxy, but only if the tool actually routes through it.

## A Slack thread is the session key and the whole API is four endpoints

The API surface is small enough to read in one screen, and its shape explains the product. Four calls, all keyed on a thread key:

```text
POST /api/session/{thread_key}          # create or reuse a session
POST /api/session/{thread_key}/messages # store the user turn
POST /api/session/{thread_key}/execute  # start the agent
GET  /api/session/{thread_key}/events   # stream or replay output
```

Creating a session and storing a message are separate calls from starting the agent, which means a client can persist a turn before anything runs. The events endpoint both streams and replays, which is what makes the replayable state claim concrete: messages, executions, events and delivery state are stored, so a client that reconnects can pick up the same thread without losing the result. The session key being the thread is also why the Slack path needs no extra mapping layer.

Above those endpoints the platform takes on sandbox lifecycle, durable transcript storage, tool access, credential injection, workflow execution and final delivery. Workflows are Python functions with durable steps that can sleep, resume, wait for events and start child agents, and they survive service restarts, which is what lets recurring checks run without anyone watching.

## The control plane is Rust, the tools are Python and the packages are pnpm

The repository is polyglot in a way that the primary language field does not suggest. The control plane for agents, tools, workflows, auth and durable state is a Rust service at services/api-rs, alongside services/slackbotv2 for Slack events and delivery and services/sandbox for the agent container image and harness adapter. The outbound proxy sits in services/iron-proxy and documents itself elsewhere, at docs.iron.sh. Tool plugins are Python under tools/ and workflow plugins are Python under workflows/. On top of that sit crates/, packages/, harness/, plugins/, patches/, contrib/, a centaur_sdk directory and a tools.toml, with pnpm-workspace.yaml at the root and a root package.json that is private and pins pnpm 10.28.1 as its package manager.

So a contributor touches at least three build systems and a task runner, since the Justfile is what drives bootstrap and up. Two files at the root are unusual enough to notice: authors.txt, and a LICENSE file sitting next to a declared license that the repository metadata leaves unasserted, so which terms apply is not something this repository states unambiguously. Also worth knowing before reading the docs further is that the project presents itself as an open-source alternative to a hosted Slack agent product, which sets the expectation that it is a full platform rather than a library.

## Legacy HTTP tool routes are gone and compatibility runs through a generated bridge

One paragraph in the tools section is really a migration note. Workflow handlers can still invoke tools through a call on the context object, but the workflow host reaches them through a generated bridge named centaur-tools for that compatibility path. The next sentence is the actual change: api-rs does not expose the legacy HTTP tool-method routes as the current sandbox tool registry. In other words, an older integration that called tools over HTTP against the control plane no longer has a route to hit, and the supported path is the local command shim that sandbox startup installs from each plugin's project scripts entry.

That makes the plugin contract narrower than it looks. A tool is not an HTTP service with a schema, it is a Python package that declares a command, and the agent runs that command. It also means the `.env.example` convention sits oddly next to the credential boundary: the plugin is expected to describe its own environment, while the sandbox itself is supposed to receive no raw keys. Organization overlays are the stated answer for extending this without forking, letting a team layer in its own tools, workflows, personas, skills and prompts on top of the base platform, and shared tools are installed once and made available to every conversation.

## Conclusion

Centaur is worth reading if you want the Slack surface and the sandbox boundary and are willing to assemble the plumbing, because those two pieces are the actual product and the tool plugin format is small enough to extend in an afternoon. Two things decide whether it fits. The first is credential handling: outbound access goes through a proxy that injects secrets, and there is also an optional static bearer token with full access to the control plane, so the security model depends on which of those your deployment actually enables. The second is the release cadence, two tag trains shipping minutes apart on the same day, which means pinning to a tag rather than tracking a branch. Before starting, fix the checkout path in your own copy, since the one in the file is somebody's home directory.

## FAQ

### What is Centaur and who is it for?

It is a self-hosted agent platform for teams that want one shared agent rather than many one-off local setups. You talk to it in Slack, give it tools, and each conversation runs in an isolated Kubernetes sandbox with a shell, workspace, git, Python, Node.js and Bun.

### What does a local Centaur setup require?

A k3s cluster on a small always-on host rather than a production Kubernetes installation, the just command runner installed through a package manager, and five exported secrets covering a 1Password service account token and vault, a Slack bot token and signing secret, and the Slackbot API key. Then just bootstrap-secrets creates the local Kubernetes secrets and just up starts the stack.

### How does Centaur keep API keys away from agents?

Agents use approved services through controlled outbound access with credential injection by the proxy in services/iron-proxy, so raw API keys never land in the sandbox environment. Separately, an optional static bearer token in CENTAUR_APIRS_ADMIN_API_KEY gives full access to api-rs, alongside short-lived JWTs signed with CENTAUR_JWT_SIGNING_SECRET.

### What API does Centaur expose?

Four calls keyed on a thread key: create or reuse a session, store the user turn, start the agent, and stream or replay output through the events endpoint. Because state is stored, a client can reconnect to a thread without losing the result.

### How are Centaur tools written and discovered?

Tools are small Python plugins with __init__.py, client.py, cli.py, a .env.example and a pyproject.toml. Each one should declare a project scripts entry so sandbox startup installs it as a local command shim, and agents discover them with centaur-tools list.

## Sources

- [Issues](https://github.com/paradigmxyz/centaur/issues)
- [paradigmxyz/centaur on GitHub](https://github.com/paradigmxyz/centaur)
- [Project website](https://centaur.run)
- [README](https://github.com/paradigmxyz/centaur/blob/main/README.md)
- [Releases](https://github.com/paradigmxyz/centaur/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/paradigmxyz-centaur
