Buddhi is the discriminative layer for autonomous agents: it decides when to act, how much effort a task deserves, when to stop, and when a human should decide.
Buddhi sits above the runtime that calls models and runs tools. It is a small, runtime-neutral kernel that allocates a bounded cognitive budget of model effort and human interruptions across a stream of work.
It neither executes nor schedules the work. It decides how much attention each item deserves, and whether the model or a person should make the judgment.
An agent runtime already knows how to invoke models and tools and drive a task to completion. What it usually lacks is a principled way to decide, before and during that work:
Left unmanaged, a supervisor over a stream of agent work fails in three common ways:
Buddhi is the layer that holds all three in check within one budgeting framework. It treats cognition (machine effort and human attention alike) as the scarce resource, and decides, per item, where that resource is spent or withheld.
The abstraction is easiest to see through a real adapter. Buddhi Review is a PR review-and-fix loop for Claude Code, built on this kernel. It maps each review finding into a kernel work item; the kernel returns a disposition, and the adapter translates that result into the matching review action: fix, ask, skip, or defer.
The division of labour is the point:
PR review is one adapter of the kernel, not the definition of Buddhi. The same interface is intended for other streams of agent work: an issue tracker’s comments, a task queue, an agent’s inbox. It applies wherever something must decide how much cognition each item deserves and when a human should step in.
The published package runs the demo directly, with no clone needed:
python -m pip install buddhikernel
python -m buddhi
The demo runs the reference implementation through the principal item-level and nested-stream
decision paths. A successful run prints SMOKE PATH OK and exits 0.
Six demonstrations, in order: Stage 0 conditioning; the seven decisions over one stream; the closure operator over a stream of streams; the two-tier exclusion lattice; the adapter contract; and the hierarchical budget (a shared pool vs. a partitioned one).
Clone to work on the kernel or run the test suite:
git clone https://github.com/buddhikernel/buddhi
cd buddhi
python -m pip install -e ".[test]"
python -m pytest tests/ -q
The kernel is pure standard library, with no runtime dependencies.
One controller, evaluate_item(), runs over each item and works through seven questions in
order, stopping at the first one that settles the item:
RESOLVED_OOB; if it does, evaluation ends without delivering the escalation.The controller lives in buddhi/closure.py as evaluate_item(); each decision is its own
module under buddhi/decisions/. The first decision that terminates returns one of seven
dispositions (decide_spend only annotates the item with an effort budget and never ends it):
| # | Decision (module) |
Terminal disposition |
|---|---|---|
| 1 | worth_acting |
DISCARDED |
| 2 | decide_spend (effort_model) |
— (annotates effort; does not terminate) |
| 3 | has_converged (convergence) |
CONVERGED |
| 4 | route_judgment (judgment_routing) |
MODEL_HANDLED |
| 5 | validate_and_ask (validity_and_ask) |
INVALID_ASK |
| 6 | check_oob_resolution (oob_resolution) |
RESOLVED_OOB |
| 7 | aggregate_budget |
ESCALATED or DENIED |
A deferred decision is represented as a business question: the kernel pre-reasons it into the options above rather than emitting a bare yes/no prompt. Step 7 also enforces a two-tier source-exclusion lattice (an excluded source is denied before the graduated admission bar is consulted), and step 3 keeps transient failures in a bounded-retry class that is excluded from convergence accounting. The rationale for each decision is in docs/decisions.md.
Buddhi reuses the same controller at two levels. At the item level, it decides how much attention one item receives. At the parent level, it treats a child stream as an item and decides how much budget that whole stream receives. The project calls this composition the closure operator, and it is the centre of the design.
In code, supervise_stream() runs evaluate_item() over the items of one stream, and
supervise_stream_of_streams() runs the identical evaluate_item() over each child stream
viewed as an item (Stream.as_item()). When a child comes back MODEL_HANDLED, the parent has
granted it budget, and the operator recurses into that child’s own items.
Budget allocation recurses; task coordination does not. The kernel accounts budget across children through the shared Store, but it does no inter-stream coordination, conflict avoidance, work partitioning, or locking. Coupled items, where acting on one changes whether another is worth acting on, need a separate layer above the kernel.
The budget itself is a tree of scopes: a parent’s ceiling bounds the combined spend of its whole subtree. With a single scope, the tree reduces to one shared budget and one admission bar, and the reference pack runs exactly that case. The mechanics, the invariants, and the reduction are in docs/budget.md.
The kernel is orchestration and depends on five interfaces, the seams; it ships no production implementation of any of them. Domain adapters provide the real implementations. The repository includes reference implementations (the naive pack) that run the demo and tests end to end; they provide only minimal behaviour, not production policy.
| Seam | Interface | Feeds |
|---|---|---|
| PolicyPack | one runtime-neutral policy source: taxonomies, thresholds, phrasings, predicates | every decision, and Stage 0 |
| Router | recommend(item) -> RouterPick(model, effort) |
decide_spend |
| Store | scope-keyed interrupt counters and a two-tier source-exclusion lattice | aggregate_budget |
| EscalationTransport | deliver(ask) |
validate_and_ask |
| OOBSource | can_observe_oob() -> bool |
check_oob_resolution |
Stage 0 (condition()) is a one-time pre-pass that turns raw input into the typed items the
loop consumes. It is anticipatory: it shapes the stream so a class of demand never becomes
items at all, where the seven decisions are reactive and spend the budget. The kernel ships a
1:1 identity pass-through.
The rationale for why each decision and seam sits where it does is in docs/decisions.md.
An adapter connects the kernel to a concrete runtime or domain. It supplies the substrate’s I/O
and lets the kernel make every decision. The contract in buddhi.adapter has four operations:
| Operation | Does |
|---|---|
ingest() |
yield the substrate’s items (an issue tracker’s comments, a task queue, an inbox) |
run_embedded(item, budget) |
hand one item to the kernel and return its disposition |
escalate_async(ask) |
deliver the pre-reasoned ask through the EscalationTransport seam |
detect_resolved(item) |
report whether the item was resolved out of band |
To run the kernel on a new domain, supply a PolicyPack and implementations of Router, Store,
EscalationTransport, and OOBSource. The worked reference is buddhi/reference/naive_pack.py
(NaiveAdapter), and the step-by-step is in docs/extending.md.
Buddhi is alpha; the API may change before 1.0. The honest split of what is demonstrated
versus asserted is in docs/claim-and-bound.md.
In the Samkhya and Vedanta traditions of faculty psychology, the mind has two functions. Manas is the deliberating faculty: it takes in what the senses report and forms and considers possibilities. Buddhi is the faculty that settles the matter; its defining act is determination or ascertainment. Manas proposes; buddhi decides.
A generative model is manas-like: it generates candidate interpretations and actions. Buddhi supplies the determinative layer, deciding what merits action, how much further effort to allocate, when the matter is settled, and when human judgment is required.
The design also follows Herbert Simon’s bounded rationality: cognition is scarce, so an agent must allocate it according to marginal value rather than attempt exhaustive optimization. Buddhi makes that allocation explicit and runnable. Read more in The name and the vision.
Start here
Go deeper
python -m buddhi).Reference
Positioning and building on it
Apache-2.0. See LICENSE. To cite Buddhi, see CITATION.cff or the archived release (DOI).