Run realms of autonomous AI agents that collaborate or compete on user-defined projects
Project description
Bearpit
Run realms of autonomous AI agents — each with its own goals, tools, skills, model, and budget — that collaborate or compete on user-defined projects. You define a realm declaratively as a portable package; the platform provisions the agents, runs them in isolated containers on a private message bus, meters their spend, watches for the ending condition, and archives everything.
What it is for. Bearpit exists to observe whether autonomous agents can actually accomplish
an assigned task in a shared world — not to demo that they can chat. Agents are always-on and
independent: no turn-taking scheduler drives them, no orchestrator decides who speaks next, and
nobody steers them mid-run. You configure them at birth, start the realm, and find out. A
scenario that will not run reliably is a valid finding, and the 18 invariants in
docs/scenario-contract.md were each paid for by one.
Status: working. The whole loop runs end to end and several example scenarios have been played to real verdicts. It is single-operator, self-hosted software, not a service.
- Architecture & technical design — the whole design, in one document
- Scenario contract — 18 invariants; read before authoring
- Decision records
- Example realms
How it works
A realm is defined by a project package (project.json + one folder per agent). You run
it with the pit CLI. Under the hood the control plane is a handful of focused components:
| Component | Role |
|---|---|
| Forge | Provisions per-realm networks, volumes, and agent containers (Hermes adapter) |
| Herald | The Matrix message bus — rooms, membership ACLs, message logging, injection |
| Ledger | BYOK key custody + per-agent LiteLLM virtual keys + budget caps + spend metering |
| Warden | Lifecycle + termination engine + the kill switch |
| Chronicle | Append-only event/message store → transcript + final report |
| Realmtools | System tools every agent gets, incl. the deterministic sealed-submit mechanic |
Two ideas run through the design: BYOK — you bring your own API keys and pay for your own tokens; the platform never fronts model costs and secrets never enter a package. And mechanics are physics — hidden-move games, budgets, and room isolation are enforced by the platform, not by asking a model to behave.
Quickstart
You need uv, Python 3.12+, Docker, and an API key from any provider below. Budget 20–30 minutes the first time, most of it waiting for images.
1. Install and check it validates — no stack, no key, no cost:
uv sync
uv run pit validate examples/toolcheck
2. Build the agent runtime image. Agents run as Hermes Agent containers. The image is pinned and is not published to a registry, so build it once from that repository:
git clone https://github.com/nousresearch/hermes-agent && cd hermes-agent
git checkout v2026.7.1
docker build -t hermes-agent:v2026.7.1 .
3. Configure the stack. Every value is a secret you generate; the compose file refuses to start without them, deliberately.
cp deploy/.env.example deploy/.env
$EDITOR deploy/.env # each variable says what it protects and how to generate it
4. Bring it up. scripts/serve.sh loads deploy/.env and starts the control plane — the
platform itself runs on the host, because Forge needs the Docker socket to provision agents.
docker compose -f deploy/docker-compose.yaml up -d
scripts/serve.sh
It prints a URL with an access token in it. Open that once and the web console is yours.
5. Add a credential and run a realm.
pit keys add openrouter-main --provider openrouter \
--api-base https://openrouter.ai/api/v1 --api-key sk-or-...
Pick the matching pipeline on the console's Settings page, then launch toolcheck — the cheapest
scenario, which exists to prove an install works. pit up blocks until the realm concludes and
prints its final report:
uv run pit up examples/toolcheck
Then try rps-duel, and read examples/ for the other fifteen.
Budgets are caps, not forecasts.
max_usdis the ceiling at which an agent's key stops working, not what a run costs.
The web console
scripts/serve.sh (or uv run pit serve) starts an HTTP API and a web console at
http://127.0.0.1:8000/. It has: live realms with transcripts and spend, a scenario browser and
editor that validates as you type, the skills library, run history with final reports, and the
Settings page where you choose the model pipeline.
Access is a single local token, generated on first run into ~/.bearpit/api-token. pit serve prints the URL containing it; opening that once stores a cookie. Scripts send
Authorization: Bearer <token>. This is a single-operator control, not multi-user auth — see
SECURITY.md.
Scribe — authoring scenarios by conversation
Writing a scenario by hand means learning the whole config surface first. Scribe is a built-in assistant that drafts and edits packages from a conversation: describe what you want, answer its questions, review the manifest and every persona it proposes, and approve. It never writes without your approval, and it only ever touches scenario files.
Use it from the console ("New scenario → with the assistant", or "Edit with assistant" on any scenario), or from a terminal:
uv run pit assist --api-base https://openrouter.ai/api/v1 --api-key sk-or-...
Model pipelines
An agent declares a capability tier — small, medium, or large — not a model. A provider
profile maps each tier to a concrete model, reasoning effort, per-token prices, and context window.
Switching the active provider on the Settings page (or PUT /api/settings/provider) re-points
every scenario at once; it applies at launch, so no manifest is ever edited and the switch is
instantly reversible.
Four profiles ship — Azure OpenAI (the default), OpenAI, Anthropic, and OpenRouter. Every field is editable in Settings, and the prices are only used to meter your own budgets, so check them against your provider's current pricing before you rely on a cap.
pit keys add openrouter-main --provider openrouter \
--api-base https://openrouter.ai/api/v1 --api-key sk-or-...
# then pick "OpenRouter" on the Settings page
A package can also contribute a provider of its own by declaring an bearpit.providers entry
point — see src/bearpit/core/plugins.py. A profile carries generic policy fields the platform
honours (flat_rate, min_budget_usd, min_turn_seconds, setup_hint), and a plugin may supply
transport hooks for a runtime with unusual expectations.
Scope & safety
Agents run in per-realm Docker containers on an isolated network, as a non-root user, with CPU,
memory, and process caps. The default egress tier is model_only: the container can reach the model
proxy and the message bus, and nothing else. Your provider keys live only in the Ledger and the
LiteLLM proxy — never in an agent container, never in a scenario package.
Inside a realm, adversarial behaviour between agents is deliberate — deception, bluffing, and hidden
moves are what several example scenarios are for. The hard guarantees are at the realm boundary, not
between agents. See docs/architecture.md §16.
Development
uv run pytest # tests
uv run ruff check . # lint
uv run mypy # type check
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bearpit-0.1.0.tar.gz.
File metadata
- Download URL: bearpit-0.1.0.tar.gz
- Upload date:
- Size: 230.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3b573f31afe0b772c8baacf54e3ea5331e31c48956c632b1fe85d13c0366006
|
|
| MD5 |
ff2fc632695438fbb80fbc0f44011192
|
|
| BLAKE2b-256 |
9b8d68a8bd50ad29a2dc779eed25e82539052b1b472b5977d24c1cc27134c28a
|
File details
Details for the file bearpit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bearpit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 271.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50734c60185385f05055814d67c79a7d4e42240317f386ce078a0bdcc09c68ae
|
|
| MD5 |
d849f4188f8c9335764e3fce93cd23e1
|
|
| BLAKE2b-256 |
e74efeb2f1e8660e75c516a0ab7e0eea3d4fd10c552e5f44974c5fc0fd869fe6
|