Skip to main content

Prosaic Harness

Version 0.7.1 is the candidate b3-prosaic-harness index distribution, with b3-prosaic-runtime>=0.8,<0.9 and optional b3-prosaic-harness-postgres 0.2.1. Imports (prosaic_harness) and CLI commands (prosaic-harness) remain unchanged. The five-package release train is pending final qualification and publication; see package migration for fresh-environment installs.

Version 0.6.2 added a validated in-memory workflow factory for approved agents, native tool registries and client-generated graphs. The host supplies policy and private bindings; proposals need no filesystem directory. Admission, schema bounds and durable failure recovery are enforced before execution.

Optional customer accounting context preserves attribution through workflow retries and resume. Existing callers and saved runs remain supported; durable usage recording is explicitly enabled through Prosaic Runtime.

Version 0.6.1 fixes lease-registration admission in the separately installed PostgreSQL adapter (0.1.1) for cross-worker durable workflows. Core remains database-free; filesystem constructors/CLI remain supported. See explicit database setup/grants and the zero-model-call two-worker example. Prose tools do not grant database access; applications retain tenant authorization and filter private run state.

The RunStore ruling register preserves implementation/review decisions, reasons and risks with stable IDs.

Version 0.5.0 adds schema-validated human responses at durable workflow pauses, with trusted validators and retained feedback for downstream agents and checks. It pins Runtime v0.5.3 and automatically installs Python Prosaic v0.3.1. Installation and CI no longer require Node.js or npm.

Version 0.4.0 adds manifest-defined CLI tools through the normal workflow CLI, with offline availability checks and required native execution evidence. Current candidates select the compatible Runtime 0.8 series.

CLI permissions and sandboxing

Harness 0.7.1 retains CLI sandbox policy enforcement and selects Runtime 0.8.x, which provides cli_sandbox_v1. Follow the sandboxed workflow walkthrough for installation, offline validation and live execution. The complete blueprint is cli-tool-sandboxed.yml.

Permissions are operator-owned, not granted by prose:

Location Setting Meaning
Agent Markdown tools: [analyze_spec] Request the tool; not authorization
Runtime YAML allowed_tools: [analyze_spec] and reviewed tool_directories Allow the tool and trust its manifest/executable
Workflow agent step tools: [analyze_spec], read_roots: [evidence] Grant that step the tool and narrow readable inputs
Runtime YAML cli_sandbox: {mode: required} Enforce OS isolation for CLI execution and probes
Workflow agent step require_tools: [analyze_spec] Require observed successful execution; grants nothing extra

All tool permission layers must agree. validate loads the workflow and runs offline CLI preflight; it does not contact a model or need an endpoint key. The sandbox is off by default. Required mode fails closed if unavailable; Linux needs Bubblewrap >= 0.12.0 and permitted user namespaces, while macOS needs Seatbelt's sandbox-exec. See Runtime's setup.

Sandboxed CLIs can read granted evidence and write private scratch, but cannot write the workspace or reach the host IP network. Keep host Unix sockets outside granted directories. Extra dependencies need narrow runtime_roots, not HOME or /. This does not sandbox Python callbacks, validators or native coding providers; builtin read tools retain their existing path checks. Harness itself still writes durable run state on the host. Required-mode policy is sealed into workflow identity: changes invalidate existing approvals/resume, and injected adapters cannot silently downgrade it. Use a fresh run directory when changing policy.

Overview

The custom-tool embedding example adds catalogue lookup, version-bound native execution evidence, deterministic answer admission and a human pause. It requires Harness v0.4.0+ / Runtime v0.5.0+.

A small Python harness for durable workflows built from neutral Prosaic agents. Define a graph in YAML, execute agents through Prosaic Runtime, validate their JSON outputs, and resume from local checkpoints. Apache-2.0.

Component Owns
Prosaic Markdown agents and resource inspection
Prosaic Runtime One model invocation, model tiers, tools, streaming, permissions
Prosaic Harness Steps, validation, transitions, review loops, human pauses, run evidence

The initial release supports Linux and macOS with Python 3.11+. It needs an existing OpenAI-compatible endpoint and the Python Prosaic CLI. Windows users can use WSL. The library imports no Echelon code.

Version 0.2.0 adds versioned approvals, trusted checks and final-output validation, and hash-bound read provenance. Version 0.3.0 pins Prosaic Runtime 0.4.0, adding opt-in acquisition, strict initial-tool enforcement, admission-time resource checks and larger incident-review examples. State format is version 2; existing 0.1 runs must start afresh. See hardening setup and contracts.

First run

Install Git and Python 3.11+ before starting. Use an explicit Python environment so another application's older runtime cannot be picked up by accident.

git clone https://github.com/B3Cognition/prosaic-harness.git
cd prosaic-harness
git checkout <exact-candidate-commit>
python3 -m venv .venv
.venv/bin/python -m pip install --find-links /absolute/path/to/curated-wheelhouse .

export PATH="$PWD/.venv/bin:$PATH"
prosaic --help
.venv/bin/prosaic-harness --help

ALWAYS use a fresh clone/environment for migration; NEVER reuse an environment containing legacy distributions. In a future terminal, return to the repository and add its .venv/bin to PATH again. Node.js and npm are not required. Candidate dependency metadata selects b3-prosaic-runtime 0.8.x, b3-prosaic 0.4.x, PyYAML, jsonschema and referencing. Use only the manifest-selected b3 wheels in the curated wheelhouse. Candidate installation requires the Runtime 0.8 producer; it is not yet a published index install. No sibling checkout or manual Prosaic installation is needed. Older Harness tags retain their historical installation docs.

Configure an endpoint

Edit examples/runtime.yml: replace the localhost URL and your-model with your operator's values. Each profile names an endpoint, model, credential environment variable, and optional transport features. Prose model_tier selects a profile through routes. Set the key without putting it into YAML:

export LOCAL_LLM_API_KEY="$(.venv/bin/python -c 'import getpass; print(getpass.getpass("Endpoint key: "))')"

An unauthenticated endpoint may omit api_key_env. If your endpoint rejects streaming usage reporting, set stream_options: false. Diagnostics do not generate text unless you explicitly request inference:

.venv/bin/prosaic-runtime doctor --config examples/runtime.yml --output text

For the private TokenProxy demo, examples/tokenproxy.yml supplies the four model profiles. examples/tokenproxy-single.yml and examples/tokenproxy-review.yml select that configuration. They require access to 10.16.81.27:8080:

source ~/.zshrc
export TOKENPROXY_KEY
.venv/bin/prosaic-runtime doctor --config examples/tokenproxy.yml --output text

Run one agent with validation

.venv/bin/prosaic-harness validate examples/single.yml --checks examples/checks.py
.venv/bin/prosaic-harness run examples/single.yml \
  --checks examples/checks.py --input examples/request.json --run-dir runs/first-note
.venv/bin/prosaic-harness status --run-dir runs/first-note

For TokenProxy, substitute examples/tokenproxy-single.yml. This makes a real model request. The briefer must return JSON matching examples/schemas/brief.json; invalid output triggers bounded retries with validation feedback. Completion prints the accepted object. Use a fresh run directory for another input.

Run a review and repair workflow

.venv/bin/prosaic-harness run examples/tokenproxy-review.yml \
  --checks examples/checks.py --input examples/request.json --run-dir runs/launch-review

This exercises four tiers: Ornith briefs the request, Qwen drafts a recommendation, DeepSeek reviews it, and Nemotron creates a final decision. A gate routes an unapproved review back to the author. The author receives the previous review as an identified input artifact. The actual final decision gets its own model review and deterministic evidence check before pausing for human approval:

.venv/bin/prosaic-harness resume examples/tokenproxy-review.yml \
  --checks examples/checks.py --run-dir runs/launch-review --choice approve

Choose reject to finish with a rejected outcome. Approval records a decision; it does not publish files or send messages. Use examples/review.yml for your own configured endpoint. See examples/README.md for the graph, contracts, tool example, and a complete Python embedding program.

Workflow format

All paths in a workflow are relative to its directory and confined to it. The workflow can be launched from any working directory. Schema references are internal to their document. Arbitrary expressions and remote schema fetching are not supported.

version: 1
source: .prosaic
runtime: runtime.yml
start: draft
limits:
  max_calls: 8
  max_visits: 3
  timeout_s: 180
steps:
  draft:
    kind: agent
    agent: subagents/author.md
    schema: schemas/draft.json
    optional_inputs: [review]
    max_attempts: 2
    next: review
  review:
    kind: agent
    agent: subagents/reviewer.md
    schema: schemas/review.json
    inputs: [draft]
    next: gate
  gate:
    kind: gate
    from: review
    field: [approved]
    equals: true
    pass: done
    fail: draft
  done:
    kind: finish

Agent arguments are a JSON object with request (the run input), artifacts (selected prior accepted outputs, keyed by step ID), and validation_feedback (the last validation error, if any). inputs are required; optional_inputs include an output only when it exists, allowing first-pass review loops. Outputs replace a step's latest accepted value on revisits, while every attempt is retained in receipts and approvals bind to exact required-input versions. Optional inputs can carry stale feedback, not required approval dependencies. Arguments also include artifact_bindings and declared file sources. Raw transport stdout must be one JSON value; a single JSON Markdown fence is also accepted. Schema failures do not advance the graph.

Step kind Fields and behavior
agent agent, schema, next; optional acquisition prose ID, input IDs, tools/read roots, required successful tools, attempts, visits
gate from, field (list of keys), equals, pass, fail; missing data blocks
check from, trusted validators, pass, fail; no model call
pause question, choices mapping named answers to next steps
finish Optional outcome: completed or rejected

A pause can optionally declare response_schema: schemas/feedback.json and host-registered validators. Submit resume(choice="refine", response={"text": "..."}) or CLI resume ... --choice refine --response feedback.json. The schema validates the payload; trusted pause validators receive {"choice": ..., "response": ...} with the original request and accepted artifacts in their check context. Applications can verify dynamic candidate membership there without encoding product IDs into the workflow graph. Invalid responses leave the pause untouched. Accepted responses are sealed into history and subsequent agent arguments include human_responses, keyed by pause step with its latest choice and response. They are user data, never tool permissions. Existing choice-only pauses retain their original behavior and reject payloads. A completed response cannot be submitted again. Trusted downstream validators also receive these accepted values through CheckContext.human_responses; they can enforce that a proposal matches the user's selection rather than trusting a model's account of that selection.

max_run_s includes human waiting. Interactive applications should use an explicit human expiry for a decision workflow and a separate bounded workflow for each model turn; do not reuse a short model request timeout as a human response deadline.

Each step may override max_visits. Agent attempts bound validation/transport retries within a visit; visits bound graph loops; max_calls bounds invocations across the whole run, including authorized interrupted retries. timeout_s is per invocation. Optional max_tokens counts all reported tokens and blocks on unknown usage; max_run_s persists a whole-run deadline including human waiting. There is no monetary guarantee. Finite graph visits also bound non-agent loops. There is no automatic model escalation.

Permissions and evidence

Default agent permissions are empty. A workflow step may declare read tools and explicit read_roots; the runtime also intersects those with the prose's tools and runtime configuration grants. Optional require_tools: [read_file] rejects an output unless the invocation produced a successful tool event for that name; it does not prove which file was read or whether the answer interpreted it correctly. Declare evidence and require_reads for hash-bound complete-file read evidence. Development-only acquisition: subagents/evidence-acquisition.md sends a short Prosaic artifact before the full agent assignment. It requires require_reads and Runtime acquisition_v1; both prose digests are part of the sealed workflow fingerprint. One Runtime invocation owns both phases, their shared deadline, usage and tool budget. Failed acquisition blocks without automatic repair or fallback. Final JSON/schema/source checks still apply after successful reads. Acquisition gets no final arguments; its own prose specifies the evidence path. For model-independent acquisition, explicitly choose the no-tool preloaded-evidence.yml blueprint instead: the controller supplies immutable evidence text in sources. This is snapshot evidence, not a native tool receipt. See the step-by-step examples. The direct-read problem and staged-acquisition resolution show how to keep a detailed answer contract out of the initial read phase and verify the native receipt before analysis. Trusted checks are explicitly supplied by the host through validators= or CLI --checks. They execute Python with host permissions and are not sandboxed. V0.2 has no shell checks, agent file writes, publication effects, remote workers, or recursive agent dispatch. Application integrations can be added through an explicit boundary in a later release.

Run evidence is local:

runs/launch-review/
  run.json                 # sole durable state authority, accepted outputs, history
  run.lock                 # OS-backed lock prevents concurrent writers
  attempts/<id>.json       # arguments, raw result, token usage, model/tool events

--events emits JSONL events and a final status report to stdout. Normal mode prints status and a five-second heartbeat to stderr and accepted results to stdout. Credentials remain in environment/secret files; run evidence contains supplied inputs and model output, so give its directory the same protection as the inputs. The harness does not redact arbitrary sensitive information supplied by users.

Resume and interruption

.venv/bin/prosaic-harness resume examples/review.yml --checks examples/checks.py --run-dir runs/launch-review

The harness saves a pending invocation before contacting the runtime, then saves its receipt before committing the accepted output and transition. If a receipt survived, resume adopts it without making another request. If no receipt survived, the run blocks with interrupted_call: the endpoint may already have processed the request. Explicitly authorize another billable call with:

.venv/bin/prosaic-harness resume examples/review.yml \
  --checks examples/checks.py --run-dir runs/launch-review --retry-interrupted

This consumes another call slot. There is no exactly-once guarantee for model calls or their tool activity. Definitions, schemas, inspected prose, and runtime configuration and validator versions are fingerprinted; changes require a new run. Declared evidence changes also reject resume. Credential rotation through the same environment-variable name does not change the fingerprint. Limit-exhausted runs remain blocked; start a new run with revised limits rather than modifying stored state. State assumes trusted local storage, not adversarial tampering. Checksums and structural checks detect corruption, not coordinated forgery. New checkpoints are version 2; old runs need a new directory. CLI exit codes: 0 completed/waiting, 1 blocked/rejected, 2 configuration or usage error, 130 interrupted. Waiting is explicit, not final acceptance.

Development

.venv/bin/python -m pip install -e '.[test]'
.venv/bin/python -m pytest
.venv/bin/python -m build

Tests cover schema retries, branching/repair, human choices, bounds, interrupted calls, receipt recovery, definition changes, locking, tool scope, and transport integration. Live runs are opt-in examples, not part of the offline suite.

Structured JSON tools

This revision pins Prosaic Runtime 0.7.1, which supplies StructuredToolLoop for explicit JSON tool-request transport. Product adapters can yield one Runtime turn per Harness invocation while retaining application-owned result validators. Register the same CustomTool descriptors with the workflow and adapter so Harness fingerprints and checks their contracts. Harness retains routing and checkpoint ownership; Runtime owns parsing, dispatch, bounds and repeat detection.

Metadata

Release files for b3-prosaic-harness 0.7.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for b3-prosaic-harness 0.7.1
File Size Uploaded
b3_prosaic_harness-0.7.1.tar.gz 355.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for b3-prosaic-harness 0.7.1
File Interpreter ABI Platform
b3_prosaic_harness-0.7.1-py3-none-any.whl Python 3 none any Details

Total release size: 422.6 kB

Release files / b3_prosaic_harness-0.7.1.tar.gz

Download URL b3_prosaic_harness-0.7.1.tar.gz
Size 355.4 kB
Tags Source
SHA-256 checksum
How to use checksums
e193b228ffa50dba8a8d3b153b6b71777901a0d08080e2cd4af30ad666302564
BLAKE2b-256 checksum
How to use checksums
623af4606de6cb070480e258daede8394c16f271cb80b4f8a7f4efcffd21bfef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release files / b3_prosaic_harness-0.7.1-py3-none-any.whl

Download URL b3_prosaic_harness-0.7.1-py3-none-any.whl
Size 67.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7cb170ad52f9170221360f2d0eac868c667d9e531dd39236db0bf46987c18db2
BLAKE2b-256 checksum
How to use checksums
eb889c363d7f82886f8b4aaad64bcfe79f7fa490d3a3aa4a7f02beb24549b935
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.7.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page