Your agent can read anything. It cannot act on it without asking.
An agent's danger is usually the sequence, not the step: a permitted read, then a permitted send. Bounds evaluates each call against the path of its task and the rules you wrote, refuses what breaks one, and records the verdict with a reason you can read and hand to somebody else.
Install it and watch it refuse.
npx attesso init
npx attesso log --action web.read --subject docs.example --task job-1 \
--trust untrusted --capability read
npx attesso log --action mail.send --subject partner@example.com --task job-1 \
--capability send
# #2 DENY mail.send partner@example.com
# (PATH_DENIED by step #1 under no-send-after-untrusted-read)
npx attesso reportNo account, no server, no key to register. The ledger is hash-chained and signed locally, and attesso report shows what ran, what was refused, and what it cost in tokens and dollars.
Path rules, refusals with reasons, and a record.
- Rules judge the task path, not one call: a send after an untrusted read is refused, and the refusal names the step that tainted it.
- Step and repeat ceilings stop a loop before it spends the afternoon: the same tool with the same arguments, refused at the limit you set.
- Every verdict is recorded with its rule and the state it was judged against, so the answer to "what happened" is a file, not a memory.
- Enforcement is steer first: on a repeat the earlier result is handed back, which is where tokens actually stop being spent.
Money and exposure, kept apart.
- Repeats and retry loops: in one measured session, 193 duplicate runs and 136 failure-shaped results out of 2,070 tool calls, an upper bound of 16% of that session's cost.
- Actions outside the bounds a person signed: refused before they run, with a signed reason.
- Context you did not need: a step or cost ceiling per task, enforced instead of noticed afterwards.
Waste is measured on your own sessions and quoted as a percentage of model spend. Incident avoidance is exposure, not a saving, and we do not multiply it by an invented probability.
The limits, stated here.
- A local ledger key sits beside the log. It proves the file was not edited, not that a human authorised anything.
- A stranger cannot verify a local file: they would have to trust the key inside it. Hosted evidence verifies against published keys.
- Local mode has no cross-device approval and no revocation beyond deleting the directory.
Human authority, cross-device keys and verification by a stranger need the hosted plane, where an approval is a passkey assertion over exact terms and the record verifies against published keys.
Nothing until the record leaves your machine.
- Free and unlimited on your own machine. Rules, ledger, report, hook; nothing metered.
- $0.0002 per synced decision when the record has to leave your laptop. That is 50 cents per 2,500 calls.
- No plan, no seats, no minimum. $2 of credit to start, about 10,000 decisions, no card.
Synced means a receipt Attesso signed, verifiable by someone who trusts neither you nor us. Decisions made offline are never metered.
A local key proves integrity. Ours proves it to a stranger.
| Method | What it proves | Where it fits |
|---|---|---|
| Local Ed25519 key | The ledger was not edited after the fact | Free, on your machine |
| Attesso receipt (ES256) | A third party verifies the decision without trusting you | Hosted, per synced decision |
| Passkey (WebAuthn) | A human approved these exact terms | Hosted, approvals |
A receipt names which signer it carries. A record claiming human authority must carry a WebAuthn assertion; a local or CI key is not interchangeable with one, and the verifier refuses the combination.
Operational detail, commands and the refusal codes: docs.attesso.com, and the package itself: npmjs.com/package/attesso.
Install it and watch it refuse.
Free on your machine, no account. $0.0002 per synced decision when the record has to travel.