An installable Python pipeline runtime that enforces software-build discipline at the dispatch boundary.
Project description
Bonfire
An installable Python pipeline runtime that enforces software-build discipline at the dispatch boundary. Define agents. Wire stages. Ship quality.
Alpha —
v0.1.0a2(install withpip install --pre bonfire-ai)This is the first functional release of
bonfire-ai. The pipeline engine, the role-bound cadre, the quality gates, the persona system, and thebonfire scanonboarding flow are wired and exercised by the test suite. An in-memoryVaultBackendships as the default knowledge store; a LanceDB-backed implementation is available behind thebonfire-ai[knowledge]extra. The CLI verb that drives the engine end-to-end (bonfire run), the bundled prompt-template directory, and the persistent knowledge-graph storage are deferred to later 0.1.x releases. The frame is shipped; some operations are deliberately not.If you are an early adopter, run it against a throwaway repo, file issues at github.com/BonfireAI/bonfire/issues, and tell us where it bites. The vocabulary, the protocols, and the config schema are stable for 0.1.x.
What Bonfire Is
Bonfire is a layer of good software-developing practices that wraps
your already-AI-assisted workflow. You pip install it; your agents
suddenly know they have nine roles talking to each other for quality.
Each agent has a static axiom of rules and an injected handoff from the prior agent. That isolation is the whole point: every role gets the best of the LLM by being asked one focused thing at a time, with exactly the context it needs and nothing else.
The discipline is structural, not advisory. The role that writes failing tests cannot edit implementation. The role that writes implementation cannot edit tests. The reviewer is read-only. A typed envelope passes between stages; a quality gate decides whether each handoff moves forward, retries once, or stops the pipeline. Source code is the deliverable.
Quick Start
pip install --pre bonfire-ai # --pre required: alpha until 0.1.0 ships
The PyPI package is bonfire-ai; the installed console script is
bonfire. Python 3.12+ is required.
# Initialize a project. Creates four artefacts under the target directory:
# - bonfire.toml (project config; minimal stub `[bonfire]`)
# - .bonfire/ (per-project state directory)
# - agents/ (role-local prompt + identity-block overrides; see Extension Points)
# - .gitignore entry: `.bonfire/tools.local.toml` (appended if missing;
# idempotent — re-running `bonfire init` does not duplicate the line)
bonfire init .
# Launch the browser-based onboarding scan
# (pass `--conversation-timeout SECONDS` to extend the default 5-minute cap,
# or `--conversation-timeout 0` to wait indefinitely)
bonfire scan
# Inspect cumulative cost and recent sessions
bonfire cost
# List installed personas
bonfire persona list
Available subcommands in v0.1.0a2: init, scan, status, resume,
handoff, persona, cost. Run bonfire --help for the full surface
or bonfire <command> --help for any single command.
Architecture Overview
A Bonfire pipeline is an ordered sequence of stages. Each stage
dispatches an agent of a specific AgentRole (researcher, tester,
implementer, verifier, publisher, reviewer, closer, synthesizer,
analyst). Between stages, QualityGate instances inspect the
envelope and decide whether to proceed, retry once, or stop.
The TDD contract is enforced at the role boundary: the tester writes failing tests that define the contract (RED), the implementer writes code to pass them (GREEN), and the verifier runs an independent quality check before the publisher opens a PR. The reviewer can bounce work back into the loop until it passes or the budget is exhausted. The closer seals the work — merges the PR, posts the completion, closes the ticket — only after every gate has cleared.
Bring your own provider key. Pick the model per role. Models are
resolved through resolve_model_for_role, which maps each
AgentRole to a capability tier (reasoning, fast, or balanced)
and returns the corresponding provider model string from your
config. Pure synchronous resolution; never raises on a string input.
The Cadre
Bonfire ships nine role-bound agents; the runtime picks how each one
runs. Four dispatch through an LLM agent backend; three are
deterministic stage handlers wrapping gh / git / pytest with no
LLM call at all; one combines synthesis with a bounded correction
step; one is opt-in pre-pipeline architectural analysis. The cadre is
fixed in source as a StrEnum and rendered through three name
layers — the generic identifier, the professional display name, and
the gamified display name.
Naming Glossary
The generic concept describes what the role does. The
professional name (AgentRole) is the canonical serialized form
used in TOML, JSONL, CLI output, and grep patterns. The gamified
name is a workflow alias emitted by the standard and research
workflow templates and normalized through GAMIFIED_TO_GENERIC
before tier lookup.
| Generic Concept | Professional (AgentRole) |
Gamified (workflow alias) |
|---|---|---|
| Investigates the task and gathers context | researcher |
scout |
| Writes failing tests (TDD RED) | tester |
knight |
| Writes code to pass the tests (TDD GREEN) | implementer |
warrior |
| Independent quality verification | verifier |
cleric |
| Creates branches, commits, opens PRs | publisher |
bard |
| Code review with structured verdicts | reviewer |
wizard |
| Merges approved PRs and announces completion | closer |
steward |
| Combines multiple reports into unified analysis | synthesizer |
sage |
| Architectural and structural analysis | analyst |
architect |
The string prover appears in the standard_build pipeline as a
stage label; that stage dispatches to the verifier role. Stage
labels name DAG nodes inside a workflow plan; display names are the
persona-emitted role names in CLI output.
Note — Falcor is a persona, not a role. The cadre is the nine roles above. The persona is what speaks for them at the CLI surface. See Personality below.
The Vault
Alongside the cadre, the Vault is the named knowledge store of
Bonfire's world — capitalized, personified in display vocabulary,
narrated by the persona at lifecycle moments (The Vault remembers,
The Vault gives back). The Vault is not an agent; it is never
dispatched and has no role. Today the VaultBackend Protocol is
published and an in-memory default backend ships (substring
matching, no embeddings, no external dependencies — suitable for
tests and small projects). A LanceDB-backed implementation is
available behind the bonfire-ai[knowledge] extra; the persistent
knowledge-graph storage layer lands in a later 0.1.x release.
Config Reference
Bonfire reads bonfire.toml from the current working directory.
Settings priority is: constructor kwargs → environment variables
(BONFIRE_ prefix, __ nested delimiter) → bonfire.toml → field
defaults.
A minimal complete config showing every section and its real defaults:
# bonfire.toml
[bonfire]
tier = "free" # commercial tier
model = "claude-sonnet-4-6" # default model when no role match
max_turns = 10 # per-agent turn cap (must be > 0)
max_budget_usd = 5.0 # per-pipeline budget cap (>= 0)
persona = "falcor" # CLI output persona
trust_project_settings = false # opt-in: ingest CLAUDE.md / .claude/ (see Security)
[models] # bring your own provider key — strings live here
reasoning = "claude-opus-4-7" # researcher, reviewer, synthesizer, analyst
fast = "claude-haiku-4-5" # tester, implementer, verifier, publisher, closer
balanced = "claude-sonnet-4-6" # fallback for unknown role strings
[memory]
session_dir = ".bonfire/sessions"
context_file = ".bonfire/context.json"
[git]
auto_branch = true
auto_commit_on_green = true
require_pr = true
The [models] section holds the strings Bonfire passes verbatim to
the agent backend. To use a different provider, swap the strings to
that provider's model identifiers and plug in a matching
AgentBackend (see Extension Points below).
Trusting Project Settings (security)
Bonfire dispatches agents with the Claude Agent SDK, which can ingest
the project's CLAUDE.md and .claude/settings.json into the agent's
system prompt and hook table. Bonfire defaults to deny: a foreign
repo's project settings are NOT loaded unless one of these holds:
bonfire.tomlcontains[bonfire] trust_project_settings = true(literal boolean — strings and ints are ignored).- The environment variable
BONFIRE_TRUST_PROJECT_SETTINGS=1is set (operator escape hatch, strict equality on the value"1"). - The dispatch
cwdis empty /None(in-tree dogfood path).
Why this matters: a malicious clone could otherwise plant instructions
in its CLAUDE.md or wire hostile hooks in .claude/settings.json
that would silently land in any agent you dispatch from inside that
repo. Opt-in is required.
Per-Role Model Routing
resolve_model_for_role(role, settings) -> str is the public
primitive. Given a role string (canonical or gamified) and a
BonfireSettings, it normalizes the input, looks up the canonical
AgentRole, maps that role to a ModelTier, and returns the
provider model string for that tier from settings.models.
The default role-to-tier mapping:
AgentRole |
ModelTier |
|---|---|
researcher |
reasoning |
tester |
fast |
implementer |
fast |
verifier |
fast |
publisher |
fast |
reviewer |
reasoning |
closer |
fast |
synthesizer |
reasoning |
analyst |
reasoning |
If the input string matches neither a canonical AgentRole nor a
gamified alias, the resolver falls back to ModelTier.BALANCED and
returns settings.models.balanced. The function never raises on a
string input — unknown roles degrade to the balanced model rather
than failing the dispatch.
Personality (Optional)
Bonfire ships persona-driven CLI output. The persona affects display only — it never enters agent prompts and never changes quality standards. The cadre is what runs; the persona is what speaks.
The default persona for v0.1.0a2 is Falcor — gentle,
encouraging, warm. The friend who tells you not to let it
end.[^falcor] Falcor narrates pipeline events, greets you on
bonfire scan, and names lifecycle moments of the Vault.
Two other personas ship for users who want neutral output:
default (professional) and minimal (terse, CI-friendly).
# Inspect installed personas
bonfire persona list
# Switch the default for this project (writes to bonfire.toml)
bonfire persona set default
The persona is configured per project via bonfire persona set <name>;
there is no per-command override flag in v0.1.0a2. A per-command
override lands when the narration/output layer grows persona awareness in
a later 0.1.x release.
Custom personas live in ~/.bonfire/personas/. The persona slot is
user-extensible: name your own assistant, write a phrase bank, drop
it in the directory.
A breadcrumb: Falcor refactors a slot earlier occupied by a
predecessor named Passelewe. History is sacred — see
docs/_lore/passelewe.md if you want the lineage.
[^falcor]: Yes, that Falcor — the luckdragon, The Neverending Story (1984).
Extension Points
Four @runtime_checkable Protocols define Bonfire's pluggable
boundaries. The composition root verifies conformance at registration
time, so any object with the matching shape works — no inheritance
required.
from typing import Protocol, runtime_checkable
from bonfire.protocols import (
AgentBackend,
DispatchOptions,
QualityGate,
StageHandler,
VaultBackend,
VaultEntry,
)
AgentBackend — swap the LLM provider that executes a single
agent turn.
@runtime_checkable
class AgentBackend(Protocol):
async def execute(
self, envelope: Envelope, *, options: DispatchOptions
) -> Envelope: ...
async def health_check(self) -> bool: ...
VaultBackend — swap the persistent knowledge store. Embedding
is internal to the backend; callers pass text, never vectors.
@runtime_checkable
class VaultBackend(Protocol):
async def store(self, entry: VaultEntry) -> str: ...
async def query(
self, query: str, *, limit: int = 5, entry_type: str | None = None
) -> list[VaultEntry]: ...
async def exists(self, content_hash: str) -> bool: ...
async def get_by_source(self, source_path: str) -> list[VaultEntry]: ...
QualityGate — custom pass/fail logic between pipeline stages.
@runtime_checkable
class QualityGate(Protocol):
async def evaluate(
self, envelope: Envelope, context: GateContext
) -> GateResult: ...
StageHandler — custom stage orchestration when an agent
dispatch is the wrong shape (parallel fan-out, human-in-the-loop,
external APIs).
@runtime_checkable
class StageHandler(Protocol):
async def handle(
self,
stage: StageSpec,
envelope: Envelope,
prior_results: dict[str, str],
) -> Envelope: ...
The full persistent Vault knowledge-graph implementation lands in a
later 0.1.x release. The protocol is stable today; the in-memory
default backend ships today and a LanceDB-backed implementation is
available behind the bonfire-ai[knowledge] extra.
What's Not There Yet
Honest list, because alpha means alpha:
- There is no
bonfire runcommand. The library works —from bonfire.engine import PipelineEngineandawait engine.run(plan)drives a real pipeline against a real backend — but the CLI verb that wires the engine end-to-end is deferred tov0.1.1. The shipped subcommands (init,scan,status,resume,handoff,persona,cost) cover onboarding, persona, and cost;status/resume/handoffprint one-line stubs for now. - The bundled prompt-template directory ships a
.gitkeepand nothing else. The cadre's prompt-layer identity is contributor-supplied today. Default identity blocks for the LLM-dispatching roles (Scout, Knight, Warrior, Wizard) come in a later 0.1.x release. - The persistent Vault knowledge-graph is not yet shipped. The
VaultBackendProtocol is stable and an in-memory default backend ships today (substring matching, no embeddings); the knowledge-graph storage and query implementation lands once the schema is locked. - No downstream surface imports the package today. Wrappers and vertical surfaces are designed against the engine but not yet wired to it. The release-gate Box validates the artifact contract, not the orchestration capability.
The v0.1.0aN alpha series reserves the name on PyPI and ships the
frame. Later 0.1.x releases ship the verb, the bundled prompt
templates, and the persistent Vault knowledge-graph. The under-claim
is the feature.
Roadmap
What's coming next, in rough order:
bonfire run— the CLI verb that drives the engine end-to-end. Deferred tov0.1.1.- Bundled prompt-template identity blocks for the four LLM-dispatching cadre roles.
- Persistent Vault knowledge-graph — the durable storage and
query implementation behind the
VaultBackendProtocol (today's default is in-memory; LanceDB is available behind thebonfire-ai[knowledge]extra). - Multi-forge support via the Instruction Set Markup (ISM) seam —
declarative third-party tool integrations replacing today's
hard-coded
gh-only forge calls. - Additional public products — Bonfire is the first; more open repos will follow.
Project
Bonfire is developed at github.com/BonfireAI. Issues, PRs, and discussion welcome.
License
Apache-2.0.
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 bonfire_ai-0.1.0a3.tar.gz.
File metadata
- Download URL: bonfire_ai-0.1.0a3.tar.gz
- Upload date:
- Size: 886.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5a1759e8e4fae9f9fe8b90937089bfb83d0d37acd91289daf95d59162aa72ee8
|
|
| MD5 |
26a005a2cd122e53c40c86e9fb1e6a7d
|
|
| BLAKE2b-256 |
3539966cbfeb60ec616fab5fcbbb417d29557f72687d7f86159c45c48a6a3709
|
Provenance
The following attestation bundles were made for bonfire_ai-0.1.0a3.tar.gz:
Publisher:
release.yml on BonfireAI/bonfire
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bonfire_ai-0.1.0a3.tar.gz -
Subject digest:
5a1759e8e4fae9f9fe8b90937089bfb83d0d37acd91289daf95d59162aa72ee8 - Sigstore transparency entry: 1553910007
- Sigstore integration time:
-
Permalink:
BonfireAI/bonfire@fb0af20e704096e29703a7a57a11d6b7e1108fbd -
Branch / Tag:
refs/tags/v0.1.0a3 - Owner: https://github.com/BonfireAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fb0af20e704096e29703a7a57a11d6b7e1108fbd -
Trigger Event:
push
-
Statement type:
File details
Details for the file bonfire_ai-0.1.0a3-py3-none-any.whl.
File metadata
- Download URL: bonfire_ai-0.1.0a3-py3-none-any.whl
- Upload date:
- Size: 313.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad7326b1d56bec2b392dab30e4b986c536876d00671d092ab8ebadcd65a17df0
|
|
| MD5 |
a712fd9c9ff1e358f5e844a786337302
|
|
| BLAKE2b-256 |
a2527ca227121fd0ce01f83fb05dfbc57b9ff412c9abb73d62590d093521a5e1
|
Provenance
The following attestation bundles were made for bonfire_ai-0.1.0a3-py3-none-any.whl:
Publisher:
release.yml on BonfireAI/bonfire
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bonfire_ai-0.1.0a3-py3-none-any.whl -
Subject digest:
ad7326b1d56bec2b392dab30e4b986c536876d00671d092ab8ebadcd65a17df0 - Sigstore transparency entry: 1553910009
- Sigstore integration time:
-
Permalink:
BonfireAI/bonfire@fb0af20e704096e29703a7a57a11d6b7e1108fbd -
Branch / Tag:
refs/tags/v0.1.0a3 - Owner: https://github.com/BonfireAI
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@fb0af20e704096e29703a7a57a11d6b7e1108fbd -
Trigger Event:
push
-
Statement type: