Tool schemas a server accepts
sanitizeTools makes an MCP tool schema something a strict
or grammar-constrained server will take, and negotiate
re-sends a request without what the endpoint or the model refused.
The endpoint-agnostic half of an OpenAI-compatible agent loop.
An agent that talks to OpenAI, Ollama, llama.cpp, vLLM or OpenRouter through the same API ends up writing the same plumbing: pooled clients, retries, streaming, and working out what each server refuses. This package is that plumbing, extracted from three servers that had each written it separately and drifted apart. Prompts, tools and what a run is for stay with the caller.
sanitizeTools makes an MCP tool schema something a strict
or grammar-constrained server will take, and negotiate
re-sends a request without what the endpoint or the model refused.
A name-only catalogue plus a load_tools meta-tool, so a
run pays for the schemas the model asks for instead of all of them on
every request.
runTurn is one streamed turn with retry and negotiation
around it; runAgentLoop runs it per step, with the tool
calls between, until the model stops asking.
ESM only, Node 22 or later. openai (version 6 or later) is a
peer dependency.
npm install @cubicecho/agent-core openai
import { runAgentLoop } from "@cubicecho/agent-core";
const { turn } = await runAgentLoop({
config: {
baseUrl: "http://localhost:11434/v1", // any OpenAI-compatible endpoint
apiKey: "",
model: "qwen3",
maxTokens: 1024,
temperature: 0.2,
maxToolIterations: 8,
},
messages: [{ role: "user", content: "What changed in the last release?" }],
tools, // OpenAI tool definitions, if the run has any
dispatch: async ({ name, args }) => callTool(name, args), // returns what the model reads
});
console.log(turn.content);
Full documentation lives in the project README: https://github.com/cubicecho/agent-core