API Reference — Clojure
One .cljc source tree that runs unchanged on Clojure (JVM) and on
cljgo (Clojure hosted on Go). Every host difference
lives behind koine, the only third-party dependency. See
the combined API Reference for the shared surface in the other ports’ tabs.
Namespaces live under toolnexus.* (clojure/src/toolnexus/). On Clojars since v0.13.0:
net.clojars.muthuishere/toolnexus {:mvn/version "0.16.0"} — koine comes with it transitively.
Every entry point below also has its own page, generated from the same manifest as the other six
ports — open the Clojure topic in the API-reference picker, or start at
toolnexus.core/build.
Toolkit — toolnexus.core/build
Section titled “Toolkit — toolnexus.core/build”(build {:keys [mcp skills skill-defs skill-provider skills-filter skill-sample-limit disable-skills builtins agents tools disable-tools wait-for]}) -> toolkit:mcp— anmcp.jsonstring or map (§2/§0.3):skills— a skills root, a seq of roots, or a seq of skill defs (§3);:skill-defsand:skill-providersupply them as data,:skills-filter/:disable-skills/:skill-sample-limitnarrow the catalog:builtins— the §0.11 toggle:false | {:disabled ..} | {:enabled ..} | {:tools {..}}:agents— remote A2A peers; each advertised skill becomes a tool (§7A):tools— extra Tools of your own (native, http, a2a — anything);:disable-toolsdrops names across EVERY source:wait-for— the ONE §10 host resolver, handed to the MCP source so a server may elicit input mid-tools/call; absent ⇒ theelicitationcapability is not advertised at all
- Returns
{:tools .. :sources .. :skills .. :statuses .. :errors .. :connections .. :wait-for ..}. Every source is isolated: a dead MCP server contributes an error + status, never an exception. (shutdown! tk)— disconnect every MCP connection the toolkit opened (idempotent).(tool-names tk)— sorted tool names.(execute tk name args)/(execute tk name args ctx).- Equivalents:
createToolkit(js) ·create_toolkit(py) ·CreateToolkit(go) ·Toolkit.create(java) ·Toolkit.CreateAsync(c#) ·Toolnexus.create_toolkit(elixir).
Skills — toolnexus.skill
Section titled “Skills — toolnexus.skill”(load-skills input) -> {:skills .. :by-name .. :skipped .. :filter-unmatched .. :sample-limit ..}—inputis a root string, a seq of roots, one skill def, a seq of defs, or the options map{:dirs .. :skills .. :filter .. :sample-limit ..}. Roots are visited in the order given, and an earlier one wins a name collision.(list-skills input) -> {:skills .. :skipped ..}— discover + validate without building a toolkit; typed skip reasonsmissing-name·malformed-frontmatter·duplicate-name·unreadable.- A data skill is a plain map:
{:name .. :description .. :content .. :resources [..] :base ..}. With no:baseit gets the logical baseskill://<name>/, so a source that never touched a disk cannot leak a host path. (skill-tool loaded)— the singleskilltool over a loaded source (progressive disclosure);(skills-prompt loaded)— the §3/§0.6 system-prompt catalog (re-exported astoolnexus.core/skills-prompt).- Equivalents:
loadSkills/listSkills(js) ·load_skills/list_skills(py) ·LoadSkillsWith/ListSkills(go) ·SkillSource.loadWith/listSkills(java) ·SkillSource.LoadWith/ListSkills(c#) ·Toolnexus.Skill.load/Toolnexus.Skill.list(elixir).
MCP · Adapters · Client
Section titled “MCP · Adapters · Client”toolnexus.mcp—(from-config config)connects every server (stdio + streamable-HTTP), returns{:tools .. :statuses .. :connections .. :errors ..};(parse-config config)validates without connecting;(tools conn),(disconnect conn),(disconnect-all conns).(from-config config {:wait-for f})also bridges a server’s elicitation onto §10 —(elicitation->request params)/(answer->elicit-result answer)— and with no:wait-forthe capability is not advertised at all.- Adapters (
toolnexus.adapter, re-exported oncore):(to-openai tk)·(to-anthropic tk)·(to-gemini tk). - Client (
toolnexus.client):(create-client opts)→(run client prompt {:toolkit tk :history [..] :on-event f :conversation-id id}).
Tools you build — native, HTTP, built-ins
Section titled “Tools you build — native, HTTP, built-ins”toolnexus.native/native-tool— map form(native-tool {:name .. :description .. :input-schema {..} :run (fn [args] ..)}); a tool that needs the §1 Context declares:ctx? trueand its:runtakes(fn [args ctx] ..). (The flag exists because Clojure/cljgo have no portable fn-arity introspection.)toolnexus.http/http-tool—(http-tool {:name .. :description .. :method :get :url ".../{id}" :headers {"authorization" "Bearer ${API_TOKEN}"} :query [:verbose] :body "json" :timeout-ms 30000 :result-mode "text"}).:timeout-msin milliseconds (default 30000);:bodyis"json" | "form" | "raw";:result-modeis"text" | "json" | "status+text".toolnexus.builtin—builtin-names/builtin-tools: the same ten built-ins,source "builtin", identical names:bash · read · write · edit · grep · glob · webfetch · question · apply_patch · todowrite. The toolkit:builtinstoggle selects them.toolnexus.tool— the primitives every source flows through:(tool {..}),(success output)/(failure output)(deliberately notok/err— those shadow aclojure.corename on cljgo),(toolkit tools),(add-tools tk tools),(tool-names tk),(execute tk name args).- Equivalents:
defineTool/httpTool(js) ·define_tool/http_tool(py) ·NativeTool/HTTPTool(go) ·NativeTool.of/HttpTool.of(java) ·NativeTool.Of/HttpTool.Of(c#) ·Toolnexus.Native.define_tool/Toolnexus.Http.tool(elixir).
A2A — serve & remote agents
Section titled “A2A — serve & remote agents”- Serve (
toolnexus.serve):(serve tk {:port 0 :a2a {..} :mcp {..} :skills .. :client llm :on-task f :on-call f})→{:url :port :store :stop! :handle};(stop! handle).:a2a/:mcpabsent ⇒ those routes off.(agent-card a2a base skills). - Remote agents (
toolnexus.a2a):(remote-agent {:card url :headers {..} :timeout ms :poll-every ms})→{:card .. :endpoint .. :tools [..]}; a failing agent is isolated to{:tools [] :error ".."}.(agent-tools spec)returns just the tools;(parse-agents-config config)declares peers in config the way MCP servers are declared. Pass the specs viabuild’s:agents, or the tools via:tools. - Equivalents:
tk.serve/agent+tk.addAgent(js) ·serve/add_agent(py) ·Serve/AddAgent(go) ·serve/addAgent(java) ·ServeAsync/AddAgentAsync(c#) ·Toolkit.serve/Toolkit.add_agent(elixir).
Translation — toolnexus.translate
Section titled “Translation — toolnexus.translate”(translate client {:messages [..] :tools [..] :toolkit tk :toolChoice .. :system .. :maxTokens ..})— SPEC §11: exactly one provider call, returned in OpenAI shape{:text :toolCalls [{:id :name :arguments}] :finishReason :usage :model :raw}. Drives no loop, executes no tool, touches no conversation store.:argumentsis a JSON string — the OpenAI wire form.(openai-messages-to-anthropic messages)·(openai-tools-to-anthropic tools)·(openai-tool-choice-to-anthropic choice)— the inbound half, including the tool-result merging a flattening translator gets wrong.
Suspension & the human loop — toolnexus.client
Section titled “Suspension & the human loop — toolnexus.client”:wait-for— the host resolver oncreate-client:(fn [request] answer), the one host slot of §10.(make-request kind prompt opts)·(make-answer id ok data reason).(suspend request)/(suspend request output)— aToolResultwhosemetadata.pendingis aRequestis a suspension (§0.12);(pending-of result)returns thatRequestor nil.(auth-required url)/(auth-required url prompt)— akind:"authorization"suspension aturl.- Equivalents:
waitFor/pending/authRequired/pendingOf(js) ·wait_for/pending(py) ·WaitFor/Pending/AuthRequired/PendingOf(go) ·waitFor/ToolResult.pending(java) ·WithWaitFor/ToolResult.Pending(c#) ·wait_for/ToolResult.pending?(elixir).