Prompt assembly.
Provider messages are explicit blocks in send order: core system rules,
project instructions (AGENTS.md / CLAUDE.md when present), extension
fragments, current user message. Per-iteration user-role context is the
engine snapshot rendered as a Python dict (session) by the loop.
Prompt assembly. Provider messages are explicit blocks in send order: core system rules, project instructions (AGENTS.md / CLAUDE.md when present), extension fragments, current user message. Per-iteration user-role context is the engine snapshot rendered as a Python dict (`session`) by the loop.
(active-extensions environment)Returns the seq of registered extensions whose :ext/activation-fn returns
truthy for environment, in registration order. Single source of truth for
activation; call ONCE at the top of a turn.
Returns the seq of registered extensions whose `:ext/activation-fn` returns truthy for `environment`, in registration order. Single source of truth for activation; call ONCE at the top of a turn.
(assemble-initial-messages {:keys [stable-prompt-messages initial-user-content
previous-turn-context turn-context
user-images skipped-images vision?]
:or {vision? true}})Initial provider messages for one turn.
Prior RESUME entries are emitted as one stable user message per turn (or
materialized fold checkpoint), so adding a turn appends a message instead of
rewriting one monolithic conversation recap. :turn-context is the current
append-only turn/utilization assignment block and rides immediately before
the current user request.
Initial provider messages for one turn. Prior RESUME entries are emitted as one stable user message per turn (or materialized fold checkpoint), so adding a turn appends a message instead of rewriting one monolithic conversation recap. `:turn-context` is the current append-only turn/utilization assignment block and rides immediately before the current user request.
(assemble-stable-prompt-messages
environment
{:keys [system-prompt active-extensions session-context] :as opts})Assemble provider-prefix messages.
Send order is explicit and tested:
SYSTEM-PROMPT - CORE_SYSTEM_PROMPT + caller addendum
PROJECT-INSTRUCTIONS - AGENTS.md / CLAUDE.md contents (when present)
TURN-SYSTEM-CONTEXT - turn-scoped runtime capability context. Today
it contains extension prompt fragments; future
message, never append a second extension
context.
Extension fragments are separate from the core system prompt and are not repeated in per-iteration trailers.
Required opts:
:active-extensions - vec from (active-extensions env). Drives
environment, extension prompt, and hint collection.
Optional opts:
:system-prompt - caller addendum appended to CORE.
:session-context - rendered fenced-Python session = {…} block
(standing session state: workspace / env / routing / tools). Embedded
ONCE here as a cached system message; the loop re-emits only the
session[...] = … structural delta in the conversation when it changes
mid-turn.
Assemble provider-prefix messages.
Send order is explicit and tested:
`SYSTEM-PROMPT` - CORE_SYSTEM_PROMPT + caller addendum
`PROJECT-INSTRUCTIONS` - AGENTS.md / CLAUDE.md contents (when present)
`TURN-SYSTEM-CONTEXT` - turn-scoped runtime capability context. Today
it contains extension prompt fragments; future
message, never append a second extension
context.
Extension fragments are separate from the core system prompt and are not
repeated in per-iteration trailers.
Required opts:
`:active-extensions` - vec from `(active-extensions env)`. Drives
environment, extension prompt, and hint collection.
Optional opts:
`:system-prompt` - caller addendum appended to CORE.
`:session-context` - rendered fenced-Python `session = {…}` block
(standing session state: workspace / env / routing / tools). Embedded
ONCE here as a cached system message; the loop re-emits only the
`session[...] = …` structural delta in the conversation when it changes
mid-turn.(build-system-prompt {:keys [system-prompt]})Core system prompt + optional caller addendum + config prompt + SYSTEM.md / APPEND_SYSTEM.md file overrides.
Assembled in send order (later blocks positionally reinforce earlier):
base, then the caller's :system-prompt addendum, then the
:system-prompt pulled from Vis config (~/.vis/config.yml / state.yml /
<project>/vis.yml / .vis/config.yml, deep-merged), then ~/.vis/APPEND_SYSTEM.md, then
<workspace>/.vis/APPEND_SYSTEM.md. The config + file hooks let a project
append house rules without any caller having to pass them.
Full rewrite precedence for the base: <workspace>/.vis/SYSTEM.md >
~/.vis/SYSTEM.md > config :system-prompt map with :replace? true >
CORE_SYSTEM_PROMPT. When a file/config replaces the base, addenda and
append files are still appended after it.
Core system prompt + optional caller addendum + config prompt + SYSTEM.md / APPEND_SYSTEM.md file overrides. Assembled in send order (later blocks positionally reinforce earlier): base, then the caller's `:system-prompt` addendum, then the `:system-prompt` pulled from Vis config (`~/.vis/config.yml` / `state.yml` / `<project>/vis.yml` / `.vis/config.yml`, deep-merged), then `~/.vis/APPEND_SYSTEM.md`, then `<workspace>/.vis/APPEND_SYSTEM.md`. The config + file hooks let a project append house rules without any caller having to pass them. Full rewrite precedence for the base: `<workspace>/.vis/SYSTEM.md` > `~/.vis/SYSTEM.md` > config `:system-prompt` map with `:replace? true` > `CORE_SYSTEM_PROMPT`. When a file/config replaces the base, addenda and append files are still appended after it.
Override injected ONLY for the non-interactive :cli channel (headless
bin/vis '<task>' one-shot runs). No human is in the loop, so the model
must never wait for input — it makes reasonable assumptions and drives the
work to a finished prose answer.
Override injected ONLY for the non-interactive `:cli` channel (headless `bin/vis '<task>'` one-shot runs). No human is in the loop, so the model must never wait for input — it makes reasonable assumptions and drives the work to a finished prose answer.
(extensions-snapshot active-extensions)Build the active extension summary placed under (:extensions ctx) from a
precomputed active-extensions vec.
Returns a vec of compact, fully-realized data maps - NO functions,
NO atoms, NO opaque runtime objects. The model walks this with a
comprehension / filter / any exactly like any other Python list of
dicts; never has to reach into an extensions() call just to discover
what's loaded.
Per element:
:alias - short symbol the model calls under ('v, 'z,
'git, ...). nil when the extension didn't declare
an :ext.engine/alias.
:namespace - fully-qualified ns symbol of the extension.
:doc - one-line LLM description from :ext/description (when set).
:kind - categorical bucket (providers, channels, foundation,
languages, persistance, ...) used as the section
label both in this snapshot and in vis extension list (when set).
:registry-id - canonical manifest id, usually the alias symbol.
:symbols - vec of bare symbol names the extension intern'd into
the sandbox.
The vec is bound ONCE at turn start (see iteration-loop) and
stays frozen for the rest of the turn - every iteration sees the
same value.
Build the active extension summary placed under `(:extensions ctx)` from a
precomputed active-extensions vec.
Returns a vec of compact, fully-realized data maps - NO functions,
NO atoms, NO opaque runtime objects. The model walks this with a
comprehension / `filter` / `any` exactly like any other Python list of
dicts; never has to reach into an `extensions()` call just to discover
what's loaded.
Per element:
:alias - short symbol the model calls under (`'v`, `'z`,
`'git`, ...). nil when the extension didn't declare
an `:ext.engine/alias`.
:namespace - fully-qualified ns symbol of the extension.
:doc - one-line LLM description from `:ext/description` (when set).
:kind - categorical bucket (providers, channels, foundation,
languages, persistance, ...) used as the section
label both in this snapshot and in `vis extension
list` (when set).
:registry-id - canonical manifest id, usually the alias symbol.
:symbols - vec of bare symbol names the extension intern'd into
the sandbox.
The vec is bound ONCE at turn start (see `iteration-loop`) and
stays frozen for the rest of the turn - every iteration sees the
same value.(previous-turn-context-block turns)Render prior-turn RESUME entries. Normal entries retain their stable turn
number and Q/A/result index. A :checkpoint? entry is the sole materialized
replacement for all complete turns covered by one broader fold.
Render prior-turn RESUME entries. Normal entries retain their stable turn number and Q/A/result index. A `:checkpoint?` entry is the sole materialized replacement for all complete turns covered by one broader fold.
(stable-prompt-text messages)Join stable prompt message contents for token budgeting and debug bindings only. Provider sends the original message vector; this is not a send path.
Join stable prompt message contents for token budgeting and debug bindings only. Provider sends the original message vector; this is not a send path.
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 |