CLM_AGENT(3) - Library Functions Manual
clm_agent_new, clm_agent_free, clm_agent_free_ptr, clm_agent_submit, clm_agent_cancel, clm_agent_compact, clm_agent_check_connection, clm_agent_set_provider, clm_provider_from_str, clm_agent_get_state, clm_agent_get_ctx_max, clm_agent_get_last_error, clm_agent_over_autocompact_threshold, clm_agent_take_mid_chain_compact_started, clm_agent_take_mid_chain_compact_succeeded, clm_agent_take_mid_chain_compact_error - create and drive a clm agent
#include <clm/clm.h>
int
clm_agent_new(const struct clm_cfg *cfg,
struct clm_host *host,
const struct clm_callbacks *cb,
void *user,
struct clm_agent **out);
void
clm_agent_free(struct clm_agent *agent);
void
clm_agent_free_ptr(struct clm_agent **agent);
int
clm_agent_submit(struct clm_agent *agent, const char *prompt);
int
clm_agent_cancel(struct clm_agent *agent);
int
clm_agent_compact(struct clm_agent *agent);
int
clm_agent_check_connection(struct clm_agent *agent);
int
clm_agent_set_provider(struct clm_agent *agent, const struct clm_cfg *cfg);
int
clm_agent_restore_history(struct clm_agent *agent,
const struct clm_history *h);
cJSON *
clm_message_to_json_full(const struct clm_message *m,
const struct clm_compressor *cz);
int
clm_message_from_json(struct clm_history *h,
const cJSON *obj,
const struct clm_compressor *cz);
enum clm_provider
clm_provider_from_str(const char *kind);
enum clm_agent_state
clm_agent_get_state(const struct clm_agent *agent);
int64_t
clm_agent_get_ctx_max(const struct clm_agent *agent);
const char *
clm_agent_get_last_error(const struct clm_agent *agent);
bool
clm_agent_over_autocompact_threshold(const struct clm_agent *agent);
bool
clm_agent_take_mid_chain_compact_started(struct clm_agent *agent);
bool
clm_agent_take_mid_chain_compact_succeeded(struct clm_agent *agent);
bool
clm_agent_take_mid_chain_compact_error(struct clm_agent *agent);
A struct clm_agent is a single conversational agent: an OpenAI-compatible chat loop, a tool registry, and conversation history, all driven asynchronously through a caller-supplied struct clm_host (transport and timers; see clm_host(3)).
clm_agent_new()
creates an agent bound to
host
and returns it in
out.
cfg
is copied at the call, so the caller does not need to keep it alive
afterward
but
every string field inside it
(api_key,
base_url,
model,
system_prompt,
volatile_tools)
is
borrowed,
not copied, and must stay valid for the life of the agent.
cb
may be
NULL
if the caller wants no events at all; otherwise every field in it is
optional, since the library checks each callback pointer before calling
it, so a minimal caller can set only
on_turn_done.
user
is an opaque pointer passed back to every callback.
The caller owns
host
and whatever it wraps (e.g. an event loop);
clm_agent_new()
never tears it down.
clm_agent_free() releases an agent and everything it owns: the tool registry, conversation history, and any turn state. Does not touch the clm_host it was created with.
clm_agent_free_ptr()
calls
clm_agent_free()
on
*agent
and sets
*agent
to
NULL.
It is intended for use with the
_cleanup_clm_
attribute, which arranges for automatic release when a variable goes out
of scope:
_cleanup_clm_ struct clm_agent *agent = NULL;
int r;
r = clm_agent_new(&cfg, host, &cb, NULL, &agent);
if (r < 0) {
errno = -r;
err(1, "clm_agent_new");
}
/* agent is released automatically on all exit paths */
clm_agent_submit() starts a user turn. It returns immediately; the turn itself runs asynchronously as the caller drives host's event loop, emitting events through the callbacks passed to clm_agent_new() and ending with on_turn_done. Callers must not submit a new turn until on_turn_done has fired for the previous one.
clm_agent_cancel()
aborts whatever is in flight for the current turn (the model request
itself, or any running tool calls) and ends the turn via
on_turn_done
with status
ECANCELED.
Safe to call from inside a callback, e.g. a UI's key handler.
clm_agent_compact() summarizes the conversation so far and folds older turns into that summary, keeping the system prompt and the most recent turns intact. This is one extra asynchronous model round-trip; it fires on_turn_done when it finishes, unless it was triggered internally, mid-chain, between tool batches, in which case the interrupted tool chain simply resumes instead of ending a turn.
clm_agent_check_connection()
probes the configured endpoint for reachability with an asynchronous
GET /v1/models.
The result arrives later through the
on_connection
callback.
Safe to call at any time, including while a turn is already in flight.
clm_agent_set_provider()
reconfigures the LLM provider/model on a live agent, swapping the
endpoint, API key, wire dialect, model, and per-model context/rate-limit
overrides, without tearing down history, tools, or MCP clients
(contrast a full clm_agent_free() + clm_agent_new(), needed)
only when the system prompt or tool set also changes; see
clm-config(5)'s
agents vs. models split .
Safe to call between turns, not while one is in flight.
Only
cfg->base_url,
api_key,
provider,
model,
context_size,
autocompact_pct,
rate_tokens_per_sec,
and
rate_burst
are read; the rest of
*cfg
(system_prompt, tools, max_iterations, ...)
is ignored, since this only ever changes the connection, not the
agent's behavior.
cfg->base_url
is the full chat completions URL (e.g.
"http://host/v1/chat/completions").
cfg->api_key
may be
NULL
for a server that requires no authentication.
context_size,
autocompact_pct,
rate_tokens_per_sec,
and
rate_burst
of 0 leave the library default in place, same as at
clm_agent_new()
time.
clm_provider_from_str()
maps a
clm-config(5)
provider's
kind
string
("openai, "anthropic, or "ollama""")
to the corresponding
enum clm_provider
value, for use in
cfg->provider.
An unrecognized or
NULL
kind
defaults to
CLM_PROVIDER_OPENAI.
clm_agent_get_state()
returns the agent's current
enum clm_agent_state
( Dv CLM_STATE_IDLE , CLM_STATE_THINKING , CLM_STATE_CALLING_TOOL ,
CLM_STATE_RATE_LIMITED, CLM_STATE_COMPLETE,
or
CLM_STATE_ERROR).
clm_agent_get_ctx_max() returns the context window size in tokens, as learned from the backend (e.g. llama.cpp's /props endpoint), or a non-positive value if it is not yet known.
clm_agent_get_last_error() returns a description of the most recent failure, valid until the next call that can fail.
clm_agent_over_autocompact_threshold() reports whether the agent's last known context usage is at or above the autocompaction threshold. clm_agent_tools_done() already checks this internally between tool batches to trigger compaction mid-chain; it is exposed here too so a frontend (e.g. a status bar) can reflect the same threshold without keeping its own separate copy of the calculation.
clm_agent_take_mid_chain_compact_started(),
clm_agent_take_mid_chain_compact_succeeded(),
and
clm_agent_take_mid_chain_compact_error()
each report, once, whether a mid-chain autocompaction (one triggered
internally between tool batches, not by an explicit
clm_agent_compact()
call) has just started, just succeeded, or just failed, respectively.
Every one of these is consuming: it clears its flag on read, so
calling it twice in a row without an intervening event returns
false
the second time.
There is no dedicated event for any of this
(the whole point of a mid-chain compaction is that the tool chain it
interrupted resumes silently rather than ending the turn)
,
so a caller that wants to
surface
"compacting..."
or
"autocompact failed, continuing anyway"
messages should poll these, for instance from the
on_state
callback, rather than expecting a dedicated event.
clm_agent_get_last_error()
holds the actual error message when
clm_agent_take_mid_chain_compact_error()
returns
true.
clm_agent_restore_history() appends a copy of every non-system message in h to the agent's history, re-applying the agent's compressor on store. It is meant for resuming a persisted session: the agent keeps its own freshly built system prologue, a saved system prompt never overrides the current configuration, and the replay does not fire the on_message callback.
clm_message_to_json_full() serializes a single history message losslessly (including tool_name and tool calls, unlike the wire format) into a caller-owned cJSON object; clm_message_from_json() parses such an object and appends the message it describes to h. Together they are the round-trip used by clm(1)'s session persistence.
clm_agent_new(), clm_agent_submit(), clm_agent_cancel(), clm_agent_compact(), clm_agent_check_connection(), and clm_agent_set_provider() return 0 on success, or a negative errno(2) value on failure. A negative return from any of these means the action itself never started; it is not a report of the turn's own eventual outcome, which always arrives later through on_turn_done.
clm_agent_free() and clm_agent_free_ptr() return nothing.
clm_agent_get_state() returns the agent's current state. clm_agent_get_ctx_max() returns the context window size in tokens, or a non-positive value if unknown. clm_agent_get_last_error() returns a borrowed string describing the most recent failure.
clm_agent_over_autocompact_threshold(),
clm_agent_take_mid_chain_compact_started(),
clm_agent_take_mid_chain_compact_succeeded(),
and
clm_agent_take_mid_chain_compact_error()
return
true
or
false.
[ENOMEM]
clm_agent_new() failed to allocate memory.
[ECANCELED]
clm_agent_cancel() successfully cancelled a turn that was in flight; this is reported to on_turn_done as the turn's status, not returned directly by clm_agent_cancel() itself.
[EBUSY]
clm_agent_submit() or clm_agent_compact() was called while a turn was already in flight.
clm_host(3), clm_tool_add(3)
clm - July 6, 2026