pinecallDocs
The gateway / The smallest app that works

The smallest app that works

The app socket spoken with no Pinecall package at all.

The app socket of Gateway API, spoken with no Pinecall package at all.

JavaScript
import WebSocket from "ws";

const AGENT = "clinica-norte";
const FREE_SLOTS = {
  name: "freeSlots",
  description: "Las horas libres de un día. Úsala antes de ofrecer una hora.",
  parameters: { type: "object", properties: { day: { type: "string" } }, required: ["day"] },
};
const ws = new WebSocket(`${process.env.PINECALL_URL.replace("http", "ws")}/v1/apps`, {
  headers: { authorization: `Bearer ${process.env.PINECALL_KEY}` },
});
const send = (type, data, call = null) =>
  ws.send(JSON.stringify({ type, agent: AGENT, call, id: String(Date.now()), data }));

// What the agent IS. Declared once, for every call this socket takes. How it opens the call —
// `greeting: { say: "Clínica Norte, ¿en qué puedo ayudarle?" }` — is the world's: it goes in
// PUT /v1/agents/{slug}/settings, and a greeting sent here is not read.
ws.on("open", () => {
  send("agent.register", { routes: [{ channel: "web", number: null }], sdk: "mine/0.1" });
  send("agent.configure", {
    config: {
      language: "es-ES",
      tools: [FREE_SLOTS],
    },
  });
});

ws.on("message", async (frame) => {
  const entry = JSON.parse(frame.toString());

  // A call opened on this agent: write the prompt and say which tools the model may see.
  if (entry.type === "call.started") {
    send("prompt.set", { name: "identity", text: "Eres la recepción de Clínica Norte. Hablas de usted." }, entry.call);
    send("tools.set", { tools: [FREE_SLOTS] }, entry.call);   // whole specs, so a tool may change
  }

  // The model asked for a tool. It runs HERE, in your process, against your database.
  if (entry.type === "tool.call") {
    const output = await freeSlots(entry.data.arguments.day);
    send("tool.result", { call_id: entry.data.call_id, name: entry.data.name, output }, entry.call);
  }
});

That is a complete Pinecall app: thirty lines, one dependency, no Pinecall package. Everything pinecall adds (the class, the tools, the prompt, the goldens) is sugar over these frames. The call it answers goes: agent.registered · agent.configured · call.started · prompt.changed · tools.changed · turn.user · tool.call · tool.result · turn.agent.