Kredent
Identity and verifiable reputation for autonomous agents.
Kredent gives a software agent a cryptographic identity it controls, lets it sign claims about what it did, and lets anyone verify those claims offline — with no registry, no resolver and no network access.
Why
Agents are starting to transact on their own: calling APIs, negotiating prices, making payments, deploying code. The infrastructure for this is being built quickly, and it has a gap at its centre. It is straightforward to answer "was this call authorised?" It is much harder to answer "who, exactly, made it, and should I trust them?"
An API key answers the first question and fails the second. A key is a bearer secret: whoever holds it can act as the agent, it says nothing about the agent's history, and it stops being meaningful the moment it is rotated or leaked. Every agent starts from zero on every new service, and no service can tell a reliable agent from a careless one.
Kredent's position is that this is an identity problem before it is a payments problem. Before an agent can be trusted to spend, it has to be identifiable across services in a way that is not controlled by any one platform. That requires an identifier that is portable by construction, and a history that is verifiable by anyone rather than held inside a proprietary scoring system.
Two choices follow from that, and they are the whole of the design:
- Identifiers are
did:key. The identifier is derived from the agent's own public key, so it is self-resolving: anyone can recover the verification key from the identifier alone, offline, with zero infrastructure. No platform issues it and no platform can revoke it. - History is a signed ledger, not a score. An agent's reputation is a deterministic function of public, signed events. Any party can recompute it and confirm the number they were given is real, rather than trusting a platform's internal metric.
What it is
A small Python library, a CLI, and an MCP server. Four operations:
| Operation | What it does |
|---|---|
create |
Generates an Ed25519 keypair and a did:key identity. |
attest |
Signs a claim, producing a self-contained attestation. |
verify |
Checks an attestation offline. Signature, key binding, integrity, expiry. |
reputation |
Computes a reputation score from a ledger of events. |
The signatures are Ed25519 (RFC 8032) over a JCS-canonical serialization (RFC 8785), following the W3C Data Integrity proof pattern. Request-level authentication uses RFC 9421 HTTP Message Signatures.
In 30 seconds
pip install kredent
kredent create --name billing-bot # an agent gets a did:key identity
kredent attest --name billing-bot \
--claim '{"action":"deployed","service":"billing-api"}' \
--out attestation.json # it signs a claim about what it did
kredent verify attestation.json # anyone checks it — offline, no registry
The verification above runs with no network and no account: the public key is
recovered from the did:key inside the document, so the file is the only input.
Install
pip install kredent
Or from a checkout:
git clone https://github.com/goun7/Kredent.git
cd Kredent
pip install -e .
The core library has a single runtime dependency, the audited
cryptography library, used for Ed25519. That
dependency is optional in practice: the package bundles a pure-Python Ed25519
implementation that is used automatically when cryptography is absent, so
kredent verify works on a machine with nothing else installed.
The MCP server additionally needs the mcp package:
pip install "kredent[mcp]"
Quickstart
Create an identity:
$ kredent create --name billing-bot --controller did:web:acme.example
{
"status": "stored",
"name": "billing-bot",
"agent_id": "did:key:z6MkhFUK6cNkNboTWN4VpRdKnMnH6y2RTXYFG6ve2EbziP7F",
"public_key_multibase": "z6MkhFUK6cNkNboTWN4VpRdKnMnH6y2RTXYFG6ve2EbziP7F",
"identity_document": { ... },
"note": "The 32-byte seed was written to the local store with 0600 permissions. ..."
}
Sign a claim:
$ kredent attest --name billing-bot \
--claim '{"action":"deployed","service":"billing-api","version":"1.4.2"}' \
--out attestation.json
wrote attestation.json
Verify it — anywhere, offline, with nothing but the file:
$ kredent verify attestation.json
{
"valid": true,
"status_code": 200,
"agent_id": "did:key:z6MkhFUK6cNkNboTWN4VpRdKnMnH6y2RTXYFG6ve2EbziP7F",
"message": "Attestation verified: signature valid over canonical document"
}
That verification needs no network and no registry lookup. The public key is
recovered from the did:key in the attestation itself, so the only input is the
document you were handed.
Score an agent from a ledger of events:
$ kredent reputation did:key:z6MkhFUK... \
--transactions 40 --total-claims 30 --refuted-claims 2
{
"agent_id": "did:key:z6MkhFUK...",
"reputation": {
"score": 0.6407,
"tier": "TIER_B",
...
}
}
Verification also reads from stdin, so it composes with anything:
cat attestation.json | kredent verify
A worked Python example
from kredent import generate_seed, create_attestation, verify_attestation
seed = generate_seed() # the root secret; keep it safe
att = create_attestation(
seed,
claim={"action": "deployed", "service": "billing-api", "version": "1.4.2"},
)
# Hand the attestation to anyone. They need nothing else to check it.
result = verify_attestation(att.to_json())
assert result.valid
print(result.agent_id) # -> did:key:z6Mk...
Using it with an MCP host
Kredent ships an MCP server exposing the same four operations as tools, so an agent can manage its own identity during a session.
{
"mcpServers": {
"kredent": {
"command": "kredent-mcp"
}
}
}
The tools:
| Tool | Purpose |
|---|---|
create_identity |
Generate a persistent did:key identity. |
attest |
Sign a claim with a stored identity. |
verify |
Verify an attestation offline. |
reputation |
Compute a reputation score from events. |
By default create_identity persists the seed locally with 0600 permissions
and never returns it over the transport. Passing persist: false returns the
seed once, for the caller to route into a secrets manager — nothing is written
to disk in that mode.
How reputation works
Reputation is not an opaque score. It is a published formula over a public ledger, so it can be recomputed and audited by anyone.
score = base_score × integrity_multiplier × volume_damping
base_score— a weighted blend of reliability (0.40), accuracy (0.30) and stability (0.15), normalised to 1.0.integrity_multiplier—max(0, 1 - 0.5 × contradiction_rate), so a history of refuted claims costs.volume_damping—1 - exp(-n/30), the cold-start term.
Three consequences worth knowing:
A new identity cannot look established. With one transaction an agent reaches about 3% of its nominal score. Farming a fake history is therefore slow and expensive, and an agent that discards its identity to reset a bad reputation starts again from near zero.
Lying costs more than honesty pays. A contradiction carries twice the weight of a confirmation, so the expected value of fabricating a history is negative.
Praise from nobodies is worth almost nothing. Each event is weighted by the counterparty's own reputation, so a ring of fresh identities confirming one another accumulates almost nothing. A share of volume concentrated in a single counterparty is flagged as a collusion pattern.
Tiers are thresholds on the score: TIER_A (≥ 0.85 with no refuted claims),
TIER_B (≥ 0.60), TIER_C (≥ 0.30), else QUARANTINED.
Security model
The seed is the identity. A 32-byte Ed25519 seed is the root of everything:
anyone holding it can sign attestations as that agent, and there is no recovery.
Treat it as a credential. Kredent never writes it anywhere unless asked, writes
it with 0600 permissions when it does, and never returns it over the MCP
transport unless you explicitly request it.
Verification is offline and keyless. kredent verify performs no network
calls. It recovers the public key from the did:key in the document, so a
verifier has nothing to compromise and no resolver to attack.
Every forgery path is a test case. Tampering with the claim, the issuer, the attestation id, or swapping in a signature from a different key are all rejected with a distinct error code. The test suite pins these behaviours.
Known limitations, stated plainly:
- A
did:keycannot be rotated or revoked. A compromised seed permanently burns the identity and its history. There is no remediation path within the protocol. For a long-lived agent that must survive key compromise,did:webwould be the better method, and nothing prevents an operator from running that underneath. - The protocol establishes who signed a claim and that it is unaltered. It does not establish that the claim is true. Grounding in reality requires evidence from outside the protocol.
- Reputation measures whether claims were confirmed or contradicted by parties willing to say so. It does not measure whether an agent's output was good; that is a judgement for a human or an evaluating model.
- Ed25519 is not post-quantum. The proof format carries an explicit
cryptosuitefield so a future suite can be introduced without changing the document model. - The bundled pure-Python Ed25519 exists so verification works with zero
dependencies. It is correct and cross-validated against
cryptographyand the RFC 8032 test vectors, but it is not constant-time and is not intended for high-volume signing. Installcryptographyfor that.
Repository layout
kredent/ Core library
crypto.py Ed25519, base58btc, multibase, did:key resolution
models.py AgentID, Attestation, ReputationScore, ledger events
canonical.py JCS (RFC 8785) and RFC 9421 canonicalization
attest.py Attestation issuance and offline verification
reputation.py Scoring engine and anti-gaming filters
ledger.py Append-only calibration ledger
store.py Local identity store (0600 secrets)
verifier.py RFC 9421 request verification with replay protection
cli.py The `kredent` command
mcp_server.py MCP server implementation
mcp/kredent_mcp.py Entry point for the MCP server
tests/ Test suite
docs/arastirma/ Research notes on DIDs, reputation and signature schemes
Tests
pip install -e ".[dev]"
pytest
1.321 tests passed, 0 failed rc=0 (LEED-ölçümü 2026-10-19, pytest tests/), covering the attestation lifecycle, every forgery path, did:key
round-tripping, JCS determinism, reputation math and anti-gaming filters, the
CLI as real subprocesses, and the MCP server over an actual JSON-RPC stdio
session.
Research notes
The design decisions above are grounded in documented specifications. Notes and
sources are in docs/arastirma/:
- Decentralized identity (DID)
- did:key vs did:web for agents
- Agent reputation systems
- The signature stack
Status
Working core. The attestation format is stable; the reputation model is still being tuned against real event data and its weights may change. Do not treat a reputation score as a decision-making oracle yet.
License
Apache-2.0. See LICENSE.
Academic & technical references
- Verifiable credentials — Kredent issues an agent a cryptographic identity it controls, plus reputation others can verify without trusting the issuer's word. This is the verifiable-credentials pattern: issuer, holder, verifier — the holder presents, the verifier checks, the issuer cannot silently revoke what was already shown.
- Decentralized identifiers (DIDs) — the identity primitive x402's
own ecosystem converged on:
x402 #1777
(agent-trust DID, 119 comments). Mesh implementation lives in
63-Sester
sester/trust.py(did:sester:prefix, attestations, trust-tiered pricing). - Reputation with wash-trade resistance — a raw count of completed
transactions is gameable: two wallets under one party can settle
real value back and forth forever and manufacture "activity."
The countermeasure is diversity (distinct counterparties or
resources per transaction); see
x402 #2833
("volume is not trust") and Sester's
wash_resistant_score. - Privacy property: Kredent's reputation is presented per-attribute — an agent proves a property about its history without exposing the whole history. Selective disclosure, not full exposure.
Current academic references (2024–2026)
The patterns above, as they appear in the 2024–2026 literature:
- Lookup-private credential status verification (2026) — Herbke, Rieder, Sechting vd. "ShadowPath: Lookup-Private Credential Status Verification over Authenticated State." (arXiv 2608.19937): checking whether a credential is still valid without the issuer learning who is checking — Kredent's "verify without trusting the issuer's word" property with the privacy half made explicit.
- Private credential inference (2026) — Breckenridge, Vilardell, Leung vd. "$π$Creds: Privately Inferred Credentials." (arXiv 2606.03771): deriving a credential's content without disclosing it — the selective-disclosure primitive Kredent's per-attribute reputation uses.
- Verifiable credentials in privacy-preserving federated analytics (2026) — Drăgnoiu & Olimid. "On the Usage of Verifiable Credentials in Privacy-Preserving Federated Analytics." (arXiv 2609.33004): issuer/holder/verifier separation as it is applied when the holder must not expose the underlying data.
- Verifiable provenance with limited disclosure via ZKPs (2026) — Hrabar, Arshadi Soufiani, Kim vd. "OreProof: Verifiable Provenance with Limited Disclosure for Critical-Minerals Supply Chains Using Zero-Knowledge Proofs." (arXiv 2609.00340): prove a chain-of-custody claim without revealing the custody history — the shape of Kredent's reputation attestation.
- DIDs for agents (2026) — Garzon, Vaziry, Kuzu, Gehrmann. "AI Agents with Decentralized Identifiers and Verifiable Credentials." (DOI 10.5220/0014234400004052, ICAART): the issuer/holder/verifier pattern applied to autonomous agents — the population Kredent attests to.
Metadata
Release files for kredent 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| kredent-1.0.0.tar.gz | 109.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kredent-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 154.9 kB
Release files / kredent-1.0.0.tar.gz
| Download URL | kredent-1.0.0.tar.gz |
|---|---|
| Size | 109.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f66f903826205e3f95f8e2141eaa652c5dbd8f8967da6b26485a12e61b3c6895
|
|
BLAKE2b-256 checksum How to use checksums |
91f3ad22d1a182e2f376297d17d911187f6d34caca7a5879ad1ccbd9ae74e8c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / kredent-1.0.0-py3-none-any.whl
| Download URL | kredent-1.0.0-py3-none-any.whl |
|---|---|
| Size | 45.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
355fdcbb247ed7eb5ffc4f82e5e2f4ba2298b4d646f735fbcd90ca51f4f8a589
|
|
BLAKE2b-256 checksum How to use checksums |
d88283f15a7caf55ccfffba4c446e17149adfdf2937efe819e9436845fe2d77c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Security for kredent 1.0.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.