const BASE = process.env.OTT_API_BASE
?? "https://ontimetrucking.com/api/v1";
// 1. What the model reads: a name, a description, a schema.
export const getQuoteTool = {
name: "get_quote",
description: "Price an LTL shipment between two US ZIPs. " +
"Returns customer-facing all-in prices.",
input_schema: {
type: "object",
required: ["originZip", "destZip", "weightLbs"],
properties: {
originZip: { type: "string", pattern: "^[0-9]{5}$" },
destZip: { type: "string", pattern: "^[0-9]{5}$" },
weightLbs: { type: "number", minimum: 1, maximum: 30000 },
},
},
};
type Args = { originZip: string; destZip: string; weightLbs: number };
// 2. What runs when the model calls it: a plain function.
export async function getQuote(a: Args) {
const res = await fetch(BASE + "/quotes", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.OTT_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
originZip: a.originZip,
destZip: a.destZip,
commodities: [{
freightClass: "100",
weightLbs: a.weightLbs,
pieces: 1,
dimsIn: { length: 48, width: 40, height: 48 },
}],
}),
});
// Return errors as data so the model can read them.
if (!res.ok) {
return { error: res.status, detail: await res.text() };
}
const q = await res.json();
return {
quoteId: q.quoteId,
options: q.options,
expiresAt: q.expiresAt,
};
}
// 3. Try it without a model: call the tool the way a model would.
const args = { originZip: "11735", destZip: "10001", weightLbs: 500 };
const result = await getQuote(args);
console.log(JSON.stringify(result, null, 2));
const BASE = process.env.OTT_API_BASE
?? "https://ontimetrucking.com/api/v1";
// 1. What the model reads: a name, a description, a schema.
export const getQuoteTool = {
name: "get_quote",
description: "Price an LTL shipment between two US ZIPs. " +
"Returns customer-facing all-in prices.",
input_schema: {
type: "object",
required: ["originZip", "destZip", "weightLbs"],
properties: {
originZip: { type: "string", pattern: "^[0-9]{5}$" },
destZip: { type: "string", pattern: "^[0-9]{5}$" },
weightLbs: { type: "number", minimum: 1, maximum: 30000 },
},
},
};
type Args = { originZip: string; destZip: string; weightLbs: number };
// 2. What runs when the model calls it: a plain function.
export async function getQuote(a: Args) {
const res = await fetch(BASE + "/quotes", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.OTT_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
originZip: a.originZip,
destZip: a.destZip,
commodities: [{
freightClass: "100",
weightLbs: a.weightLbs,
pieces: 1,
dimsIn: { length: 48, width: 40, height: 48 },
}],
}),
});
// Return errors as data so the model can read them.
if (!res.ok) {
return { error: res.status, detail: await res.text() };
}
const q = await res.json();
return {
quoteId: q.quoteId,
options: q.options,
expiresAt: q.expiresAt,
};
}
// 3. Try it without a model: call the tool the way a model would.
const args = { originZip: "11735", destZip: "10001", weightLbs: 500 };
const result = await getQuote(args);
console.log(JSON.stringify(result, null, 2));