Koinii actor identity: per-agent contexts as the identity substrate AND the write boundary, an admin-only agent registry, and the one auth extension point whose strength is conditional on the adjudication policy.
The engine deliberately pushes per-caller identity OUT — *creator* is an
unauthenticated annotation and the daemon's only auth is one shared bearer token —
so koinii's answer is the context lattice, not a new auth subsystem:
CxAtlas, lifted under the
channel by (genlCx CxDeploy CxAtlas). A reader of CxDeploy sees the union of
every agent's assertions; CxAtlas alone is 'everything Atlas said' — a plain
context read. Because context is part of sentex identity, Atlas's P and
Boreas's P are two DISTINCT sentexes, each with its own creator, so
first-writer-wins loses no co-source (co-attribution-survives?).The auth extension point is conditional on policy (koinii design D4):
*creator* bound by convention, the write routed
to the agent's own context, trusted because the agents are. Correct for a
notify-only deployment. It defends fat-fingers, NOT attackers: authenticate
trusts the claimed id with no proof, so a client may claim any identity. State
plainly that identity is unauthenticated here.authenticate
verifies a credential (the verify-fn extension point — sign-at-ingest, an authenticating
proxy, or A2A AgentCards / DIDs) and REFUSES an unverified request; ingest under
the principal it mints attests each write with the deployment key (*attest-key*).
Both checks run in the process that holds the key, never on the wire.Every write goes through the provenance-stamping assert path — NEVER
bulk-assert-facts!, which binds *bulk-load?* and writes no provenance at all.
Koinii actor identity: per-agent contexts as the identity substrate AND the write boundary, an admin-only agent registry, and the one auth extension point whose strength is conditional on the adjudication policy. The engine deliberately pushes per-caller identity OUT — `*creator*` is an unauthenticated annotation and the daemon's only auth is one shared bearer token — so koinii's answer is the context lattice, not a new auth subsystem: - **An agent IS its context.** Atlas writes into `CxAtlas`, lifted under the channel by `(genlCx CxDeploy CxAtlas)`. A reader of `CxDeploy` sees the union of every agent's assertions; `CxAtlas` alone is 'everything Atlas said' — a plain context read. Because context is part of sentex identity, Atlas's `P` and Boreas's `P` are two DISTINCT sentexes, each with its own creator, so first-writer-wins loses no co-source (`co-attribution-survives?`). - **The write boundary is 'your own context, and nothing else.'** That is the one enforcement point identity needs, and it is why the registry context is the one context agents may NOT write — the governed may not write the authority that governs them. The auth extension point is conditional on policy (koinii design D4): - **Cooperative** (the default) — `*creator*` bound by convention, the write routed to the agent's own context, trusted because the agents are. Correct for a notify-only deployment. It defends fat-fingers, NOT attackers: `authenticate` trusts the claimed id with no proof, so a client may claim any identity. State plainly that identity is unauthenticated here. - **Proof-tier** — REQUIRED the moment trust-resolve is enabled, because trust-weighting a spoofable identity is worse than no trust. `authenticate` verifies a credential (the `verify-fn` extension point — sign-at-ingest, an authenticating proxy, or A2A AgentCards / DIDs) and REFUSES an unverified request; `ingest` under the principal it mints attests each write with the deployment key (`*attest-key*`). Both checks run in the process that holds the key, never on the wire. Every write goes through the provenance-stamping `assert` path — NEVER `bulk-assert-facts!`, which binds `*bulk-load?*` and writes no provenance at all.
The deployment's HMAC-SHA256 key — a byte array or a string of at least 32 bytes — or
nil for a key drawn at random once per process. authenticate seals each principal it
verifies with it (:grant), and ingest under a sealed :proof-tier principal attests
each write with it (:attestation in provenance). The key itself lives in this var or
in the per-process draw, and no koinii fn writes it to provenance, a log, a refusal or
the wire. A deployment sets it at start with alter-var-root, or with binding. A
grant or attestation made under one key does not verify under another, so ballots
attested before a restart on the per-process key read unattested after it.
The deployment's HMAC-SHA256 key — a byte array or a string of at least 32 bytes — or nil for a key drawn at random once per process. `authenticate` seals each principal it verifies with it (`:grant`), and `ingest` under a sealed `:proof-tier` principal attests each write with it (`:attestation` in provenance). The key itself lives in this var or in the per-process draw, and no koinii fn writes it to provenance, a log, a refusal or the wire. A deployment sets it at start with `alter-var-root`, or with `binding`. A grant or attestation made under one key does not verify under another, so ballots attested before a restart on the per-process key read unattested after it.
The identity policy (koinii design D4).
:cooperative (the default) — *creator* is trusted by convention; correct for
a notify-only deployment. It defends fat-fingers, not attackers: a client may
claim any id, and there is no barrier to impersonation.:proof-tier — REQUIRED once trust-resolve is enabled; a credential is verified
at ingest and an unverified request is refused. Trust-weighting a spoofable
identity is worse than no trust.The identity policy (koinii design D4). - `:cooperative` (the default) — `*creator*` is trusted by convention; correct for a notify-only deployment. It defends fat-fingers, not attackers: a client may claim any id, and there is no barrier to impersonation. - `:proof-tier` — REQUIRED once trust-resolve is enabled; a credential is verified at ingest and an unverified request is refused. Trust-weighting a spoofable identity is worse than no trust.
The proof-tier verifier EXTENSION POINT: (verify-fn claimed-id credential) returns truthy
iff the credential proves the claim. nil ships no crypto — the design provides the
extension point (sign-at-ingest / an authenticating proxy / A2A AgentCards / DIDs) and the
deployment wires it. Under :proof-tier a nil verifier fails CLOSED: every
request is refused rather than silently trusted.
The proof-tier verifier EXTENSION POINT: `(verify-fn claimed-id credential)` returns truthy iff the credential proves the claim. nil ships no crypto — the design provides the extension point (sign-at-ingest / an authenticating proxy / A2A AgentCards / DIDs) and the deployment wires it. Under `:proof-tier` a nil verifier fails CLOSED: every request is refused rather than silently trusted.
(agent-context kb deploy-ctx agent-id)Create/lift agent-id's per-agent context under the channel deploy-ctx so the
channel sees it — (genlCx deploy-ctx CxAtlas) — and root it under CxCore so the
agent speaks the core vocabulary. Both edges are monotonic topology. Returns the
agent context symbol.
Create/lift `agent-id`'s per-agent context under the channel `deploy-ctx` so the channel sees it — `(genlCx deploy-ctx CxAtlas)` — and root it under `CxCore` so the agent speaks the core vocabulary. Both edges are monotonic topology. Returns the agent context symbol.
(agent-context-mark ctx agent)The sentence that says ctx is agent's own context — (agentContext CxAtlas AgentAtlas), written into ctx itself by place-agent-context. Pass '?agent for
the pattern that reads it back.
Why a written fact rather than a shape read off the lattice. context-for maps
AgentAtlas to CxAtlas by dropping a prefix, so an agent context is spelled exactly
like a channel and no name tells them apart; and the placement EDGES do not either,
because (genlCx ?parent ctx) and (genlCx ctx ?root) are the ordinary wiring of any
nested context — the same two edges under a channel rolled up into a wider one.
Inferring the role from them makes admission a function of what else has landed and of
which vocabulary a placement rooted at, which is order dependence in an entry point. A
positive stored fact is neither: it is written once by whoever placed the context, it
reads the same however the rest of the lattice grew, and every koinii placement route
writes it.
It lands in the agent's OWN context, which is the one context D8 already says the agent
writes — so recording it needs no privilege the agent does not have, and no agent can
mark a context it may not write. Under cooperative identity that boundary is an entry point
and not a wall (*policy*), exactly as it is for everything else the agent asserts.
The sentence that says `ctx` is `agent`'s own context — `(agentContext CxAtlas AgentAtlas)`, written into `ctx` itself by `place-agent-context`. Pass `'?agent` for the pattern that reads it back. **Why a written fact rather than a shape read off the lattice.** `context-for` maps `AgentAtlas` to `CxAtlas` by dropping a prefix, so an agent context is spelled exactly like a channel and no name tells them apart; and the placement EDGES do not either, because `(genlCx ?parent ctx)` and `(genlCx ctx ?root)` are the ordinary wiring of any nested context — the same two edges under a channel rolled up into a wider one. Inferring the role from them makes admission a function of what else has landed and of which vocabulary a placement rooted at, which is order dependence in an entry point. A positive stored fact is neither: it is written once by whoever placed the context, it reads the same however the rest of the lattice grew, and every koinii placement route writes it. It lands in the agent's OWN context, which is the one context D8 already says the agent writes — so recording it needs no privilege the agent does not have, and no agent can mark a context it may not write. Under cooperative identity that boundary is an entry point and not a wall (`*policy*`), exactly as it is for everything else the agent asserts.
(attested-by kb handle)The principal id whose ingest attested the sentex at handle under the current
*attest-key*, or nil when it carries no attestation that verifies. Only this process
holds the key, so a writer on the wire, or a caller of v/add-provenance, cannot make
one that does.
The principal id whose `ingest` attested the sentex at `handle` under the current `*attest-key*`, or nil when it carries no attestation that verifies. Only this process holds the key, so a writer on the wire, or a caller of `v/add-provenance`, cannot make one that does.
(authenticate request)(authenticate request opts)Turn a request into a principal, or refuse — the identity extension point.
request is {:claimed-id <id> :credential <opaque> :source <str> :admin? <bool>};
opts may override {:policy … :verify-fn …} (defaulting to *policy* /
*verify-fn*). Returns {:id :context :source :policy :authenticated?}, :context
being (context-for :id), plus a :grant sealing it under *attest-key* when the
identity was verified.
:cooperative — trusts the claimed id: :authenticated? false and no grant.:proof-tier — requires (verify-fn id credential) to pass, else throws
:koinii/identity-unverified.:admin? true, under either policy — mints the registry's one writer, :context
CxRegistry and :policy :admin. Requires (verify-fn id credential {:admin? true})
to pass, else throws :koinii/identity-unverified; a nil verify-fn, or one with no
three-argument arm, mints no admin.Turn a `request` into a principal, or refuse — the identity extension point.
`request` is `{:claimed-id <id> :credential <opaque> :source <str> :admin? <bool>}`;
`opts` may override `{:policy … :verify-fn …}` (defaulting to `*policy*` /
`*verify-fn*`). Returns `{:id :context :source :policy :authenticated?}`, `:context`
being `(context-for :id)`, plus a `:grant` sealing it under `*attest-key*` when the
identity was verified.
- `:cooperative` — trusts the claimed id: `:authenticated? false` and no grant.
- `:proof-tier` — requires `(verify-fn id credential)` to pass, else throws
`:koinii/identity-unverified`.
- `:admin? true`, under either policy — mints the registry's one writer, `:context`
`CxRegistry` and `:policy :admin`. Requires `(verify-fn id credential {:admin? true})`
to pass, else throws `:koinii/identity-unverified`; a nil verify-fn, or one with no
three-argument arm, mints no admin.(check-registry-write! who target-ctx)Throw if target-ctx is the admin registry; else return nil. The one boundary
that holds even in cooperative mode — where an agent may otherwise write across
contexts (the speech-act entry points take an explicit ctx for exactly that) — because the
governed may never write the authority that governs them (docs/koinii.md). Narrower
than check-write-boundary!, which also enforces own-context-only, a proof-tier rule
the cooperative entry points do not impose. who is named in the refusal for the log.
Throw if `target-ctx` is the admin registry; else return nil. The **one** boundary that holds even in cooperative mode — where an agent may otherwise write across contexts (the speech-act entry points take an explicit `ctx` for exactly that) — because the governed may never write the authority that governs them (docs/koinii.md). Narrower than `check-write-boundary!`, which also enforces own-context-only, a proof-tier rule the cooperative entry points do not impose. `who` is named in the refusal for the log.
(check-write-boundary! principal target-ctx)Throw if principal may not write target-ctx; else return nil. The single
enforcement point — the extension point a proof-tier deployment relies on, and the reason no
call site can route a write into a context it does not own.
Throw if `principal` may not write `target-ctx`; else return nil. The single enforcement point — the extension point a proof-tier deployment relies on, and the reason no call site can route a write into a context it does not own.
(co-attribution kb sentence)Every context that independently asserts sentence — the set of per-agent contexts
backing a claim. Because context is part of sentex identity, an agent re-asserting
a fact another already stated is a DISTINCT sentex in a DISTINCT context, so
first-writer-wins provenance loses no co-source: 'how many sources back P' is this
set, recovered from the per-agent contexts with no separate source index.
Every context that independently asserts `sentence` — the set of per-agent contexts backing a claim. Because context is part of sentex identity, an agent re-asserting a fact another already stated is a DISTINCT sentex in a DISTINCT context, so first-writer-wins provenance loses no co-source: 'how many sources back P' is this set, recovered from the per-agent contexts with no separate source index.
(context-for agent-id)The per-agent context for agent-id, by convention: AgentAtlas -> CxAtlas
(a leading Agent is dropped, then Cx-prefixed). The destination of an agent's
writes is a DETERMINISTIC function of its authenticated id, so 'write only your own
context' needs no separate lookup — identity fixes the destination, and a principal
can never be routed to a context that is not its own.
The per-agent context for `agent-id`, by convention: `AgentAtlas` -> `CxAtlas` (a leading `Agent` is dropped, then `Cx`-prefixed). The destination of an agent's writes is a DETERMINISTIC function of its authenticated id, so 'write only your own context' needs no separate lookup — identity fixes the destination, and a principal can never be routed to a context that is not its own.
(display-name-of kb agent-id)The stored display name for agent-id, or nil.
The stored display name for `agent-id`, or nil.
(ingest kb principal sentence)The sanctioned everyday write path. Given a principal from authenticate and a
sentence, assert it into the agent's OWN context with *creator* bound to the
principal id, so no call site can forget either the attribution or the routing. Under
:proof-tier the write is attested (attested-by reads it back), which is what makes
a ballot count (adjudication/resolve-by-majority). Returns the handle.
The sanctioned everyday write path. Given a `principal` from `authenticate` and a `sentence`, assert it into the agent's OWN context with `*creator*` bound to the principal id, so no call site can forget either the attribution or the routing. Under `:proof-tier` the write is attested (`attested-by` reads it back), which is what makes a ballot count (`adjudication/resolve-by-majority`). Returns the handle.
(ingest-into kb principal target-ctx sentence)The explicit-target write path, for a caller that names target-ctx — the write
goes through the SAME boundary check ingest does, so a principal authenticated as
Boreas targeting CxAtlas is refused (:koinii/foreign-context) and any governed
agent targeting CxRegistry is refused (:koinii/registry-forbidden). Returns the
handle.
The explicit-target write path, for a caller that names `target-ctx` — the write goes through the SAME boundary check `ingest` does, so a principal authenticated as Boreas targeting `CxAtlas` is refused (`:koinii/foreign-context`) and any governed agent targeting `CxRegistry` is refused (`:koinii/registry-forbidden`). Returns the handle.
(load-registry kb)Load the CxRegistry vocabulary into kb from resources/kb/koinii/CxRegistry.txt.
Koinii KB files are not auto-discovered (the starter only walks upper/ and
middle/), so this explicit loader is how the registry context comes into being.
Requires CxCore already loaded (CxRegistry wires (genlCx CxRegistry CxCore)).
Returns kb.
Load the CxRegistry vocabulary into `kb` from resources/kb/koinii/CxRegistry.txt. Koinii KB files are not auto-discovered (the starter only walks upper/ and middle/), so this explicit loader is how the registry context comes into being. Requires CxCore already loaded (CxRegistry wires `(genlCx CxRegistry CxCore)`). Returns kb.
(load-seed-context kb context)Assert every sentence of koinii's seed KB file for context into that context,
order-insensitively: a sentence refused because content further down the file has
not arrived yet is retried rather than fatal, so the file may be grouped term-centrically
rather than in dependency order. The sentences that survive a round changing nothing are
re-asserted without a catch, so a genuinely ill-formed one still throws. Returns kb.
Assert every sentence of koinii's seed KB file for `context` into that context, **order-insensitively**: a sentence refused because content further down the file has not arrived yet is retried rather than fatal, so the file may be grouped term-centrically rather than in dependency order. The sentences that survive a round changing nothing are re-asserted without a catch, so a genuinely ill-formed one still throws. Returns kb.
(place-agent-context write! parent agent-id roots)Place agent-id's per-agent context (context-for) in the lattice: LIFTED under
parent so the parent sees the agent's writes — (genlCx parent CxAtlas) — ROOTED
under roots so the agent speaks that vocabulary and the rules over it fire, and
MARKED as the agent's own (agent-context-mark) so a later reader can tell an agent's
context from a channel. All three are :monotonic and idempotent, so re-placing an
agent is a no-op; the two edges are topology in CxUniverse, the mark is a fact about
the context and lands in it. Returns the agent context symbol.
The three writes in one place, and write! is what lets them be. A channel writes
through its Medium (for a wire handle, the daemon), a plain caller writes straight
to a KB — so the writer is the argument: write! is (fn [sentence context opts] …).
Every koinii placement — agent-context here, speech-acts/speaker-context,
channel/join, adjudication's arbiter — is this trio under a different parent and a
different root, which is what makes the mark true of an agent context however it was
placed.
Place `agent-id`'s per-agent context (`context-for`) in the lattice: LIFTED under `parent` so the parent sees the agent's writes — `(genlCx parent CxAtlas)` — ROOTED under `roots` so the agent speaks that vocabulary and the rules over it fire, and MARKED as the agent's own (`agent-context-mark`) so a later reader can tell an agent's context from a channel. All three are `:monotonic` and idempotent, so re-placing an agent is a no-op; the two edges are topology in `CxUniverse`, the mark is a fact about the context and lands in it. Returns the agent context symbol. **The three writes in one place, and `write!` is what lets them be.** A channel writes through its `Medium` (for a `wire` handle, the daemon), a plain caller writes straight to a KB — so the writer is the argument: `write!` is `(fn [sentence context opts] …)`. Every koinii placement — `agent-context` here, `speech-acts/speaker-context`, `channel/join`, `adjudication`'s arbiter — is this trio under a different parent and a different root, which is what makes the mark true of an agent context however it was placed.
(register-agent kb principal agent-id display-name trust)Register agent-id in CxRegistry — its membership mark, display name, and
bootstrap trust value — as the admin principal, minted by authenticate with
:admin? true. Refused (:koinii/registry-forbidden) for any other principal,
a hand-built {:admin? true} included, so a governed agent cannot self-register or
self-promote. Returns the agent id.
Register `agent-id` in `CxRegistry` — its membership mark, display name, and
bootstrap trust value — as the admin `principal`, minted by `authenticate` with
`:admin? true`. Refused (`:koinii/registry-forbidden`) for any other principal,
a hand-built `{:admin? true}` included, so a governed agent cannot self-register or
self-promote. Returns the agent id.(registered-agents kb)Every registered agent id — the extent of (agent ?a) in CxRegistry. 'Which
agents exist' as a plain context-scoped read.
Every registered agent id — the extent of `(agent ?a)` in `CxRegistry`. 'Which agents exist' as a plain context-scoped read.
The admin-only registry context. The one context governed agents may not write.
The admin-only registry context. The one context governed agents may not write.
(set-trust! kb principal agent-id new-value)OVERWRITE agent-id's trust with new-value, as the admin principal (D3: trust
is a mutable number). trustLevel is functional, so the update retracts the old
value and asserts the new rather than accumulating two. Refused for any principal
but an admin authenticate minted. Returns the new handle.
The row it retracts is read through sole-registry-match, whose docstring holds the
reason: the overwrite must not rest on an unordered set having exactly one member.
OVERWRITE `agent-id`'s trust with `new-value`, as the admin `principal` (D3: trust is a mutable number). `trustLevel` is functional, so the update retracts the old value and asserts the new rather than accumulating two. Refused for any principal but an admin `authenticate` minted. Returns the new handle. The row it retracts is read through `sole-registry-match`, whose docstring holds the reason: the overwrite must not rest on an unordered set having exactly one member.
(trust-of kb agent-id)The stored trust number for agent-id, or nil — a plain context-scoped read of
CxRegistry, ready for adjudication to weigh.
The stored trust number for `agent-id`, or nil — a plain context-scoped read of `CxRegistry`, ready for adjudication to weigh.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |