(assemble-prompt-text messages)Flatten messages into "role: content" lines — the FULL request, every
turn (an ACP session is stateful, so sending only the delta would make this
client a second, shadow copy of conversation state) — and append the
supersedes marker naming the latest message's text, so a stateful agent
answers the CURRENT request rather than an earlier near-duplicate already
sitting in its own session history (ADR 0031).
Flatten `messages` into "role: content" lines — the FULL request, every turn (an ACP session is stateful, so sending only the delta would make this client a second, shadow copy of conversation state) — and append the supersedes marker naming the latest message's text, so a stateful agent answers the CURRENT request rather than an earlier near-duplicate already sitting in its own session history (ADR 0031).
(close client)Terminate the child process. Idempotent — calling it more than once past the first call is a no-op (guarded by a compare-and-set! "close once" flag, the portable equivalent of Go's sync.Once).
Terminate the child process. Idempotent — calling it more than once past the first call is a no-op (guarded by a compare-and-set! "close once" flag, the portable equivalent of Go's sync.Once).
(connect command)(connect command opts)Spawn command (a vector, e.g. ["my-agent" "acp"]) and complete
initialize -> session/new (-> optional session/set_mode) (-> optional
model). Returns a live, warm client map. Throws (ex-info) on any handshake
failure — a model source that cannot connect is a construction-time error,
matching toolnexus.agents.runtime/create-runtime's own validation. The
ex-data carries :phase ("initialize", "session/new", ...) and the
agent's :stderr tail.
opts:
:cwd absolute working directory handed to session/new
AND the child's working directory.
Real agents REJECT session/new with -32602 without
an absolute cwd (ADR 0031) — defaults to
the process's own resolved cwd (koine.fs/real-path
on "."), which is always absolute.
:mcp-servers session/new mcpServers: a list of JSON objects
sent VERBATIM and in order (SPEC §8C) — never
validated, renamed or reshaped. Default [] (the key
is always present; real agents require it).
:session-meta sent as session/new _meta (opaque); the key is
absent when unset.
:client-caps-meta sent as initialize clientCapabilities._meta (opaque).
:model if set, passed through unchanged after session/new:
session/set_config_option {configId "model"}, then
session/set_model if that is rejected. Both failing
is a connect error.
:on-permission (fn [params] option-id) decides every
session/request_permission (see answer-permission!).
:on-update (fn [params]) sees every raw session/update (must not
block — it runs on the reader thread).
:environment / :env extra env vars for the child (merged; matches
toolnexus.mcp's environment/env alias).
:mode if set, issues an optional session/set_mode after
session/new.
:timeout per-call timeout ms for the setup handshake.
Default 30000.
:permission-timeout the safety net bounding a session/prompt reply
— see default-permission-timeout-ms. Default 30000.
The client map also carries :initialize-result.
The agent is spawned without a shell (exec replaces the pid-recording
wrapper, argv untouched); close ends the agent's whole process tree, since
koine exposes no process groups.
Spawn `command` (a vector, e.g. ["my-agent" "acp"]) and complete
`initialize` -> `session/new` (-> optional `session/set_mode`) (-> optional
model). Returns a live, warm client map. Throws (ex-info) on any handshake
failure — a model source that cannot connect is a construction-time error,
matching `toolnexus.agents.runtime/create-runtime`'s own validation. The
ex-data carries `:phase` ("initialize", "session/new", ...) and the
agent's `:stderr` tail.
opts:
:cwd absolute working directory handed to `session/new`
AND the child's working directory.
Real agents REJECT session/new with -32602 without
an absolute cwd (ADR 0031) — defaults to
the process's own resolved cwd (`koine.fs/real-path`
on "."), which is always absolute.
:mcp-servers `session/new` mcpServers: a list of JSON objects
sent VERBATIM and in order (SPEC §8C) — never
validated, renamed or reshaped. Default [] (the key
is always present; real agents require it).
:session-meta sent as session/new `_meta` (opaque); the key is
absent when unset.
:client-caps-meta sent as initialize clientCapabilities._meta (opaque).
:model if set, passed through unchanged after session/new:
session/set_config_option {configId "model"}, then
session/set_model if that is rejected. Both failing
is a connect error.
:on-permission (fn [params] option-id) decides every
session/request_permission (see answer-permission!).
:on-update (fn [params]) sees every raw session/update (must not
block — it runs on the reader thread).
:environment / :env extra env vars for the child (merged; matches
toolnexus.mcp's `environment`/`env` alias).
:mode if set, issues an optional `session/set_mode` after
`session/new`.
:timeout per-call timeout ms for the setup handshake.
Default 30000.
:permission-timeout the safety net bounding a `session/prompt` reply
— see default-permission-timeout-ms. Default 30000.
The client map also carries `:initialize-result`.
The agent is spawned without a shell (`exec` replaces the pid-recording
wrapper, argv untouched); `close` ends the agent's whole process tree, since
koine exposes no process groups.(generate client)Build a semantic generate fn — (fn [req] -> {:content ...}) — backed by
this warm ACP client, in the exact shape
toolnexus.client/create-in-process-client and
toolnexus.agents.runtime/create-runtime's :in-process option accept.
(let [c (toolnexus.acp/connect ["my-agent" "acp"])] (toolnexus.client/create-in-process-client {:model "my-agent" :generate (toolnexus.acp/generate c)}))
Throws on an ACP-level failure (a closed session, a timed-out call, an RPC
error) — the same failure shape any other generate fn raising surfaces to
the caller.
Build a semantic `generate` fn — (fn [req] -> {:content ...}) — backed by
this warm ACP client, in the exact shape
`toolnexus.client/create-in-process-client` and
`toolnexus.agents.runtime/create-runtime`'s `:in-process` option accept.
(let [c (toolnexus.acp/connect ["my-agent" "acp"])]
(toolnexus.client/create-in-process-client
{:model "my-agent" :generate (toolnexus.acp/generate c)}))
Throws on an ACP-level failure (a closed session, a timed-out call, an RPC
error) — the same failure shape any other `generate` fn raising surfaces to
the caller.(generate-stream client)Build a streaming semantic generate — (fn [req emit] -> {:content ...}) —
the shape toolnexus.client/create-in-process-client's :generate-stream
accepts. emit receives text / thought / tool_call / tool_result events
from the reader thread while the turn runs (incremental, not after it);
the returned content is only the agent_message_chunk text. Throws like
generate on an ACP-level failure.
Build a streaming semantic generate — (fn [req emit] -> {:content ...}) —
the shape `toolnexus.client/create-in-process-client`'s `:generate-stream`
accepts. `emit` receives text / thought / tool_call / tool_result events
from the reader thread while the turn runs (incremental, not after it);
the returned content is only the agent_message_chunk text. Throws like
`generate` on an ACP-level failure.(prompt client text)(prompt client text emit)Send one turn's FULL prompt text and wait for the accumulated
agent_message_chunk reply. Turns on the same client are serialised —
{:ok content} or {:error reason}. With emit, every session/update of the
turn is also handed to it AS IT ARRIVES (see stream-update!).
Send one turn's FULL prompt text and wait for the accumulated
agent_message_chunk reply. Turns on the same client are serialised —
{:ok content} or {:error reason}. With `emit`, every session/update of the
turn is also handed to it AS IT ARRIVES (see `stream-update!`).(stderr client)The agent's most recent stderr lines (koine keeps a bounded tail), joined with newlines — for error messages. Never contains anything we wrote.
The agent's most recent stderr lines (koine keeps a bounded tail), joined with newlines — for error messages. Never contains anything we wrote.
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 |