Liking cljdoc? Tell your friends :D

vaelii.agents.engine

The vaelii.host.* vars this repo reads, and the one namespace in vaelii.agents.* that reaches for them. vaelii.host.* is the engine's tooling tier, private and free to change, so a breaking change upstream is an edit here. Each var is the engine's own under the name the callers use.

The daemon's op tables (vaelii.host.serve): ops, kbless-ops, feed-ops and write-ops. vaelii.agents.tools generates the model's tool schemas from the read subset of ops and dispatches tool calls back through it, so a model's reads are the daemon's reads with no second copy.

vaelii.agents.mcp.* (the MCP server) reaches further than vaelii.agents.tools does: its write verbs (assert, unassert) have to reconstruct, ahead of a write, every predicate a sentence's assert would actually store — rule surfaces, ist nesting, except/exceptWhen peeling, forall desugaring, storage-context resolution — work vaelii.core does not expose a single call for. The vars below are that reach, one per engine fn the server calls outside vaelii.core: require-token!, api-token and public-bind? (vaelii.host.guard); register-cache (vaelii.impl.caches); read-forms and load-entries! (vaelii.impl.io.text); context? and literals (vaelii.impl.naming); ist-parts and storage-context (vaelii.impl.assert-entry); soft-priority-surface?, cardinality-surface?, minimize-surface?, split-exceptWhen, inner-rule and expand-rule (vaelii.impl.rules); free-vars, conjunction?, peel-exception-strength, forall?, desugar-forall-literal, defn-sentence?, rule-functor and sentex-handle (vaelii.impl.sentex); substitute and unify (vaelii.impl.resolution). None of this is vaelii.host.* or vaelii.impl.* surface this repo would propose keeping stable on its own account — every var here is a candidate for a vaelii.core read a write-verb author would otherwise have to duplicate (see this repo's README, "Reaching into the engine", and docs/mcp.md, "Engine reach", which proposes the vaelii.core entry point).

The `vaelii.host.*` vars this repo reads, and the one namespace in `vaelii.agents.*`
that reaches for them.  `vaelii.host.*` is the engine's tooling tier, private and free
to change, so a breaking change upstream is an edit here.  Each var is the engine's
own under the name the callers use.

The daemon's op tables (`vaelii.host.serve`): [[ops]], [[kbless-ops]], [[feed-ops]] and
[[write-ops]].
`vaelii.agents.tools` generates the model's tool schemas from the read subset of
[[ops]] and dispatches tool calls back through it, so a model's reads are the daemon's
reads with no second copy.

`vaelii.agents.mcp.*` (the MCP server) reaches further than `vaelii.agents.tools` does:
its write verbs (`assert`, `unassert`) have to reconstruct, ahead of a write, every
predicate a sentence's assert would actually store — rule surfaces, `ist` nesting,
`except`/`exceptWhen` peeling, `forall` desugaring, storage-context resolution — work
`vaelii.core` does not expose a single call for. The vars below are that reach, one
per engine fn the server calls outside `vaelii.core`:
[[require-token!]], [[api-token]] and [[public-bind?]] (`vaelii.host.guard`);
[[register-cache]] (`vaelii.impl.caches`); [[read-forms]] and [[load-entries!]]
(`vaelii.impl.io.text`); [[context?]] and [[literals]] (`vaelii.impl.naming`);
[[ist-parts]] and [[storage-context]] (`vaelii.impl.assert-entry`);
[[soft-priority-surface?]], [[cardinality-surface?]], [[minimize-surface?]],
[[split-exceptWhen]], [[inner-rule]] and [[expand-rule]] (`vaelii.impl.rules`);
[[free-vars]], [[conjunction?]], [[peel-exception-strength]], [[forall?]],
[[desugar-forall-literal]], [[defn-sentence?]], [[rule-functor]] and
[[sentex-handle]] (`vaelii.impl.sentex`); [[substitute]] and [[unify]]
(`vaelii.impl.resolution`). None of this is `vaelii.host.*` or `vaelii.impl.*`
surface this repo would propose keeping stable on its own account — every var here
is a candidate for a `vaelii.core` read a write-verb author would otherwise have to
duplicate (see this repo's README, "Reaching into the engine", and docs/mcp.md,
"Engine reach", which proposes the `vaelii.core` entry point).
raw docstring

vaelii.agents.llm.anthropic

The Anthropic Messages API backend, over java.net.http and cheshire. Beyond the neutral request keys it reads :thinking-display and :fallbacks. See docs/llm.md § The Messages API backend.

The Anthropic Messages API backend, over `java.net.http` and `cheshire`.  Beyond the
neutral request keys it reads `:thinking-display` and `:fallbacks`.  See docs/llm.md
§ The Messages API backend.
raw docstring

vaelii.agents.llm.http

The part of an HTTP provider's transport that is not its wire format: the connect and read deadlines, the typed send, the not-JSON refusal, the bounded excerpt. Each fn takes an endpoint {:label :slug}: :label names the far end in a message, :slug in a thread name. See docs/llm.md § What both HTTP backends share.

The part of an HTTP provider's transport that is not its wire format: the connect and
read deadlines, the typed send, the not-JSON refusal, the bounded excerpt.  Each fn
takes an endpoint
`{:label :slug}`: `:label` names the far end in a message, `:slug` in a thread name.
See docs/llm.md § What both HTTP backends share.
raw docstring

vaelii.agents.llm.ollama

The Ollama chat API backend, over java.net.http and cheshire, plus the host probes. Beyond the neutral request keys it reads :temperature and :keep-alive. See docs/llm.md § The local backend.

The Ollama chat API backend, over `java.net.http` and `cheshire`, plus the host
probes.  Beyond the neutral request keys it reads `:temperature` and `:keep-alive`.
See docs/llm.md § The local backend.
raw docstring

vaelii.agents.llm.pool

A yes/no question put to a model several times across a pool of Ollama hosts, and the vote over the answers. See docs/llm.md § The vote pool.

A yes/no question put to a model several times across a pool of Ollama hosts, and
the vote over the answers.  See docs/llm.md § The vote pool.
raw docstring

vaelii.agents.llm.protocol

The Provider extension point: two methods over a provider-neutral request and response map, neither naming HTTP, JSON or a vendor field. See docs/llm.md § Providers.

Request:

{:model      "claude-opus-5-5"   ; provider-resolved when absent
 :system     [{:text "…" :cache? true} …]   ; blocks, in order
 :messages   [{:role "user"|"assistant" :content <string | [block …]}]
 :tools      [<tool schema> …]      ; vaelii.agents.tools/schemas
 :format     {…}                    ; a JSON schema decoding is constrained to
 :max-tokens 8192
 :effort     "low"|"medium"|"high"|"xhigh"|"max"
 :thinking-display "summarized"     ; Anthropic only
 :num-ctx    8192}                  ; context length, tokens; local providers only

:cache? on a system block asks for a cache breakpoint after it. This list is the whole of what a provider reads, so a key any path sends belongs here. A provider ignores a key it cannot express: :cache? on Ollama, :num-ctx on Anthropic.

Response:

{:stop-reason  "end_turn"|"tool_use"|"refusal"|"max_tokens"|…
 :stop-details {…}                ; populated only on a refusal
 :content      [{:type :text     :text "…"}
                {:type :tool-use :id "…" :name "…" :input {…}}
                {:type :thinking :text "…"}]
 :model        "…"
 :usage        {…}}

A refusal is a successful answer with empty or partial :content: a caller reads :stop-reason first, and a provider never fabricates a text block. Assistant content is echoed back verbatim in the next request's :messages, so a provider may carry its own vendor blocks through :content.

The `Provider` extension point: two methods over a provider-neutral request and
response map, neither naming HTTP, JSON or a vendor field.  See docs/llm.md § Providers.

Request:

    {:model      "claude-opus-5-5"   ; provider-resolved when absent
     :system     [{:text "…" :cache? true} …]   ; blocks, in order
     :messages   [{:role "user"|"assistant" :content <string | [block …]}]
     :tools      [<tool schema> …]      ; vaelii.agents.tools/schemas
     :format     {…}                    ; a JSON schema decoding is constrained to
     :max-tokens 8192
     :effort     "low"|"medium"|"high"|"xhigh"|"max"
     :thinking-display "summarized"     ; Anthropic only
     :num-ctx    8192}                  ; context length, tokens; local providers only

`:cache?` on a system block asks for a cache breakpoint after it.  This list is the
whole of what a provider reads, so a key any path sends belongs here.  A provider
ignores a key it cannot express: `:cache?` on Ollama, `:num-ctx` on Anthropic.

Response:

    {:stop-reason  "end_turn"|"tool_use"|"refusal"|"max_tokens"|…
     :stop-details {…}                ; populated only on a refusal
     :content      [{:type :text     :text "…"}
                    {:type :tool-use :id "…" :name "…" :input {…}}
                    {:type :thinking :text "…"}]
     :model        "…"
     :usage        {…}}

A refusal is a successful answer with empty or partial `:content`: a caller reads
`:stop-reason` first, and a provider never fabricates a text block.  Assistant content
is echoed back verbatim in the next request's `:messages`, so a provider may carry its
own vendor blocks through `:content`.
raw docstring

vaelii.agents.llm.provider

Which backend a turn runs against: :stub (the default), :ollama or :anthropic, resolved lazily, with an unreachable backend falling back to the stub. Every fn here that can build a stub reads that stub's own opts (vaelii.agents.llm.stub/provider) from opts's :stub, and hands a backend opts without it. See docs/llm.md § Choosing one.

Which backend a turn runs against: `:stub` (the default), `:ollama` or `:anthropic`,
resolved lazily, with an unreachable backend falling back to the stub.  Every fn here
that can build a stub reads that stub's own opts (`vaelii.agents.llm.stub/provider`)
from `opts`'s `:stub`, and hands a backend `opts` without it.  See docs/llm.md
§ Choosing one.
raw docstring

vaelii.agents.llm.stub

The default provider: deterministic, offline, no credential, and scripted. See docs/llm.md § The stub is the default.

A :script entry is a full response map, or one of these shorthands:

"some text" a plain text answer {:tool "kb_sentexes_matching" :input {…}} a tool-use turn (:id, :prose optional)

A caller with answer shapes of its own passes :expand, which sees each map entry first.

The default provider: deterministic, offline, no credential, and scripted.  See
docs/llm.md § The stub is the default.

A `:script` entry is a full response map, or one of these shorthands:

  "some text"                                a plain text answer
  {:tool "kb_sentexes_matching" :input {…}}  a tool-use turn (`:id`, `:prose` optional)

A caller with answer shapes of its own passes `:expand`, which sees each map entry
first.
raw docstring

vaelii.agents.mcp.argue

Four-valued epistemic status for ground assertions.

Queries both a sentence and its explicit negation (not S) and returns a verdict map with :verdict, :for, :against, and justification evidence.

Two query modes:

  • No opts: uses ask? (ground facts + prover registry, no rule expansion)
  • With opts containing :max-depth: uses query (rules fire, bounded)

Callers who want rule expansion MUST pass {:max-depth N} explicitly. A silent default depth would turn derivable facts into false :unknown.

Four-valued epistemic status for ground assertions.

Queries both a sentence and its explicit negation (not S) and returns
a verdict map with :verdict, :for, :against, and justification evidence.

Two query modes:
- No opts: uses `ask?` (ground facts + prover registry, no rule expansion)
- With opts containing :max-depth: uses `query` (rules fire, bounded)

Callers who want rule expansion MUST pass {:max-depth N} explicitly.
A silent default depth would turn derivable facts into false :unknown.
raw docstring

vaelii.agents.mcp.audit

Pure v1 audit-record construction, validation, normalization, and hashing.

This namespace performs no I/O and does not invent journal metadata. The durable writer (vaelii.agents.mcp.dispatcher's JournalAuditSink) adds record identity, sequence, and server time at the commit point.

Pure v1 audit-record construction, validation, normalization, and hashing.

This namespace performs no I/O and does not invent journal metadata. The
durable writer (`vaelii.agents.mcp.dispatcher`'s `JournalAuditSink`) adds
record identity, sequence, and server time at the commit point.
raw docstring

vaelii.agents.mcp.config

Server configuration reader.

A config file maps bearer-token fingerprints to stable principal IDs and fork IDs. Raw tokens never appear in the config — only their SHA-256 hex digest.

EDN format:

{:state-dir "path/to/authority" :forks-dir "path/to/forks" :principals {"alice" {:token-sha256 "abcdef..." :fork-id "alice" :lifecycle :durable} "bob" {:token-sha256 "012345..." :fork-id "bob" :lifecycle :durable}}}

All paths are resolved relative to the config file's parent directory. Unknown top-level keys are rejected (closed schema). :state-dir is ALWAYS required — even all-leased configs need durable authority.

Server configuration reader.

A config file maps bearer-token fingerprints to stable principal IDs and
fork IDs.  Raw tokens never appear in the config — only their SHA-256 hex
digest.

EDN format:

  {:state-dir     "path/to/authority"
   :forks-dir     "path/to/forks"
   :principals
   {"alice" {:token-sha256 "abcdef..."
             :fork-id      "alice"
             :lifecycle    :durable}
    "bob"   {:token-sha256 "012345..."
             :fork-id      "bob"
             :lifecycle    :durable}}}

All paths are resolved relative to the config file's parent directory.
Unknown top-level keys are rejected (closed schema).
:state-dir is ALWAYS required — even all-leased configs need durable authority.
raw docstring

vaelii.agents.mcp.dispatcher

Transport-neutral MCP dispatch with A1 audit integration and effect fencing.

Audit lifecycle per request:

  1. Health-check the A1 sink → refuse if unhealthy
  2. Mint operation_id
  3. Record durable Attempt → refuse if fails
  4. Acquire generation permit from session registry
  5. Check permit at mutation boundary (inside verb execution)
  6. Execute verb
  7. Record durable Completion → error handling per effect certainty
  8. Return response

Fencing: the generation counter in the session registry increments on revocation or lease retirement. A permit acquired at admission is checked before the mutation commits. If the generation changed, the mutation is refused even though the session was valid at admission time.

Transport-neutral MCP dispatch with A1 audit integration and effect fencing.

Audit lifecycle per request:
  1. Health-check the A1 sink → refuse if unhealthy
  2. Mint operation_id
  3. Record durable Attempt → refuse if fails
  4. Acquire generation permit from session registry
  5. Check permit at mutation boundary (inside verb execution)
  6. Execute verb
  7. Record durable Completion → error handling per effect certainty
  8. Return response

Fencing: the generation counter in the session registry increments on
revocation or lease retirement. A permit acquired at admission is checked
before the mutation commits. If the generation changed, the mutation is
refused even though the session was valid at admission time.
raw docstring

vaelii.agents.mcp.http-transport

Streamable HTTP transport for the Vaelii MCP server.

Implements MCP Streamable HTTP (POST/DELETE/GET on /mcp) and the POST /op raw-operation route. Service handle owns Jetty + lease sweeper; stop is idempotent.

Streamable HTTP transport for the Vaelii MCP server.

Implements MCP Streamable HTTP (POST/DELETE/GET on /mcp) and the POST /op
raw-operation route.
Service handle owns Jetty + lease sweeper; stop is idempotent.
raw docstring

vaelii.agents.mcp.kb-utils

Small helpers over vaelii.core that vaelii.agents.mcp.overlay needs and vaelii.core does not itself provide.

Small helpers over `vaelii.core` that `vaelii.agents.mcp.overlay` needs and
`vaelii.core` does not itself provide.
raw docstring

vaelii.agents.mcp.overlay

An overlay knowledge loader: a directory's excepts.edn and *.clj files into the base KB at server start, each file into the context contexts.edn names for it. Kept out of vaelii.agents.mcp.server, which calls load-overlay! once, so the server file stays a near copy of the shape a non-overlay deployment would use.

An overlay knowledge loader: a directory's `excepts.edn` and `*.clj` files
into the base KB at server start, each file into the context `contexts.edn`
names for it. Kept out of `vaelii.agents.mcp.server`, which calls
`load-overlay!` once, so the server file stays a near copy of the shape a
non-overlay deployment would use.
raw docstring

vaelii.agents.mcp.server

Production entry point for the Vaelii MCP server.

A4: The production startup path MUST NOT construct a RecordingAuditSink or any in-memory test sink. The A1 adapter is mandatory.

Production entry point for the Vaelii MCP server.

A4: The production startup path MUST NOT construct a RecordingAuditSink
or any in-memory test sink. The A1 adapter is mandatory.
raw docstring

vaelii.agents.mcp.session

Session registry with durable, linearizable security authority.

ALL mutable state lives in ONE atom: sessions, revoked principals, fork KBs, fork metadata, and a monotonic generation counter.

Authority changes (revocation, restoration, provisioning, lease retirement) are commit-before-ack: the durable store is written BEFORE in-memory state becomes less restrictive.

The generation counter increments on every revocation, restoration, or lease retirement. Dispatchers acquire a permit (generation snapshot) at admission; the mutation boundary checks the permit is still current.

Three lifetimes: connection ≠ session ≠ fork

Session registry with durable, linearizable security authority.

ALL mutable state lives in ONE atom: sessions, revoked principals,
fork KBs, fork metadata, and a monotonic generation counter.

Authority changes (revocation, restoration, provisioning, lease retirement)
are commit-before-ack: the durable store is written BEFORE in-memory state
becomes less restrictive.

The generation counter increments on every revocation, restoration, or lease
retirement. Dispatchers acquire a permit (generation snapshot) at admission;
the mutation boundary checks the permit is still current.

Three lifetimes:  connection ≠ session ≠ fork
raw docstring

vaelii.agents.mcp.transport

MCP JSON-RPC 2.0 transport over stdio.

Reads newline-delimited JSON-RPC messages from stdin, dispatches them through the transport-neutral dispatcher, and writes JSON-RPC responses to stdout. Stderr is reserved for server-side logging.

This transport owns:

  • Reading bytes from stdin, writing bytes to stdout
  • Parsing/serializing JSON
  • Authentication (token extraction from initialize or env var)

This transport does NOT own:

  • MCP method routing (dispatcher's job)
  • Session/verb semantics (dispatcher's job)
  • HTTP concepts (Streamable HTTP adapter is separate)
MCP JSON-RPC 2.0 transport over stdio.

Reads newline-delimited JSON-RPC messages from stdin, dispatches them
through the transport-neutral dispatcher, and writes JSON-RPC responses
to stdout.  Stderr is reserved for server-side logging.

This transport owns:
  - Reading bytes from stdin, writing bytes to stdout
  - Parsing/serializing JSON
  - Authentication (token extraction from initialize or env var)

This transport does NOT own:
  - MCP method routing (dispatcher's job)
  - Session/verb semantics (dispatcher's job)
  - HTTP concepts (Streamable HTTP adapter is separate)
raw docstring

vaelii.agents.mcp.verbs

The six MCP verb tools — assert, unassert, unassert-handle, query, argue, matching — the write-and-read surface an MCP client reaches a fork KB through.

Each verb is a map → map function: JSON-shaped input (string keys, EDN values carried as strings) → a Clojure result map the transport serializes to JSON. Errors are maps with :mcp-error true, never thrown — the transport layer decides how to encode them (a JSON-RPC error, an MCP error content block, etc.).

Fork injection. Every verb receives the fork KB through the dynamic var *mcp-kb*, which the MCP server binds per request. The verbs never see the base KB directly; the fork's overlay isolates their writes.

Strength cap. An MCP client may assert at :default only — never :monotonic. The cap is enforced here, before the call reaches vaelii.core, so a client cannot promote a belief past the fork's own defeat semantics.

EDN coercion. Sentence, goal, and context arguments arrive as JSON strings holding EDN s-expressions. Parsed with clojure.edn/read-string (never read-string) — EDN has no reader-eval, so a client's output cannot execute code.

Wire format. Results are Clojure maps serialized to JSON by the transport. Handles are longs. Bindings are maps of string keys to EDN-string values.

The six MCP verb tools — `assert`, `unassert`, `unassert-handle`, `query`,
`argue`, `matching` — the write-and-read surface an MCP client reaches a fork KB through.

Each verb is a map → map function: JSON-shaped input (string keys, EDN values
carried as strings) → a Clojure result map the transport serializes to JSON.
Errors are maps with `:mcp-error true`, never thrown — the transport layer
decides how to encode them (a JSON-RPC error, an MCP error content block, etc.).

**Fork injection.**  Every verb receives the fork KB through the dynamic var
`*mcp-kb*`, which the MCP server binds per request.  The verbs never see the
base KB directly; the fork's overlay isolates their writes.

**Strength cap.**  An MCP client may assert at `:default` only — never
`:monotonic`.  The cap is enforced here, before the call reaches `vaelii.core`,
so a client cannot promote a belief past the fork's own defeat semantics.

**EDN coercion.**  Sentence, goal, and context arguments arrive as JSON strings
holding EDN s-expressions.  Parsed with `clojure.edn/read-string` (never
`read-string`) — EDN has no reader-eval, so a client's output cannot execute
code.

**Wire format.**  Results are Clojure maps serialized to JSON by the transport.
Handles are longs.  Bindings are maps of string keys to EDN-string values.
raw docstring

vaelii.agents.tools

The model's read tools, generated from the read subset of the engine daemon's op table (vaelii.agents.engine/ops) and dispatched back through it. No tool writes. See docs/llm.md § Tools.

The model's read tools, generated from the read subset of the engine daemon's op
table (`vaelii.agents.engine/ops`) and dispatched back through it.  No tool
writes.  See docs/llm.md § Tools.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close