mcpField
B
bound

bound

github.com/danny-de-breeAgent workflows755 installsUpdated 14w ago
Repository

About bound

bound is an execution-evaluation tool for coding agents. At meaningful task boundaries, it assesses completed work and recommends continuing, retrying, replanning, or rolling back; its integrations are instruction-based and do not enforce actions.

Key features

  1. 01Evaluate completed steps
  2. 02Recommend four control actions
  3. 03Track evidence and provenance
  4. 04Keep append-only decision lineage
  5. 05Provide instructions for several agents

Use cases

  1. 01Decide whether to continue after verification
  2. 02Replan when evidence is insufficient
  3. 03Compare current and historical evaluations

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/danny-de-bree/bound --skill bound

After installing, type/boundin Claude Code to confirm it loaded.

Bundled filesagents/openai.yamlreferences/integration-report.md

Details

From the project README

BOUND

Use BOUND after meaningful execution steps to decide whether the agent should continue, retry, replan, or roll back. BOUND evaluates completed work; it does not decide what code to write.

Agent integration types

All BOUND agent integrations are instruction-only — they are prompts that the agent reads and follows. There are no enforced integrations (no programmatic hooks into the agent's event system, MCP servers, rules, or lifecycle events). Every integration relies on the agent to voluntarily follow the instructions and act on BOUND's decisions.

AgentFileTypeMechanism
Clineintegrations/cline/INSTALL_BOUND.mdInstruction-onlyPrompt-based; agent follows instructions
Codexintegrations/codex/INSTALL_BOUND.mdInstruction-onlyPrompt-based; agent follows instructions
Claude Codeintegrations/claude-code/INSTALL_BOUND.mdInstruction-onlyPrompt-based; agent follows instructions
Hermes Agentintegrations/hermes-agent/INSTALL_BOUND.mdInstruction-onlyPrompt-based; agent follows instructions
Kilo Codeintegrations/kilo-code/INSTALL_BOUND.mdInstruction-onlyPrompt-based; agent follows instructions
Genericintegrations/generic/INSTALL_BOUND.mdInstruction-onlyPrompt-based; any agent follows instructions

Key distinction: Instruction-only integrations describe the BOUND control loop and instruct the agent to manually call BOUND's CLI or Python API at each boundary. The agent is responsible for acting on the decision — BOUND does not enforce the action. Enforced integrations (future) would hook into the agent's event system to intercept decisions before they reach the agent.

Inspect before integrating

  1. Install the latest stable package into the project's environment:

    pip install bound-policy
    
  2. Inspect the installed API instead of relying on remembered signatures:

    python -c "import bound; print(bound.__version__); print(bound.__all__)"
    bound integration-spec
    
  3. Confirm the project's real test, lint, type-check, and build commands.

  4. Inspect the agent's actual hooks, modes, instructions, commands, task boundaries, telemetry, and checkpoint support. Do not invent a native BOUND integration or an undocumented framework mechanism.

  5. Find existing INTEGRATION.md, INTEGRATION_REPORT.md, PLAN.md, and bound_integration/ files. Treat recorded results as claims to reproduce, not authoritative evidence.

Establish execution lineage

For multi-step work, maintain PLAN.md at the repository root. A small one-step task may use an inline plan. Give each meaningful phase a stable id and define its goal, observable acceptance checks, risk checks, verification commands, budget, expected artifacts, owner, and dependencies where relevant.

Maintain this lineage:

intent -> plan phase -> StepContract -> execution -> ExecutionEvidence
       -> BOUND evaluation -> control action -> integration report

Preserve a phase after execution. When the strategy changes materially, create a derived id such as PHASE-002-R1; do not rewrite history to hide a replan.

Choose meaningful boundaries

Call BOUND after implementation plus verification, after a focused retry, and before deciding to keep refining the same objective. Do not call it after each token, file read, shell command, or low-level tool call.

Each boundary must have observable completion criteria. Combine or redefine a step when no meaningful success or risk signal can be observed.

Report the proposal before modifying the project

Record these headings before implementation:

Integration point:
Step boundary:
Available evidence:
Missing evidence:
Control-flow mapping:
Files to modify:

List exact verification commands and the small, removable set of integration files. Represent unavailable metrics as unavailable rather than estimating them.

Build contracts and evidence

Map each phase to a StepContract with at least one AcceptanceCheck, optional RiskChecks, expected artifacts, and a StepBudget. Collect ExecutionEvidence only from observations made during the run: command exit codes, check results, changed artifacts, retries, tool calls, tokens, runtime, and rollback availability when exposed.

Keep check_id values aligned between contract and evidence. Missing evidence for a required check is not a pass. Distinguish an unset budget (None), an unavailable measurement, and an observed zero.

Prefer the installed evaluate_agent_step(...) helper when its inspected API provides it. Otherwise call BoundWorkflow.evaluate_step(...) and use exactly:

ACCEPT   -> continue
RETRY    -> retry
REPLAN   -> replan
ROLLBACK -> rollback

Never add a fifth action or reproduce BOUND's scoring and decision formula.

Verified evidence & provenance (v0.7.0)

BOUND v0.7.0 separates who reports evidence from who verifies it. The agent is a participant, not the judge.

  • Define the contract upfront, including provenance requirements. Each AcceptanceCheck / RiskCheck may declare accepted_provenance (which trust provenances it accepts), on_missing, on_claimed, and — for risk checks — decision_critical (missing/claimed evidence then forces INSUFFICIENT assurance and blocks a clean ACCEPT).

  • Configure allowed collectors; BOUND performs objective verification. Use the BOUND collectors (PytestCollector, GitCollector, JUnitCollector, BudgetCollector, ProcessRuntimeCollector, CommandCollector, plus native RuffEvidence, MypyEvidence, CoverageEvidence) to execute verification BOUND controls. They record evidence.collected audit events with VERIFIED/OBSERVED provenance, a collector name/version, artefact hash and a timezone-aware timestamp. A collector crash or stale artefact is recorded honestly (evidence.collection_failed / INVALID), never a verified pass.

  • The agent CANNOT assign VERIFIED provenance. Agent self-report is always CLAIMED, never VERIFIED/OBSERVED. The agent must not override or suppress a collector result. MISSING means "not collected" — never silently 0; None on a telemetry metric is missing, not a measured zero.

  • Subjective criteria use a separate evaluator (EVALUATED). Criteria that cannot be independently re-run (e.g. UX quality) are EVALUATED — honest but never VERIFIED.

  • BOUND logs what the agent reports; the agent executes control actions. BOUND records action.reported (reported_provenance=CLAIMED); an independent hook may add observed_action to confirm it. The agent executes control actions. BOUND is a thin harness: it emits ROLLBACK and may independently verify the resulting state. It can roll back the workspace with explicit bound rollback --execute against a previously confirmed checkpoint, but never without explicit opt-in.

  • Assurance gates the candidate decision. BOUND computes a DecisionAssurance (VERIFIED/MIXED/CLAIMED/INSUFFICIENT) from the decision-critical checks' provenance. A candidate ACCEPT backed only by CLAIMED/MISSING critical evidence is downgraded to the contract's on_missing/on_claimed action. Inspect it:

    bound inspect <run_id>                  # per-check provenance + candidate vs final + assurance + coverage
    bound inspect <run_id> --only-unverified # only unverified/claimed/missing/invalid evidence
    bound inspect <run_id> --json           # machine-readable: provenance + assurance + coverage
    

Persist the numeric evaluation

For every evaluation, read the numbers from the returned BOUND object and emit:

BOUND evaluation
Acceptance (A): <4 decimals>
Influence (I): <4 decimals>
Risk (R): <4 decimals>
Cost (C): <4 decimals>
Score (S): <4 decimals>
Threshold (T): <4 decimals>
Decision: <ACCEPT|RETRY|REPLAN|ROLLBACK>
Next action: <continue|retry|replan|rollback>

Also persist exposed weights, weighted components, retry margin, rollback-risk threshold, and score provenance. Read references/integration-report.md for the required report structure.

Validate earlier scores

When an earlier integration record exists, compare its contract, evidence, criteria, budgets, scores, decision, and action with the current run. When its inputs are complete, reconstruct them and call BOUND again. Compare returned A/I/R/C/S/T, decision, and action with the record.

  • Mark incomplete historical results not reproducible and list missing data.
  • Mark evaluations stale when evidence or configuration changed.
  • Append a new evaluation instead of silently overwriting history.
  • Treat a mismatch as a failed consistency check and investigate it before continuing.
  • Do not independently implement the formula as a second evaluator.

React to the result

  • ACCEPT: stop refining this phase and continue.
  • RETRY: preserve the strategy, make one focused correction, collect fresh evidence, and re-evaluate within the budget.
  • REPLAN: stop the current strategy, choose a materially different approach, and create a derived contract id.
  • ROLLBACK: restore only a previously confirmed safe checkpoint without discarding unrelated or pre-existing changes, then replan. If no safe checkpoint exists, report that and avoid a destructive approximation.

Record decision lineage (v0.7.0)

BOUND v0.7.0 can record every evaluation as a reproducible, append-only local lineage — contract → evidence → scores → decision → agent outcome — under .bound/runs/<run_id>/. It is opt-in per run and backwards compatible: if you never start a run, nothing is recorded. Disable it with BOUND_LINEAGE_DISABLED=1.

For any non-trivial task you evaluate with BOUND, follow these rules:

  1. Start ONE run per task.

    bound run start "<task>" --metadata phase=PHASE-001
    

    (In Python: with bound.start_run("<task>") as run:.)

  2. Use STABLE step/contract ids. Carry the same id from PLAN.md → StepContract(id=...) → lineage. A replan of the same step appends -R<N> (PHASE-001 → PHASE-001-R1); never invent an unrelated id or rewrite history to hide a replan.

  3. Evaluate only MEANINGFUL boundaries (after implementation + verification, not after every token/file/command), and record the evaluation into the run:

    bound evaluate --run <run_id> --step PHASE-001 --attempt 1 \
        --action "..." --goal "..." \
        --acceptance A --influence I --risk R --cost C \
        --threshold 0.7 --retry-margin 0.1
    

    This writes step_started + evaluation_recorded and adds a lineage block to the JSON.

  4. Record the REAL follow-up action you actually took — not what BOUND "should" have produced:

    bound outcome --run <run_id> --step PHASE-001 --attempt 1 \
        --decision REPLAN --note "switched strategy to validator + parametrized tests"
    

    --next-action and --reason-code are derived from --decision (ACCEPT|RETRY|REPLAN|ROLLBACK) when omitted.

  5. Explicitly CLOSE the run when the task ends:

    bound run finish <run_id> --status completed|interrupted|failed --note "..."
    

    A missing run_finished marks an incomplete/crashed run (the log stays readable). If you used with bound.start_run(...) the context manager auto-finishes an interrupted run on exit.

  6. REPORT the local lineage path — .bound/runs/<run_id>/ (run.json + the append-only events.jsonl) — and show the decision tree:

    bound inspect <run_id>
    

The canonical flow is one run, two attempts:

Attempt 1  →  evidence 1/3 (A=0.3333)  →  REPLAN  → switch strategy
            (new step PHASE-001-R1, attempt 2)
Attempt 2  →  evidence 3/3 (A=1.0000)  →  ACCEPT  → continue to next step

The event log is append-only: a replan emits a new step_started with attempt+1 and a -R<N>-suffixed contract id; earlier attempts are never rewritten. Prompts, tokens, and source code are never stored — only the contract id, scores, threshold, decision, reason code, and your follow-up action/note. See docs/lineage.md for the full data model and API.

Verify the integration

Add an end-to-end test that builds a real contract, collects real observed evidence, calls BOUND, asserts one of the four decisions, and asserts the exact control-flow mapping. Do not hardcode ACCEPT unless the evidence genuinely satisfies the contract.

Keep all wiring thin and outside src/bound/ in consumer repositories. Never fabricate evidence, duplicate policy logic, or use an LLM as the final judge.

Comments

Markdown supported