Skip to content

Instantly share code, notes, and snippets.

@jez500
Created April 16, 2026 11:32
Show Gist options
  • Select an option

  • Save jez500/e4e80c6a899264cddaf2637ae70d477d to your computer and use it in GitHub Desktop.

Select an option

Save jez500/e4e80c6a899264cddaf2637ae70d477d to your computer and use it in GitHub Desktop.
PaperclipAi get/set agent model
#!/usr/bin/env node
/**
* set-agent-model.js
*
* Changes the model and/or adaptorType for a Paperclip agent.
*
* Usage:
* node set-agent-model.js --agent-id <id> --model <model-name> [options]
* node set-agent-model.js --agent-id <id> --adaptor-type <type> [options]
*
* Options:
* --agent-id Agent UUID (required)
* --model Model name to set, e.g. claude-sonnet-4-6
* --adaptor-type Adaptor type to set, e.g. claude-code
* --company-id Company UUID (defaults to PAPERCLIP_COMPANY_ID env var)
* --api-url API base URL (defaults to PAPERCLIP_API_URL or http://localhost:3100)
* --api-key Bearer token (defaults to PAPERCLIP_API_KEY env var)
* --list List agents and their current models and adaptor types, then exit
* --dry-run Show what would be changed without applying it
*
* Auth:
* Set PAPERCLIP_API_KEY to a valid bearer token.
* To get one, run:
* npx paperclipai agent local-cli <agent-id-or-shortname> --company-id <company-id>
* That command prints PAPERCLIP_API_KEY — export it, then re-run this script.
*/
const https = require("https");
const http = require("http");
const { URL } = require("url");
// --- Arg parsing ---
const args = process.argv.slice(2);
const get = (flag) => {
const i = args.indexOf(flag);
return i !== -1 ? args[i + 1] : null;
};
const has = (flag) => args.includes(flag);
const agentId = get("--agent-id");
const model = get("--model");
const adaptorType = get("--adaptor-type");
const companyId = get("--company-id") || process.env.PAPERCLIP_COMPANY_ID;
const apiUrl = (get("--api-url") || process.env.PAPERCLIP_API_URL || "http://localhost:3100").replace(/\/$/, "");
const apiKey = get("--api-key") || process.env.PAPERCLIP_API_KEY;
const dryRun = has("--dry-run");
const listMode = has("--list");
const helpMode = has("--help") || has("-h");
function printUsage(exitCode = 0) {
console.log(`
Usage:
node set-agent-model.js --agent-id <id> --model <model-name> [options]
node set-agent-model.js --agent-id <id> --adaptor-type <type> [options]
node set-agent-model.js --list --company-id <id>
Options:
--agent-id Agent UUID (required unless --list)
--model Model name to set (required unless --adaptor-type or --list)
--adaptor-type Adaptor type to set (can be combined with --model)
--company-id Company UUID (defaults to PAPERCLIP_COMPANY_ID env var)
--api-url API base URL (defaults to PAPERCLIP_API_URL or http://localhost:3100)
--api-key Bearer token (defaults to PAPERCLIP_API_KEY env var)
--list List agents and their current models and adaptor types, then exit
--dry-run Show what would be changed without applying it
--help, -h Show this help message
Examples:
# Set model for a specific agent
node set-agent-model.js --agent-id abc-123 --model claude-sonnet-4-6
# Set adaptor type for a specific agent
node set-agent-model.js --agent-id abc-123 --adaptor-type claude-code
# Set both model and adaptor type at once
node set-agent-model.js --agent-id abc-123 --model claude-opus-4-6 --adaptor-type claude-code
# Preview change without applying
node set-agent-model.js --agent-id abc-123 --model claude-opus-4-6 --dry-run
# List all agents and their current models and adaptor types
node set-agent-model.js --list --company-id xyz-456
# Use explicit API key and URL
node set-agent-model.js --agent-id abc-123 --model claude-haiku-4-5-20251001 \\
--api-key <token> --api-url https://api.paperclip.ai
Auth:
Set PAPERCLIP_API_KEY to a valid bearer token.
To get one, run:
npx paperclipai agent local-cli <agent-id-or-shortname> --company-id <company-id>
That command prints PAPERCLIP_API_KEY — export it, then re-run this script.
`);
process.exit(exitCode);
}
if (helpMode) printUsage(0);
if (!listMode && (!agentId || (!model && !adaptorType))) {
console.error("Error: --agent-id and at least one of --model or --adaptor-type are required (or use --list)\n");
printUsage(1);
}
if (!apiKey) {
console.error("Error: PAPERCLIP_API_KEY is not set.\n");
console.error("Get one by running:");
console.error(" npx paperclipai agent local-cli <agent-id-or-shortname> --company-id <company-id>\n");
console.error("Then export PAPERCLIP_API_KEY=<value> and re-run.");
process.exit(1);
}
// --- HTTP helpers ---
function request(method, path, body) {
return new Promise((resolve, reject) => {
const url = new URL(apiUrl + path);
const isHttps = url.protocol === "https:";
const lib = isHttps ? https : http;
const payload = body ? JSON.stringify(body) : null;
const options = {
hostname: url.hostname,
port: url.port || (isHttps ? 443 : 80),
path: url.pathname + url.search,
method,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
...(payload ? { "Content-Length": Buffer.byteLength(payload) } : {}),
},
};
const req = lib.request(options, (res) => {
let data = "";
res.on("data", (chunk) => (data += chunk));
res.on("end", () => {
let parsed;
try {
parsed = JSON.parse(data);
} catch {
parsed = data;
}
if (res.statusCode >= 400) {
reject(new Error(`HTTP ${res.statusCode}: ${JSON.stringify(parsed)}`));
} else {
resolve(parsed);
}
});
});
req.on("error", reject);
if (payload) req.write(payload);
req.end();
});
}
// --- Main ---
async function main() {
if (listMode) {
if (!companyId) {
console.error("Error: --company-id or PAPERCLIP_COMPANY_ID is required for --list");
process.exit(1);
}
console.log(`Fetching agents for company ${companyId}...`);
const agents = await request("GET", `/api/companies/${companyId}/agents`);
const list = Array.isArray(agents) ? agents : agents.agents || agents.data || [];
if (!list.length) {
console.log("No agents found.");
return;
}
console.log(`\n${"ID".padEnd(38)} ${"Name".padEnd(20)} ${"Adaptor Type".padEnd(20)} Model`);
console.log("-".repeat(100));
for (const a of list) {
const m = a.adapterConfig?.model || "(not set)";
const t = a.adapterType || a.adapterConfig?.adapterType || "(not set)";
console.log(`${(a.id || "").padEnd(38)} ${(a.name || a.urlKey || "").padEnd(20)} ${t.padEnd(20)} ${m}`);
}
return;
}
// --- Get current agent ---
console.log(`Fetching agent ${agentId}...`);
const agent = await request("GET", `/api/agents/${agentId}`);
const currentModel = agent.adapterConfig?.model || "(not set)";
const currentAdaptorType = agent.adapterType || agent.adapterConfig?.adapterType || "(not set)";
console.log(` Name: ${agent.name || agent.urlKey || agentId}`);
console.log(` Adapter: ${agent.adapter}`);
if (model !== null) {
console.log(` Current model: ${currentModel}`);
console.log(` New model: ${model}`);
}
if (adaptorType !== null) {
console.log(` Current adaptorType: ${currentAdaptorType}`);
console.log(` New adaptorType: ${adaptorType}`);
}
const modelUnchanged = model === null || currentModel === model;
const adaptorTypeUnchanged = adaptorType === null || currentAdaptorType === adaptorType;
if (modelUnchanged && adaptorTypeUnchanged) {
console.log("\nAll values already set. Nothing to do.");
return;
}
if (dryRun) {
if (!modelUnchanged) console.log("\n[dry-run] Would PATCH adapterConfig.model — skipping.");
if (!adaptorTypeUnchanged) console.log("[dry-run] Would PATCH adaptorType — skipping.");
return;
}
// Merge changes into existing adapterConfig / top-level fields
const newAdapterConfig = { ...(agent.adapterConfig || {}), ...(model !== null ? { model } : {}) };
const patchBody = { adapterConfig: newAdapterConfig, ...(adaptorType !== null ? { adapterType: adaptorType } : {}) };
console.log("\nApplying update...");
const updated = await request("PATCH", `/api/agents/${agentId}`, patchBody);
const appliedModel = updated.adapterConfig?.model;
const appliedAdaptorType = updated.adapterType || updated.adapterConfig?.adapterType;
const modelOk = model === null || appliedModel === model;
const adaptorTypeOk = adaptorType === null || appliedAdaptorType === adaptorType;
if (modelOk && adaptorTypeOk) {
if (model !== null) console.log(`\nDone. Model updated to: ${appliedModel}`);
if (adaptorType !== null) console.log(`Done. adaptorType updated to: ${appliedAdaptorType}`);
} else {
// Fallback: try the dashboard endpoint the user discovered
console.log("PATCH did not apply all changes. Trying dashboard endpoint...");
if (!companyId) {
console.error("Error: --company-id or PAPERCLIP_COMPANY_ID is required for dashboard fallback");
process.exit(1);
}
await request("POST", `/api/companies/${companyId}/dashboard`, patchBody);
if (model !== null) console.log(`\nDone via dashboard endpoint. Model set to: ${model}`);
if (adaptorType !== null) console.log(`Done via dashboard endpoint. adaptorType set to: ${adaptorType}`);
}
}
main().catch((err) => {
console.error("\nFailed:", err.message);
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment