Witness kernel for agent tool compositions — diagnose, attest, seal
Project description
bulla
Witness kernel for agent tool compositions — diagnose, attest, seal.
When AI agents compose tools into pipelines, implicit semantic assumptions (date formats, unit scales, encoding schemes) can silently produce wrong results. Type-checking passes, but the pipeline is broken. Bulla computes the coherence fee: the exact number of independent semantic dimensions that bilateral verification cannot detect. For each blind spot, it recommends a bridge and issues a tamper-evident WitnessReceipt.
Zero heavy dependencies. Only requires PyYAML. No numpy, no scipy, no LLM calls. Installs in under a second.
Naming: Bulla is the protocol and tool. SEAM is the underlying theory (paper). Glyph is the company.
Install
pip install bulla
Architecture
Three layers, cleanly separated:
| Layer | Concern | Module |
|---|---|---|
| Measurement | Composition → Diagnostic (fee, blind spots, bridges) | diagnostic.py |
| Binding | Diagnostic → WitnessReceipt (content-addressable, tamper-evident) | witness.py |
| Judgment | Policy → Disposition (proceed / refuse / bridge) | witness.py |
The measurement layer has zero imports from the witness layer. Measurement does not know it is being witnessed.
Quick start
bulla diagnose --examples # run on bundled compositions
bulla scan "python my_server.py" # scan a live MCP server
bulla check compositions/ # CI gate (exit 1 on failure)
Python API
from bulla import (
BullaGuard, WitnessBasis, PolicyProfile,
diagnose, load_composition, witness,
verify_receipt_consistency, verify_receipt_integrity,
)
# Load and diagnose
comp = load_composition(path="pipeline.yaml")
diag = diagnose(comp)
print(f"Fee: {diag.coherence_fee}, Blind spots: {len(diag.blind_spots)}")
# Witness with provenance
basis = WitnessBasis(declared=3, inferred=1, unknown=0)
policy = PolicyProfile(name="strict", max_unknown=2)
receipt = witness(diag, comp, witness_basis=basis, policy_profile=policy)
print(f"Disposition: {receipt.disposition.value}")
# Verify
ok, violations = verify_receipt_consistency(receipt, comp, diag)
assert verify_receipt_integrity(receipt.to_dict())
BullaGuard (high-level)
guard = BullaGuard.from_mcp_server("python my_server.py")
guard.check(max_blind_spots=0) # raises BullaCheckError on failure
guard = BullaGuard.from_tools({
"parser": {"fields": ["amount", "currency"], "conventions": {"amount_unit": "dollars"}},
"engine": {"fields": ["amount"], "conventions": {"amount_unit": "cents"}},
}, edges=[("parser", "engine")])
MCP Server
Bulla exposes a JSON-RPC 2.0 stdio server with two tools and one resource:
bulla serve # starts MCP stdio server
bulla.witness— composition YAML → WitnessReceipt (structured output)bulla.bridge— composition YAML → patched YAML + receipt chainbulla://taxonomy— convention pack taxonomy
Convention Packs
Layered vocabulary for convention recognition. Later packs override earlier ones.
bulla diagnose --pack financial.yaml pipeline.yaml
bulla scan --pack custom.yaml "python server.py"
Ships with base (10 dimensions) and financial (4 domain-specific dimensions).
Witness Contract
Every receipt binds three hashes: composition (what was proposed), diagnostic (what was measured), receipt (what was witnessed). Receipts chain via parent_receipt_hash for auditable repair flows.
See WITNESS-CONTRACT.md for the normative specification.
CI Integration
# GitHub Actions with SARIF
- run: pip install bulla
- run: bulla check --format sarif compositions/ > bulla.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: bulla.sarif
Commands
| Command | Purpose |
|---|---|
bulla diagnose |
Full diagnostic with blind spots, bridges, fee |
bulla check |
CI gate with configurable thresholds |
bulla scan |
Scan live MCP servers (zero config) |
bulla witness |
Diagnose and emit WitnessReceipt as JSON |
bulla bridge |
Auto-bridge and emit patched YAML + patches |
bulla manifest |
Generate/validate Bulla Manifest files |
bulla serve |
MCP stdio server |
bulla init |
Interactive composition wizard |
bulla infer |
Infer proto-composition from MCP manifest |
Output formats: --format text (default), --format json, --format sarif.
How it works
Bulla builds a coboundary operator from tool dimensions to edge dimensions for both the observable and full sheaves. The coherence fee is:
fee = rank(δ_full) − rank(δ_obs)
Each unit of fee is an independent semantic dimension invisible to pairwise checks. Bridging increases rank(δ_obs) until it matches rank(δ_full). Rank computation uses exact arithmetic (fractions.Fraction) — no floating-point, no numpy.
License
MIT
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 bulla-0.15.0.tar.gz.
File metadata
- Download URL: bulla-0.15.0.tar.gz
- Upload date:
- Size: 127.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29c1e0caf7429d021b08b7aae168b968a0a1d5dae9acdf69eae82eab0f4101be
|
|
| MD5 |
d0cde980cd44ebdbea9b083626c6f5d2
|
|
| BLAKE2b-256 |
f9fc0a4c444a14ab5649f8a7eeb29b7a025488d663c41da577beb7365eee6dcc
|
File details
Details for the file bulla-0.15.0-py3-none-any.whl.
File metadata
- Download URL: bulla-0.15.0-py3-none-any.whl
- Upload date:
- Size: 67.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd5fa38d0d6e03a7473fc72395bc9687fdef414e2f973e1cd67d627241608f85
|
|
| MD5 |
1924be249c994209eec42caef2b341a5
|
|
| BLAKE2b-256 |
6265ab3fcbbca58c97131cff19da4fcd3c2877fef37464de2d123592bcfa01fd
|