vis-agent CLI binary - :db Telemere handler, one-shot agent helper,
built-in CLI commands, and the -main dispatcher entry point.
Everything in this file is binary-only. The library surface
(iteration loop, turn engine, environment lifecycle, session
cache) lives in com.blockether.vis.internal.loop; this namespace requires
that one and wires it into the command tree the vis-agent wrapper
exposes.
Public entry point:
(-main & args) - invoked by the :vis alias / bin/vis-agent.
Configures logging, discovers Clojure extensions, loads Python
extensions before one-shot dispatches, redirects stderr to this
process's role/start-time/pid-stamped file under ~/.vis/logs/ for
any TTY-owning channel, then dispatches to the resolved
command's :cmd/run-fn.
Built-in commands registered here: vis-agent providers - provider inspection, auth, and limits vis-agent sessions - list persisted sessions vis-agent projects - list projects, or delete one with its sessions vis-agent extension list - list registered extensions vis-agent channels <name> - auto-mounted via the channel registry
vis-agent doctor is host-owned. Extensions plug diagnostics into it
with :ext/doctor-fn; extension-owned CLI commands stay under
vis-agent extension.
vis-agent CLI binary - :db Telemere handler, one-shot agent helper,
built-in CLI commands, and the `-main` dispatcher entry point.
Everything in this file is binary-only. The library surface
(iteration loop, turn engine, environment lifecycle, session
cache) lives in `com.blockether.vis.internal.loop`; this namespace requires
that one and wires it into the command tree the `vis-agent` wrapper
exposes.
Public entry point:
(-main & args) - invoked by the `:vis` alias / `bin/vis-agent`.
Configures logging, discovers Clojure extensions, loads Python
extensions before one-shot dispatches, redirects stderr to this
process's role/start-time/pid-stamped file under `~/.vis/logs/` for
any TTY-owning channel, then dispatches to the resolved
command's `:cmd/run-fn`.
Built-in commands registered here:
vis-agent providers - provider inspection, auth, and limits
vis-agent sessions - list persisted sessions
vis-agent projects - list projects, or delete one with its sessions
vis-agent extension list - list registered extensions
vis-agent channels <name> - auto-mounted via the channel registry
`vis-agent doctor` is host-owned. Extensions plug diagnostics into it
with `:ext/doctor-fn`; extension-owned CLI commands stay under
`vis-agent extension`.(-main & raw-args)Initialize the closed distribution, walk the command tree, dispatch.
Behavior:
help / --help / -h -> help for the resolved command:cmd/run-fnRoot prompt shortcut lives here, not in commandline/dispatch!, so
the generic dispatcher stays a pure command tree while the binary owns
CLI ergonomics (vis-agent fix this, vis-agent --json summarize).
Initialize the closed distribution, walk the command tree, dispatch. Behavior: - No args -> top-level help - `help` / `--help` / `-h` -> help for the resolved command - Recognized command -> invoke its `:cmd/run-fn` - Bare prompt / run flags -> one-shot CLI agent - Unknown command + help -> honest unknown-command error Root prompt shortcut lives here, not in `commandline/dispatch!`, so the generic dispatcher stays a pure command tree while the binary owns CLI ergonomics (`vis-agent fix this`, `vis-agent --json summarize`).
(agent {:keys [name] :as opts})Create an agent definition (data map).
Options:
The iteration loop runs until the model emits :answer or the
user cancels.
Example: (agent {:name "code-reviewer" :description "Reviews Clojure code for quality" :model "gpt-4o"})
Create an agent definition (data map).
Options:
- :name - Agent name (string, default "default")
- :description - What the agent does
- :constants - Map of {symbol value} constants for the Python sandbox
- :model - Override default model selection
The iteration loop runs until the model emits `:answer` or the
user cancels.
Example:
(agent {:name "code-reviewer"
:description "Reviews Clojure code for quality"
:model "gpt-4o"})(handler:db)(handler:db _opts)Telemere handler that persists every signal through the
com.blockether.vis.core/log! facade.
The handler reads :db-info from the signal's telemere context
(*ctx*). When :db-info is absent (no DB connection active in
scope), the signal is silently dropped - the console handler still
prints it.
Usage: (tel/add-handler! :db (handler:db))
(tel/with-ctx+ {:db-info db-info :session-soul-id session-id} (tel/log! :info "something happened"))
Telemere handler that persists every signal through the
`com.blockether.vis.core/log!` facade.
The handler reads `:db-info` from the signal's telemere context
(`*ctx*`). When `:db-info` is absent (no DB connection active in
scope), the signal is silently dropped - the console handler still
prints it.
Usage:
(tel/add-handler! :db (handler:db))
(tel/with-ctx+ {:db-info db-info :session-soul-id session-id}
(tel/log! :info "something happened"))(initialize-all!)Initialize the closed Clojure manifest, then project-local Python extensions.
Initialize the closed Clojure manifest, then project-local Python extensions.
(list-extensions)Return all registered extensions with their metadata (table rows).
Managed GitHub packages show their lowercase owner/repository and keep the
technical package name in parentheses. Other namespaces use the v/ prefix
(see short-ext-ns). :kind groups rows; :group labels a contribution inside
that kind. Managed packages derive :owner from the recorded GitHub source.
Other owner, author and license values come from the extension manifest;
bundled extensions use the distribution name ("vis") as their owner.
Return all registered extensions with their metadata (table rows).
Managed GitHub packages show their lowercase owner/repository and keep the
technical package name in parentheses. Other namespaces use the `v/` prefix
(see `short-ext-ns`). `:kind` groups rows; `:group` labels a contribution inside
that kind. Managed packages derive `:owner` from the recorded GitHub source.
Other owner, author and license values come from the extension manifest;
bundled extensions use the distribution name ("vis") as their owner.(root-command)Build the root vis-agent command tree. Subcommands are pulled fresh on
every call so newly registered extensions show up immediately.
Build the root `vis-agent` command tree. Subcommands are pulled fresh on every call so newly registered extensions show up immediately.
(run! agent-def
prompt
&
[{:keys [spec model provider reasoning-effort on-chunk debug? config db
persist? no-persist? session-id]
:as _opts}])Execute a one-shot agent turn.
Runs one turn. Default is ephemeral: in-memory SQLite only, no
:cli session written to disk.
Returns map with:
:error or :cancelled).Options:
high or max):memory, path, or db spec):cli
session. Default false.:persist? is true.Ephemeral runs use an in-memory SQLite DB (:db :memory), run the
turn, then dispose the env (which vaporizes the DB). Result has
:session-id nil. Useful for CI, scripting, sensitive prompts.
Persistent calls (:persist? true) create a fresh session in
the :cli channel. Past runs are browsable via
(sessions/by-channel :cli).
Execute a one-shot agent turn.
Runs one turn. Default is ephemeral: in-memory SQLite only, no
`:cli` session written to disk.
Returns map with:
- :session-id - Session ID (UUID string) when persisted;
nil for default ephemeral runs
- :answer - The agent's response
- :iteration-count - Number of iterations executed
- :duration-ms - Total wall-clock time
- :tokens - {:input N :output N :reasoning N :cached N :total N}
- :cost - {"input_cost" N "output_cost" N "total_cost" N "model" str}
- :trace - Full iteration trace
- :confidence - :high/:medium/:low (when present)
- :status - Only on failure (`:error` or `:cancelled`).
- :error - Error message (only on failure).
Options:
- :spec - Output spec for structured responses
- :provider - Override provider (keyword or string, e.g. :openai)
- :model - Override model
- :reasoning-effort - Exact provider-native effort (`high` or `max`)
- :on-chunk - Streaming callback fn
- :debug? - Enable debug logging (default false)
- :config - Provider config override (skips ~/.vis/config.edn)
- :db - DB target for ephemeral runs (`:memory`, path, or db spec)
- :persist? - Write the run to ~/.vis/vis.mdb as a `:cli`
session. Default false.
- :session-id - Continue an existing persisted session (full UUID or
unambiguous prefix). Implies persistent execution.
- :no-persist? - Backward-compatible override; when true, forces
ephemeral execution even if `:persist?` is true.
Ephemeral runs use an in-memory SQLite DB (`:db :memory`), run the
turn, then dispose the env (which vaporizes the DB). Result has
`:session-id nil`. Useful for CI, scripting, sensitive prompts.
Persistent calls (`:persist? true`) create a fresh session in
the `:cli` channel. Past runs are browsable via
`(sessions/by-channel :cli)`.(setup-db-handler!)Install the :db Telemere handler. Idempotent - reusing the same
handler key replaces the previous registration. Call once at
process startup, after the persistence backend is loaded
(otherwise the handler will silently drop signals because no
backend is registered with the facade yet).
The handler is asynchronous (dropping mode, 2048-entry buffer, single drain thread) so a slow DB write never back-pressures the call site that emitted the signal.
Install the `:db` Telemere handler. Idempotent - reusing the same handler key replaces the previous registration. Call once at process startup, after the persistence backend is loaded (otherwise the handler will silently drop signals because no backend is registered with the facade yet). The handler is asynchronous (dropping mode, 2048-entry buffer, single drain thread) so a slow DB write never back-pressures the call site that emitted the signal.
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 |