Valqore QED¶
QED decides whether an AI agent may perform an action, and writes evidence a third party can verify without trusting the party that produced it.
It is one self-hosted process. No bytes leave it by default. The decision path
contains no model: a verdict is a function of a proposal, a signed policy
bundle, a budget and a derived context, and the same inputs produce the same
bytes. The evidence is an Ed25519 hash-chained ledger, and the verifier that
checks it — qed-verify — is a separate package with cryptography as its only
dependency, written as an independent reimplementation so that agreement
between the two means something.
Thirty seconds¶
pip install valqore-qed installs a placeholder, not QED
The name is reserved; QED is not released. What PyPI serves today is a
0.0.0 package containing one README and no code — the reservation
exists so that nobody else can take the name, and publishing the real
thing is the irreversible step still ahead. Install from the repository
instead: git clone https://github.com/valqore/qed && cd qed &&
pip install -e ., and run qed --version to see which you have.
qed demo needs nothing: it generates a key, writes a qed.yaml, decides five
proposals -- a read, a destructive migration, an open security group, an
unapproved egress and an agent nobody authorised -- and verifies the chain it
wrote. It exits 0 although a BLOCK is in it, because the exit code of a demo
is whether the demo ran, and every record it writes is marked dev so the
chain cannot be mistaken for evidence.
Then the same path by hand, which is what an adapter does:
qed keys init --dir ./state
qed check proposal.json --dir ./state # 0 ALLOW · 2 BLOCK · 3 REQUIRE_APPROVAL
qed export --dir ./state > chain.jsonl
qed-verify chain.jsonl --keys ./state/public --instance-id qed-local
The last command is the one that matters. It reads a file and a public key, and it never contacts the instance that wrote them.
--instance-id is the only check in it that ties the export to a particular
instance, and it is the only one that can be skipped. Leave it out and the
verifier reports bound to : NOTHING and names the check that did not run,
because the alternative — printing an unqualified OK — would be the verifier
overstating its own result.
Where to go next¶
What this is not¶
- Not a scanner. It does not read your Terraform or your Kubernetes manifests. That is a different product.
- Not a model. There is no LLM in the decision path, and
tests/core/test_no_llm.pyfails the build if one appears. - Not a SaaS. The kernel runs where your agents run, and produces
auditor-acceptable evidence while completely offline. Anything under
qed.remote.*is opt-in, outbound-only, and carries hashes and signatures but never customer data. - Not finished. See the changelog for what is released and the threat model for what is not covered.
Honesty about assurance¶
A record proves different things depending on what produced it, and the
difference is recorded in the record rather than in the brochure. An
enforcing adapter holds the credential, so a BLOCK means the call did not
happen. An advisory adapter can only ask, so a BLOCK means the agent was
told no. Both are useful and they are not the same claim.
Assurance classes is the page that says which is which.