Abe · free · open source · FJP Gate reference implementation

Act. Block. Escalate.

Abe is one control point before an AI agent acts. It checks a proposed action against your policy and returns ACT, BLOCK or ESCALATE, with an immutable record of why. It runs entirely on your machine. No account, no API key, no network, no model.

< 1 ms
Median evaluation, no external calls.
0
Network calls, accounts or keys required. No call-home.
L3
Every record passes FJP-CONF v0.1. 160 conformance checks, offline.

Three answers. Nothing else.

ACT

The policy found no reason to stop or escalate. Execute exactly as evaluated. It does not claim the action is optimal.

BLOCK

A rule clearly forbids it: over a hard limit, blocked vendor, unauthorized agent. Do not execute.

ESCALATE

Rules conflict, evidence is missing, stakes or irreversibility are high, or judgment is required. Hold. Not an error.

BLOCK beats ESCALATE beats ACT. Bad input or a broken rule returns ESCALATE / EVALUATION_FAILURE. Abe never silently acts.

01Install and run your first check
$ pip install abe-ai # or: npm install abe-ai $ abe init # writes abe-policy.yaml + request.json $ abe check request.json Decision: ESCALATE Reason: FINANCIAL_THRESHOLD_EXCEEDED Rules: purchase_review_limit Record: jgr_01M3Q4…
02Put it in front of the action
Python
from abe import Abe abe = Abe("abe-policy.yaml") r = abe.check( action={"type": "wire_transfer", "amount": 50000}, context={"agent_id": "finance-agent"}) if r.decision == "ACT": execute()
TypeScript
import { Abe } from "abe-ai"; const abe = new Abe({ policy: "./abe-policy.yaml" }); const r = await abe.check({ action: { type: "purchase", amount: 12500 }, context: { agent_id: "procurement-agent" } }); if (r.decision === "ACT") execute();

Any other language: abe serve runs a local HTTP sidecar on 127.0.0.1 (POST /v1/check), also available as a Docker image. MCP agents: abe mcp exposes fjp_check_action.

03Write the policy you already have in your head
version: "0.1" defaults: { unmatched: ESCALATE } # fail closed rules: - id: purchase_hard_limit when: { all: [ { field: action.type, op: eq, value: purchase }, { field: action.amount, op: gt, value: 100000 } ] } decision: BLOCK - id: purchase_review_limit when: { all: [ { field: action.type, op: eq, value: purchase }, { field: action.amount, op: gt, value: 10000 } ] } decision: ESCALATE reason_code: FINANCIAL_THRESHOLD_EXCEEDED evidence_requirements: - { id: refund_evidence, when: { field: action.type, op: eq, value: refund }, require: [evidence.customer_verified, evidence.original_transaction] } judgment_required: - action.type: terminate_employee
SectionDoes
rules11 operators (eq gt in contains exists…) with all / any / not
authorizationWhich agent may take which action types → AUTHORIZATION_FAILED
evidence_requirementsRequired facts before acting → EVIDENCE_MISSING with the missing fields
risk · irreversibilityLevels with thresholds. Callers can raise risk, never lower it.
confidenceAgent-supplied confidence minimums, recorded as uncalibrated
judgment_requiredAction classes that always need judgment
04Keep a record an auditor can verify

Every call returns a Judgment-Grounded Record: the decision, every matched rule, the exact policy hash, the request hash and a SHA-256 record hash, optionally Ed25519-signed with a local key. Records never change. Outcomes and resolutions are appended as linked records.

decisionESCALATE · FINANCIAL_THRESHOLD_EXCEEDED
policy.hashsha256:7152f8e4… (which rules existed when the agent acted)
falsifierAn OUTCOME record reports status executed before a RESOLUTION with decision ACT is linked
record_hashsha256:684f5e90… · signature ed25519 (optional)
$ abe validate-record jgr.json --public-key abe-signing-key.pub.pem VALID jgr.json (hash verified, signature verified; FJP-CONF v0.1 L0-L2)
05When rules aren't enough, add Flow

Rules handle the obvious. When Abe says ESCALATE, hand that one action to Flow's judgment service. ACT and BLOCK never leave your machine; only escalations are sent, redacted, and only they cost anything.

$ pip install abe-flow from abe_flow import FlowResolver abe = Abe("abe-policy.yaml", resolver=FlowResolver(api_key=os.environ["FLOW_API_KEY"]))
Abe saysFlowResult
ACT / BLOCKnot calledunchanged. A resolver can never loosen a BLOCK.
ESCALATE: human approvalnot calledstays with the human
ESCALATE: anything elsejudgeREACH → ACT · SKIP → BLOCK · WAIT / RESEARCH_FIRST → ESCALATE, with Flow's reason and falsifier linked to Abe's record
Flow unreachablestays ESCALATE. Abe never fails because Flow is down.
Abe acts, blocks or escalates. Flow resolves the escalations. Abe is useful without Flow. Flow is what you call when Abe says a call needs judgment.
06Prove it conforms
$ abe conformance --bench 160/160 checks passed RESULT: conforms to FJP-CONF v0.1 Gate profile, Level 3 performance: p50 0.34 ms p95 0.44 ms

Third-party implementations can run the same published fixtures and claim "FJP Compatible". Apache-2.0.