liminate-invariant
Invariant by Liminate. A deterministic claim-verification correction harness for AI agents, built on liminate.run(): it hosts an agent behind a callable, runs a Liminate contract against the agent's output each cycle, reads structured failure details off the result stream, feeds them back to the agent, and re-runs until claims verify, stall, or the ground proves unstable. Per-claim status, partial-pass acceptance, and honest escalation (a stall is not the same as flaky ground, and neither is a plain fail) are the point.
import liminate_invariant as invariant
result = invariant.run(contract_text, agent, probes={"build-output": run_build})
agent is a callable of AgentTask -> AgentResponse: it receives the contract text, the current cycle number, and the failure details from the previous cycle, and returns the claims it produced this round. probes are optional callables that acquire ground truth directly (test output, a build status, a metric) — Invariant re-acquires and re-samples them each cycle to tell a genuinely unstable measurement (flaky) apart from a claim the agent keeps getting wrong (a stall).
run() never writes anything. It proposes a result; the caller decides what to do with it.
Status vocabulary
Each claim resolves to one of:
verified— passed on the first cycle.corrected— failed at least once, then passed after the agent revised its claim.escalated— did not resolve.escalation_reasonis one of:"claim will not converge"— the same failure recurs across consecutive cycles; re-eliciting from the agent isn't fixing it."ground will not stabilize"— the probe-acquired ground itself won't settle into a stable pass or fail.
pending— reserved for a future prediction capability (condition-gated re-check). This build's loop never assigns it.
Quick start with simple()
For a plain string-in/string-out function, skip the structured interface:
import liminate_invariant as invariant
def call_my_agent(prompt: str) -> str:
... # however you talk to your model of choice
agent = invariant.simple(call_my_agent, source="build-status")
result = invariant.run(contract_text, agent)
simple() serializes the contract and failure details into a single prompt string for you. It's the fast on-ramp — the structured AgentTask / AgentResponse interface is the recommended integration, since serializing to a prompt string discards machine-readable failure identity that a real integration can use directly.
Generating governance
Pass narratia= to have repeated failures propose durable inherited when handlers instead of just failing the same way forever:
import liminate_invariant as invariant
narratia = invariant.NarratiaReference(complete=lambda prompt: client(prompt))
result = invariant.run(contract_text, agent, narratia=narratia)
complete is any string-in/string-out completion callable wrapped in a lambda — there's zero LLM SDK dependency inside Invariant itself. Every proposal Narratia returns passes a deterministic gate before it can touch a cycle: it's parsed by the same engine that runs your contract, and checked for contradictions against the contract's obligations. Every rejection is recorded, not silently dropped.
Admitted handlers apply in memory for the rest of the run and come back as InvariantResult.new_handlers — canonical, attributed inherited when ... from narratia text. run() still never writes: committing those handlers to your actual contract is yours to do.
Release files for liminate-invariant 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| liminate_invariant-0.1.1.tar.gz | 31.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| liminate_invariant-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.2 kB
Release files / liminate_invariant-0.1.1.tar.gz
| Download URL | liminate_invariant-0.1.1.tar.gz |
|---|---|
| Size | 31.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fc5d5c2e430f24f60602d0b586c0b9e2be509395e4edc685649f303f28e6e977
|
|
BLAKE2b-256 checksum How to use checksums |
aa92a5a62427a1f24971dfadd8b3c9bc701ff9ac4a5b47a5d21c9e7106c8c66f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / liminate_invariant-0.1.1-py3-none-any.whl
| Download URL | liminate_invariant-0.1.1-py3-none-any.whl |
|---|---|
| Size | 17.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
025870e01656c9d19ca8c9d8fff63fef9cf563d89be62cfd34c01e613ead747c
|
|
BLAKE2b-256 checksum How to use checksums |
9b5ef2ebfd0f0adf90e347c2702fc272518d775c096adb4ef1670824d10a5b31
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|