Paperclip adapter for local or proxy LLM HTTP endpoints that speak either:
- OpenAI Chat Completions (
/chat/completions) - Anthropic Messages (
/messages)
The adapter calls the endpoint directly from the Paperclip server. It does not infer providers, rewrite model IDs, shell out to a CLI, or route through another agent runtime.
- OpenAI-compatible and Anthropic-compatible transports
- Buffered, non-streaming requests
- Per-run instructions file loading
apiKeyEnvsecret handling only; rawapiKeyis rejected- Redacted auth/key/token/secret headers in adapter logs
- Paperclip config-schema support for the generic adapter form
- Environment diagnostics through Paperclip's
Test environmentbutton - Best-effort tool support (see Tool Support below)
Install it from npm through the Paperclip adapter manager:
Settings -> Adapters -> Install Adapter -> npm package
paperclip-adapter-custom-llm-local
Or install through the adapter API:
curl -X POST http://localhost:3100/api/adapters \
-H "Content-Type: application/json" \
-d '{"packageName":"paperclip-adapter-custom-llm-local"}'If your Paperclip instance requires board authentication, include your normal authorization headers with the request above.
For local development, install from a local directory through the same adapter
manager or by adding an entry to ~/.paperclip/adapter-plugins.json:
[
{
"packageName": "paperclip-adapter-custom-llm-local",
"localPath": "/absolute/path/to/paperclip-adapter-custom-llm-local",
"type": "custom_llm_local",
"installedAt": "2026-01-01T00:00:00.000Z"
}
]Restart Paperclip after changing the plugin list.
Once the adapter is installed and Paperclip has restarted, configuration fields appear automatically in the agent settings UI:
Agent Settings → Adapter → Custom LLM (Local)
If the fields do not appear, make sure the adapter is installed and Paperclip has been restarted. If you installed from a local path, pull the latest code and restart Paperclip.
The following fields are rendered by Paperclip from the adapter's config schema:
Example for an OpenAI-compatible local proxy:
{
"adapterType": "custom_llm_local",
"adapterConfig": {
"model": "gpt-4.1-mini",
"baseUrl": "http://127.0.0.1:8080/v1",
"apiKeyEnv": "LOCAL_LLM_API_KEY",
"transport": "openai_chat_completions",
"timeoutSec": 300,
"graceSec": 30,
"instructionsFilePath": "/absolute/path/to/AGENTS.md"
}
}Example for an Anthropic-compatible endpoint:
{
"adapterType": "custom_llm_local",
"adapterConfig": {
"model": "claude-compatible-model",
"baseUrl": "http://127.0.0.1:8080/v1",
"apiKeyEnv": "LOCAL_LLM_API_KEY",
"transport": "anthropic_messages",
"timeoutSec": 300,
"graceSec": 30
}
}| Field | Required | Description |
|---|---|---|
model |
Yes | Model ID sent verbatim to the endpoint. |
baseUrl |
Yes | Absolute http or https base URL. |
transport |
Yes | openai_chat_completions or anthropic_messages. |
apiKeyEnv |
No | Environment variable name containing the API key. |
instructionsFilePath |
No | Absolute path to a markdown instructions file. |
timeoutSec |
No | Request timeout in seconds. Defaults to 300. |
graceSec |
No | Grace period before hard abort. Defaults to 30. |
extraHeaders |
No | Additional string headers to merge into the request. |
modelAlias |
No | Optional display/canonical model alias in result JSON. |
The adapter passes model through unchanged. Some proxies expect bare model IDs
such as gpt-4.1-mini; others expect provider-prefixed IDs such as
openai/gpt-4.1-mini. Use the exact model string your endpoint accepts.
llama-server exposes both OpenAI-compatible /v1/chat/completions and
Anthropic-compatible /v1/messages APIs. Choose the adapter transport that
matches the endpoint you want to call.
For OpenAI Chat Completions:
{
"model": "your-llama-model",
"baseUrl": "http://127.0.0.1:8080/v1",
"transport": "openai_chat_completions"
}For Anthropic Messages:
{
"model": "your-llama-model",
"baseUrl": "http://127.0.0.1:8080/v1",
"transport": "anthropic_messages"
}The adapter forwards tool definitions from the execution context to the LLM endpoint and parses tool-call requests from the response. This is a best-effort implementation:
- If the Paperclip runtime provides tool definitions in the execution context,
they are passed through to the LLM as
toolsin the request body. - For the OpenAI Chat Completions transport, tools are sent in OpenAI format
(
{ type: "function", function: { name, description, parameters } }). - For the Anthropic Messages transport, tools are automatically converted to
Anthropic format (
{ name, description, input_schema }) if they arrive in OpenAI format. Tools already in Anthropic format are passed through as-is. - Tool-call requests in the LLM response are parsed into a normalized array
(
toolCalls) in the result JSON, with each entry containingid,name, andarguments(JSON string).
Whether the Paperclip core runtime interprets and acts on these tool calls depends on the Paperclip version. The adapter prepares the data; interpretation is outside the adapter's scope.
If your endpoint does not support tools, the adapter simply omits the tools
field from the request and no tool calls are parsed from the response.
- Do not put API key values in
adapterConfig. - Set secrets in the Paperclip server process environment and reference them by
name with
apiKeyEnv. - Headers whose names include
auth,key,token, orsecretare redacted in logs. - Endpoint responses may contain prompt or completion text. Treat run logs as sensitive if your prompts contain private data.
npm install
npm run typecheck
npm test
npm run buildBefore publishing, run:
npm run prepublishOnlyThe prepublishOnly script typechecks, tests, builds, and scans the repository
for common secret and personal-path patterns.
MIT