@pinecall/skills 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/build.mjs +204 -0
- package/package.json +29 -0
- package/skills/pinecall-concepts/SKILL.md +41 -0
- package/skills/pinecall-concepts/references/concepts/agents-and-channels.md +155 -0
- package/skills/pinecall-concepts/references/concepts/deployment-topologies.md +120 -0
- package/skills/pinecall-concepts/references/concepts/hot-reload.md +119 -0
- package/skills/pinecall-concepts/references/concepts/philosophy.md +100 -0
- package/skills/pinecall-concepts/references/concepts/server-vs-client-llm.md +119 -0
- package/skills/pinecall-examples/SKILL.md +59 -0
- package/skills/pinecall-examples/references/examples/browser-widget.md +206 -0
- package/skills/pinecall-examples/references/examples/chat-bot.md +184 -0
- package/skills/pinecall-examples/references/examples/headless-agent.md +121 -0
- package/skills/pinecall-examples/references/examples/index.md +183 -0
- package/skills/pinecall-examples/references/examples/multi-channel-bot.md +173 -0
- package/skills/pinecall-examples/references/examples/outbound-dispatch.md +109 -0
- package/skills/pinecall-examples/references/examples/turn-detection.md +150 -0
- package/skills/pinecall-guides/SKILL.md +68 -0
- package/skills/pinecall-guides/references/guides/call-ringing.md +149 -0
- package/skills/pinecall-guides/references/guides/conversation-history.md +377 -0
- package/skills/pinecall-guides/references/guides/dev-mode.md +130 -0
- package/skills/pinecall-guides/references/guides/events.md +677 -0
- package/skills/pinecall-guides/references/guides/human-takeover.md +184 -0
- package/skills/pinecall-guides/references/guides/inbound-voice.md +201 -0
- package/skills/pinecall-guides/references/guides/knowledge-bases.md +166 -0
- package/skills/pinecall-guides/references/guides/live-listening.md +199 -0
- package/skills/pinecall-guides/references/guides/multi-tenant.md +158 -0
- package/skills/pinecall-guides/references/guides/outbound-calls.md +279 -0
- package/skills/pinecall-guides/references/guides/sse-streaming.md +207 -0
- package/skills/pinecall-guides/references/guides/testing-agents.md +272 -0
- package/skills/pinecall-guides/references/guides/tools-and-functions.md +254 -0
- package/skills/pinecall-guides/references/guides/webrtc-browser.md +200 -0
- package/skills/pinecall-guides/references/guides/whatsapp.md +370 -0
- package/skills/pinecall-guides/references/guides/ws-streaming.md +235 -0
- package/skills/pinecall-quickstart/SKILL.md +54 -0
- package/skills/pinecall-quickstart/references/index.md +123 -0
- package/skills/pinecall-quickstart/references/quickstart.md +185 -0
- package/skills/pinecall-reference/SKILL.md +43 -0
- package/skills/pinecall-reference/references/reference/cli.md +578 -0
- package/skills/pinecall-reference/references/reference/events.md +366 -0
- package/skills/pinecall-reference/references/reference/llm-providers.md +263 -0
- package/skills/pinecall-reference/references/reference/rest-api.md +122 -0
- package/skills/pinecall-reference/references/reference/session-limits.md +119 -0
- package/skills/pinecall-reference/references/reference/stt-providers.md +174 -0
- package/skills/pinecall-reference/references/reference/tts-providers.md +149 -0
- package/skills/pinecall-sdk-api/SKILL.md +56 -0
- package/skills/pinecall-sdk-api/references/api/agent.md +328 -0
- package/skills/pinecall-sdk-api/references/api/call.md +324 -0
- package/skills/pinecall-sdk-api/references/api/pinecall.md +186 -0
- package/skills/pinecall-sdk-api/references/api/reply-stream.md +148 -0
- package/skills/pinecall-security/SKILL.md +37 -0
- package/skills/pinecall-security/references/security.md +138 -0
- package/skills/pinecall-web-chat/SKILL.md +38 -0
- package/skills/pinecall-web-chat/references/web/chat/chat-session.md +178 -0
- package/skills/pinecall-web-chat/references/web/chat/overview.md +98 -0
- package/skills/pinecall-web-components/SKILL.md +37 -0
- package/skills/pinecall-web-components/references/web/components/overview.md +128 -0
- package/skills/pinecall-web-voice/SKILL.md +40 -0
- package/skills/pinecall-web-voice/references/web/core/datachannel-protocol.md +149 -0
- package/skills/pinecall-web-voice/references/web/core/overview.md +70 -0
- package/skills/pinecall-web-voice/references/web/core/state-and-phases.md +153 -0
- package/skills/pinecall-web-voice/references/web/core/voice-session.md +279 -0
- package/skills/pinecall-web-widget/SKILL.md +41 -0
- package/skills/pinecall-web-widget/references/web/widget/overview.md +67 -0
- package/skills/pinecall-web-widget/references/web/widget/props.md +291 -0
- package/skills/pinecall-web-widget/references/web/widget/theming.md +131 -0
- package/skills/pinecall-web-widget/references/web/widget/tools-api.md +381 -0
- package/skills/pinecall-web-widget/references/web/widget/use-voice-session-hook.md +130 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# @pinecall/skills
|
|
2
|
+
|
|
3
|
+
**Agent Skills for the [Pinecall](https://pinecall.io) SDK.** Drop the Pinecall
|
|
4
|
+
docs into any agent (Claude Code, Google Antigravity, Cursor, GitHub Copilot,
|
|
5
|
+
Codex — anything that speaks the open [Agent Skills](https://github.com/agentskills/agentskills)
|
|
6
|
+
format) so it builds voice & chat agents the right way, offline, with the
|
|
7
|
+
correct defaults.
|
|
8
|
+
|
|
9
|
+
Each skill is a folder with a `SKILL.md` + a `references/` tree of the real docs
|
|
10
|
+
pages, loaded on demand (progressive disclosure). The whole package is
|
|
11
|
+
**generated from `sdk/docs/`** — one source of truth feeds the docs site, the
|
|
12
|
+
`/ask` knowledge base, and these skills.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# the open installer (softaworks/agent-toolkit) — picks an agent dir + symlinks
|
|
18
|
+
npx skills add pinecall/skills
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or manually copy the skills you want into your agent's skills directory:
|
|
22
|
+
|
|
23
|
+
| Agent | Directory |
|
|
24
|
+
|-------|-----------|
|
|
25
|
+
| Claude Code | `.claude/skills/` |
|
|
26
|
+
| Google Antigravity | `.agents/skills/` (or the plugin's `skills/`) |
|
|
27
|
+
| Cursor / others | per the agent's docs |
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
cp -R skills/pinecall-guides ~/your-project/.claude/skills/
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## What's inside
|
|
34
|
+
|
|
35
|
+
| Skill | Covers |
|
|
36
|
+
|-------|--------|
|
|
37
|
+
| `pinecall-quickstart` | Install + first voice agent |
|
|
38
|
+
| `pinecall-concepts` | Agents/Channels/Calls, server vs client LLM, hot reload, topologies |
|
|
39
|
+
| `pinecall-guides` | Inbound/outbound, WhatsApp, tools, events, takeover, WebRTC, multi-tenant, testing… |
|
|
40
|
+
| `pinecall-examples` | Copy-paste full agents |
|
|
41
|
+
| `pinecall-sdk-api` | `@pinecall/sdk` API (Pinecall / Agent / Call / ReplyStream) |
|
|
42
|
+
| `pinecall-web-voice` | `@pinecall/web/core` — browser WebRTC voice |
|
|
43
|
+
| `pinecall-web-widget` | `@pinecall/web` React widget |
|
|
44
|
+
| `pinecall-web-chat` | `@pinecall/web/chat` — text chat |
|
|
45
|
+
| `pinecall-web-components` | Framework-agnostic web components |
|
|
46
|
+
| `pinecall-reference` | CLI, STT/TTS/LLM providers, events, limits, REST |
|
|
47
|
+
| `pinecall-security` | Security model |
|
|
48
|
+
|
|
49
|
+
Every skill carries the **house rules** so the agent never drifts:
|
|
50
|
+
`stt: "deepgram/flux"`, `llm: "openai/gpt-5-chat-latest"`, `voice: "elevenlabs/sarah"`,
|
|
51
|
+
never `nova-2`, and never set `turnDetection`/`vad` by hand.
|
|
52
|
+
|
|
53
|
+
## Regenerate (keep in sync with the docs)
|
|
54
|
+
|
|
55
|
+
The `skills/` tree is generated and committed. Whenever `sdk/docs/` changes,
|
|
56
|
+
re-run the generator and commit the result — same flow as re-pushing the docs KB.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
node build.mjs # reads ../sdk/docs by default
|
|
60
|
+
DOCS_DIR=/path/to/sdk/docs node build.mjs
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The generator maps each `docs.json` navigation group to one skill, copies that
|
|
64
|
+
group's pages into `references/`, and writes a `SKILL.md` index + the house
|
|
65
|
+
rules. No dependencies.
|
package/build.mjs
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @pinecall/skills — generator.
|
|
4
|
+
*
|
|
5
|
+
* Nourishes an Agent-Skills package straight from the SDK docs.
|
|
6
|
+
* Reads `sdk/docs/docs.json` + each page's frontmatter and emits one skill per
|
|
7
|
+
* docs group: skills/<skill>/SKILL.md + skills/<skill>/references/<page>.md
|
|
8
|
+
*
|
|
9
|
+
* Re-run whenever `sdk/docs/` changes — same flow as the KB push. Output is
|
|
10
|
+
* committed (so `npx skills add pinecall/skills` works offline).
|
|
11
|
+
*
|
|
12
|
+
* node build.mjs # default DOCS_DIR=../sdk/docs
|
|
13
|
+
* DOCS_DIR=/path node build.mjs
|
|
14
|
+
*/
|
|
15
|
+
import { readFileSync, writeFileSync, mkdirSync, rmSync, existsSync } from "node:fs";
|
|
16
|
+
import { dirname, join, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
18
|
+
|
|
19
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const DOCS_DIR = resolve(HERE, process.env.DOCS_DIR || "../sdk/docs");
|
|
21
|
+
const OUT_DIR = join(HERE, "skills");
|
|
22
|
+
|
|
23
|
+
// --- House rules: injected into every SKILL.md so each skill is self-correcting.
|
|
24
|
+
const HOUSE_RULES = `## House rules — always apply
|
|
25
|
+
|
|
26
|
+
- **Example defaults** (use these exact strings unless the user asks otherwise):
|
|
27
|
+
\`stt: "deepgram/flux"\`, \`llm: "openai/gpt-5-chat-latest"\`, \`voice: "elevenlabs/sarah"\`.
|
|
28
|
+
**NEVER use \`deepgram/nova-2\`** — it is not supported. Use \`deepgram/nova-3\`
|
|
29
|
+
only for languages Flux doesn't support (e.g. Arabic).
|
|
30
|
+
- **Turn detection & VAD are auto-derived from the STT provider — never set
|
|
31
|
+
\`turnDetection\` or \`vad\` manually.** Flux → native turns + native VAD;
|
|
32
|
+
every other STT → \`smart_turn\` + \`silero\`.
|
|
33
|
+
- **Greeting**: inbound → \`greeting\` field in \`pc.agent()\`; outbound → \`greeting\`
|
|
34
|
+
field in \`agent.dial()\`. It is sugar for \`call.say()\` in \`call.started\`.
|
|
35
|
+
- **Auth**: \`new Pinecall()\` reads \`PINECALL_API_KEY\` from env and auto-connects.
|
|
36
|
+
- Full documentation: <https://docs.pinecall.io>`;
|
|
37
|
+
|
|
38
|
+
// --- Canonical example every voice skill should anchor on.
|
|
39
|
+
const CANONICAL_EXAMPLE = `\`\`\`typescript
|
|
40
|
+
import { Pinecall } from "@pinecall/sdk";
|
|
41
|
+
|
|
42
|
+
const pc = new Pinecall(); // reads PINECALL_API_KEY, auto-connects
|
|
43
|
+
|
|
44
|
+
const agent = pc.agent("mara", {
|
|
45
|
+
prompt: "You are Mara, a friendly voice assistant. Be concise.",
|
|
46
|
+
llm: "openai/gpt-5-chat-latest",
|
|
47
|
+
voice: "elevenlabs/sarah",
|
|
48
|
+
stt: "deepgram/flux",
|
|
49
|
+
language: "en",
|
|
50
|
+
greeting: "Hello! How can I help?",
|
|
51
|
+
});
|
|
52
|
+
\`\`\``;
|
|
53
|
+
|
|
54
|
+
// --- docs.json group name -> skill metadata. Unknown groups fall back to slug.
|
|
55
|
+
const GROUP_MAP = {
|
|
56
|
+
"Get Started": {
|
|
57
|
+
slug: "pinecall-quickstart",
|
|
58
|
+
blurb: "Install @pinecall/sdk and build your first voice agent in minutes.",
|
|
59
|
+
keywords: "install, quickstart, first agent, pc.agent, PINECALL_API_KEY, pinecall run",
|
|
60
|
+
},
|
|
61
|
+
Concepts: {
|
|
62
|
+
slug: "pinecall-concepts",
|
|
63
|
+
blurb: "The mental model — Pinecall, Agent, Channel, Call; server- vs client-side LLM; hot reload; deployment topologies.",
|
|
64
|
+
keywords: "agents and channels, server vs client llm, hot reload, deployment, mental model, architecture",
|
|
65
|
+
},
|
|
66
|
+
Guides: {
|
|
67
|
+
slug: "pinecall-guides",
|
|
68
|
+
blurb: "Task guides for building Pinecall agent features.",
|
|
69
|
+
keywords: "inbound, outbound, whatsapp, tools, function calling, events, live listening, conversation history, human takeover, webrtc, multi-tenant, dev mode, testing, agent.dial, call.say, tool()",
|
|
70
|
+
},
|
|
71
|
+
Examples: {
|
|
72
|
+
slug: "pinecall-examples",
|
|
73
|
+
blurb: "Copy-paste recipes — full working agents for common scenarios.",
|
|
74
|
+
keywords: "example, recipe, sample, outbound dispatch, chat bot, browser widget, multi-channel, headless",
|
|
75
|
+
},
|
|
76
|
+
"@pinecall/sdk (Node.js)": {
|
|
77
|
+
slug: "pinecall-sdk-api",
|
|
78
|
+
blurb: "@pinecall/sdk API reference — Pinecall, Agent, Call, ReplyStream.",
|
|
79
|
+
keywords: "api, pc.agent, agent.dial, call object, reply stream, replyStream, server sdk surface",
|
|
80
|
+
},
|
|
81
|
+
"@pinecall/web/core (Voice)": {
|
|
82
|
+
slug: "pinecall-web-voice",
|
|
83
|
+
blurb: "@pinecall/web/core — browser WebRTC voice (VoiceSession, state & phases, DataChannel protocol).",
|
|
84
|
+
keywords: "webrtc, voice session, browser voice, datachannel, @pinecall/web/core",
|
|
85
|
+
},
|
|
86
|
+
"@pinecall/web (React Widget)": {
|
|
87
|
+
slug: "pinecall-web-widget",
|
|
88
|
+
blurb: "@pinecall/web React widget — VoiceWidget props, theming, useVoiceSession hook, client tools.",
|
|
89
|
+
keywords: "react widget, voicewidget, useVoiceSession, theming, props, client tools, @pinecall/web",
|
|
90
|
+
},
|
|
91
|
+
"@pinecall/web/chat (Chat)": {
|
|
92
|
+
slug: "pinecall-web-chat",
|
|
93
|
+
blurb: "@pinecall/web/chat — browser text chat (ChatSession, ChatView).",
|
|
94
|
+
keywords: "chat, chatsession, text chat, @pinecall/web/chat",
|
|
95
|
+
},
|
|
96
|
+
"@pinecall/web (Web Components)": {
|
|
97
|
+
slug: "pinecall-web-components",
|
|
98
|
+
blurb: "@pinecall/web web components — framework-agnostic custom elements.",
|
|
99
|
+
keywords: "web components, custom element, framework-agnostic widget",
|
|
100
|
+
},
|
|
101
|
+
Reference: {
|
|
102
|
+
slug: "pinecall-reference",
|
|
103
|
+
blurb: "Reference tables — CLI commands, STT/TTS/LLM providers, events, session limits, REST API.",
|
|
104
|
+
keywords: "cli, commands, stt providers, tts providers, llm providers, events, session limits, rest api, reference",
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const slugify = (s) =>
|
|
109
|
+
"pinecall-" +
|
|
110
|
+
s.toLowerCase().replace(/@pinecall\/?/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
111
|
+
|
|
112
|
+
// Minimal frontmatter reader (title + description), no deps.
|
|
113
|
+
function frontmatter(md) {
|
|
114
|
+
const m = md.match(/^---\n([\s\S]*?)\n---/);
|
|
115
|
+
const fm = {};
|
|
116
|
+
if (m) {
|
|
117
|
+
for (const line of m[1].split("\n")) {
|
|
118
|
+
const kv = line.match(/^(\w+):\s*"?(.*?)"?\s*$/);
|
|
119
|
+
if (kv) fm[kv[1]] = kv[2];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return fm;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function loadPage(slug) {
|
|
126
|
+
const file = join(DOCS_DIR, slug.endsWith(".md") ? slug : slug + ".md");
|
|
127
|
+
if (!existsSync(file)) return null;
|
|
128
|
+
const md = readFileSync(file, "utf8");
|
|
129
|
+
const fm = frontmatter(md);
|
|
130
|
+
return {
|
|
131
|
+
slug,
|
|
132
|
+
file,
|
|
133
|
+
md,
|
|
134
|
+
title: fm.title || slug.split("/").pop(),
|
|
135
|
+
description: fm.description || "",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// --- main
|
|
140
|
+
const docsJson = JSON.parse(readFileSync(join(DOCS_DIR, "..", "docs.json"), "utf8"));
|
|
141
|
+
const groups = docsJson.navigation.groups;
|
|
142
|
+
|
|
143
|
+
if (existsSync(OUT_DIR)) rmSync(OUT_DIR, { recursive: true });
|
|
144
|
+
mkdirSync(OUT_DIR, { recursive: true });
|
|
145
|
+
|
|
146
|
+
const built = [];
|
|
147
|
+
for (const group of groups) {
|
|
148
|
+
const meta = GROUP_MAP[group.group] || { slug: slugify(group.group), blurb: group.group, keywords: "" };
|
|
149
|
+
const skillDir = join(OUT_DIR, meta.slug);
|
|
150
|
+
mkdirSync(join(skillDir, "references"), { recursive: true });
|
|
151
|
+
|
|
152
|
+
const pages = group.pages.map(loadPage).filter(Boolean);
|
|
153
|
+
|
|
154
|
+
// Copy each page into references/, build the index rows.
|
|
155
|
+
const rows = [];
|
|
156
|
+
for (const p of pages) {
|
|
157
|
+
const refRel = join("references", p.slug + ".md");
|
|
158
|
+
const refAbs = join(skillDir, refRel);
|
|
159
|
+
mkdirSync(dirname(refAbs), { recursive: true });
|
|
160
|
+
writeFileSync(refAbs, p.md);
|
|
161
|
+
rows.push(
|
|
162
|
+
`| **${p.title}** | ${p.description || "—"} | [\`${refRel}\`](${refRel}) · [docs](https://docs.pinecall.io/${p.slug}) |`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const isVoice = /quickstart|guides|examples|sdk-api/.test(meta.slug);
|
|
167
|
+
const description =
|
|
168
|
+
`${meta.blurb} Use when the user is building, configuring, or debugging with @pinecall/sdk. ` +
|
|
169
|
+
`Keywords: ${meta.keywords}.`;
|
|
170
|
+
|
|
171
|
+
const body = `---
|
|
172
|
+
name: ${meta.slug}
|
|
173
|
+
description: >-
|
|
174
|
+
${description.replace(/\n/g, " ")}
|
|
175
|
+
license: MIT
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
# ${group.group}
|
|
179
|
+
|
|
180
|
+
${meta.blurb}
|
|
181
|
+
|
|
182
|
+
This skill bundles the official Pinecall documentation for **${group.group}**. The
|
|
183
|
+
table below indexes every page; open the \`references/…\` file for the full text
|
|
184
|
+
(loaded on demand). Source of truth: <https://docs.pinecall.io>.
|
|
185
|
+
|
|
186
|
+
| Page | What it covers | Open |
|
|
187
|
+
|------|----------------|------|
|
|
188
|
+
${rows.join("\n")}
|
|
189
|
+
|
|
190
|
+
${isVoice ? "## Canonical agent\n\n" + CANONICAL_EXAMPLE + "\n" : ""}
|
|
191
|
+
${HOUSE_RULES}
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
*Generated from \`sdk/docs/\` by \`@pinecall/skills\` — do not edit by hand; edit the
|
|
195
|
+
docs and re-run \`node build.mjs\`.*
|
|
196
|
+
`;
|
|
197
|
+
|
|
198
|
+
writeFileSync(join(skillDir, "SKILL.md"), body);
|
|
199
|
+
built.push({ slug: meta.slug, group: group.group, pages: pages.length });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// eslint-disable-next-line no-console
|
|
203
|
+
console.log(`Built ${built.length} skills from ${DOCS_DIR}:`);
|
|
204
|
+
for (const b of built) console.log(` ${b.slug.padEnd(26)} ${String(b.pages).padStart(2)} pages (${b.group})`);
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pinecall/skills",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Agent Skills for the Pinecall SDK — installable into Claude Code, Antigravity, Cursor, Copilot and any agent that supports the open Skills format.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://docs.pinecall.io",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/pinecall/skills"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"pinecall",
|
|
14
|
+
"agent-skills",
|
|
15
|
+
"skills",
|
|
16
|
+
"claude-code",
|
|
17
|
+
"antigravity",
|
|
18
|
+
"voice-ai",
|
|
19
|
+
"sdk"
|
|
20
|
+
],
|
|
21
|
+
"files": [
|
|
22
|
+
"skills",
|
|
23
|
+
"build.mjs",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "node build.mjs"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pinecall-concepts
|
|
3
|
+
description: >-
|
|
4
|
+
The mental model — Pinecall, Agent, Channel, Call; server- vs client-side LLM; hot reload; deployment topologies. Use when the user is building, configuring, or debugging with @pinecall/sdk. Keywords: agents and channels, server vs client llm, hot reload, deployment, mental model, architecture.
|
|
5
|
+
license: MIT
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Concepts
|
|
9
|
+
|
|
10
|
+
The mental model — Pinecall, Agent, Channel, Call; server- vs client-side LLM; hot reload; deployment topologies.
|
|
11
|
+
|
|
12
|
+
This skill bundles the official Pinecall documentation for **Concepts**. The
|
|
13
|
+
table below indexes every page; open the `references/…` file for the full text
|
|
14
|
+
(loaded on demand). Source of truth: <https://docs.pinecall.io>.
|
|
15
|
+
|
|
16
|
+
| Page | What it covers | Open |
|
|
17
|
+
|------|----------------|------|
|
|
18
|
+
| **Philosophy** | Why Pinecall is code-first and what that means for your architecture. | [`references/concepts/philosophy.md`](references/concepts/philosophy.md) · [docs](https://docs.pinecall.io/concepts/philosophy) |
|
|
19
|
+
| **Agents and Channels** | The mental model: how Pinecall, Agent, Channel, and Call fit together. | [`references/concepts/agents-and-channels.md`](references/concepts/agents-and-channels.md) · [docs](https://docs.pinecall.io/concepts/agents-and-channels) |
|
|
20
|
+
| **Server-side vs Client-side LLM** | The single most important architectural decision when building a Pinecall agent. | [`references/concepts/server-vs-client-llm.md`](references/concepts/server-vs-client-llm.md) · [docs](https://docs.pinecall.io/concepts/server-vs-client-llm) |
|
|
21
|
+
| **Hot-Reload** | Change voice, language, prompt, tools — even during an active call. | [`references/concepts/hot-reload.md`](references/concepts/hot-reload.md) · [docs](https://docs.pinecall.io/concepts/hot-reload) |
|
|
22
|
+
| **Deployment Topologies** | Embedded, standalone, or headless — pick the topology that fits your architecture. | [`references/concepts/deployment-topologies.md`](references/concepts/deployment-topologies.md) · [docs](https://docs.pinecall.io/concepts/deployment-topologies) |
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## House rules — always apply
|
|
26
|
+
|
|
27
|
+
- **Example defaults** (use these exact strings unless the user asks otherwise):
|
|
28
|
+
`stt: "deepgram/flux"`, `llm: "openai/gpt-5-chat-latest"`, `voice: "elevenlabs/sarah"`.
|
|
29
|
+
**NEVER use `deepgram/nova-2`** — it is not supported. Use `deepgram/nova-3`
|
|
30
|
+
only for languages Flux doesn't support (e.g. Arabic).
|
|
31
|
+
- **Turn detection & VAD are auto-derived from the STT provider — never set
|
|
32
|
+
`turnDetection` or `vad` manually.** Flux → native turns + native VAD;
|
|
33
|
+
every other STT → `smart_turn` + `silero`.
|
|
34
|
+
- **Greeting**: inbound → `greeting` field in `pc.agent()`; outbound → `greeting`
|
|
35
|
+
field in `agent.dial()`. It is sugar for `call.say()` in `call.started`.
|
|
36
|
+
- **Auth**: `new Pinecall()` reads `PINECALL_API_KEY` from env and auto-connects.
|
|
37
|
+
- Full documentation: <https://docs.pinecall.io>
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
*Generated from `sdk/docs/` by `@pinecall/skills` — do not edit by hand; edit the
|
|
41
|
+
docs and re-run `node build.mjs`.*
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Agents and Channels"
|
|
3
|
+
description: "The mental model: how Pinecall, Agent, Channel, and Call fit together."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Agents and Channels
|
|
7
|
+
|
|
8
|
+
The Pinecall SDK has four nouns. Understanding them is most of understanding the SDK.
|
|
9
|
+
|
|
10
|
+
## The four nouns
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
### `Pinecall` — the client
|
|
15
|
+
|
|
16
|
+
One per process. Owns the WebSocket connection to `voice.pinecall.io`, handles auth and reconnection, and multiplexes events across multiple agents. **Auto-connects on construction.**
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
const pc = new Pinecall(); // reads PINECALL_API_KEY from env, connects automatically
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### `Agent` — a personality
|
|
23
|
+
|
|
24
|
+
A configured assistant. Has a name (the agent ID), a voice, an STT provider, an LLM config, and a list of tools. Listens for events; owns channels.
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
const agent = pc.agent("support", {
|
|
28
|
+
voice: "elevenlabs/sarah",
|
|
29
|
+
language: "en",
|
|
30
|
+
llm: "openai/gpt-5-chat-latest",
|
|
31
|
+
stt: "deepgram/flux",
|
|
32
|
+
prompt: "...",
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
You can have many agents on the same `Pinecall` instance — `support`, `sales`, `intake` — each with their own personality and channels.
|
|
37
|
+
|
|
38
|
+
### `Channel` — a way to reach the agent
|
|
39
|
+
|
|
40
|
+
A surface through which calls arrive. Some channels need explicit registration; others work automatically:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// Phone number — declared in config
|
|
44
|
+
const agent = pc.agent("support", {
|
|
45
|
+
phoneNumber: "+13186330963",
|
|
46
|
+
whatsapp: [{ phoneNumberId: "123", accessToken: "..." }],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Or imperatively:
|
|
50
|
+
agent.addPhoneNumber("+13186330963");
|
|
51
|
+
agent.addWhatsapp({ phoneNumberId: "123", accessToken: "..." });
|
|
52
|
+
|
|
53
|
+
// WebRTC + Chat: work via tokens, no registration needed
|
|
54
|
+
const token = await agent.createToken("webrtc");
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Channel types:
|
|
58
|
+
|
|
59
|
+
| Type | Registration | How users connect |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `phone` | `phoneNumber: "+1..."` | Call the number |
|
|
62
|
+
| `whatsapp` | `whatsapp: [{...}]` | Send a WhatsApp message |
|
|
63
|
+
| `webrtc` | **None** (automatic) | Browser widget + token |
|
|
64
|
+
| `chat` | **None** (automatic) | WebSocket + token |
|
|
65
|
+
|
|
66
|
+
### `Call` — a live session
|
|
67
|
+
|
|
68
|
+
Created automatically when someone connects on a channel. You receive a `Call` object in the `call.started` event. Use it to:
|
|
69
|
+
|
|
70
|
+
- Speak (`call.say`, `call.reply`, `call.replyStream`)
|
|
71
|
+
- Control the call (`call.hangup`, `call.forward`, `call.hold`)
|
|
72
|
+
- Update mid-call (`call.update`, `call.setPrompt`, `call.addContext`)
|
|
73
|
+
- Read state (`call.transcript`, `call.from`, `call.duration`)
|
|
74
|
+
|
|
75
|
+
## Creating an agent
|
|
76
|
+
|
|
77
|
+
### With `phoneNumber` (declarative)
|
|
78
|
+
|
|
79
|
+
Pass a phone number directly in the config:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const mara = pc.agent("mara", {
|
|
83
|
+
voice: "elevenlabs/sarah",
|
|
84
|
+
language: "es",
|
|
85
|
+
llm: "openai/gpt-5-chat-latest",
|
|
86
|
+
stt: "deepgram/flux",
|
|
87
|
+
prompt: "You are Mara. Be concise.",
|
|
88
|
+
phoneNumber: "+13186330963",
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
WebRTC and Chat work automatically — no declaration needed. Just create tokens.
|
|
93
|
+
|
|
94
|
+
### With `agent.addPhoneNumber()` (imperative)
|
|
95
|
+
|
|
96
|
+
Use `agent.addPhoneNumber()` when you need per-number config overrides:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const mara = pc.agent("mara", {
|
|
100
|
+
voice: "elevenlabs/sarah",
|
|
101
|
+
language: "es",
|
|
102
|
+
llm: "openai/gpt-5-chat-latest",
|
|
103
|
+
stt: "deepgram/flux",
|
|
104
|
+
prompt: "You are Mara. Be concise.",
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
mara.addPhoneNumber("+13186330963", {
|
|
108
|
+
voice: "elevenlabs/daniel",
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Per-number config overrides
|
|
113
|
+
|
|
114
|
+
The agent has defaults. Each phone number can override voice, language, and STT. This is how you give the same agent different settings per number:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const agent = pc.agent("support", {
|
|
118
|
+
llm: "openai/gpt-5-chat-latest",
|
|
119
|
+
stt: "deepgram/flux",
|
|
120
|
+
voice: "elevenlabs/sarah",
|
|
121
|
+
phoneNumber: { number: "+34911234567", voice: "elevenlabs/valentina", language: "es" },
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
For multiple numbers with different overrides — including STT provider — use `phoneNumbers`:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
const agent = pc.agent("global-support", {
|
|
129
|
+
prompt: "You are a multilingual support agent.",
|
|
130
|
+
llm: "openai/gpt-5-chat-latest",
|
|
131
|
+
phoneNumbers: [
|
|
132
|
+
{ number: "+14155551234", language: "en", voice: "elevenlabs/sarah", stt: "deepgram/flux" },
|
|
133
|
+
{ number: "+34612345678", language: "es", voice: "elevenlabs/valentina", stt: "deepgram/flux" },
|
|
134
|
+
// Arabic requires Nova-3 (Flux doesn't support it)
|
|
135
|
+
{ number: "+972501234567", language: "ar", voice: "elevenlabs/ahmad", stt: "deepgram/nova-3" },
|
|
136
|
+
],
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The agent's prompt, tools, and LLM stay the same — only the audio surface changes per number. Turn detection and VAD are auto-derived from the STT provider (Flux → native, Nova-3 → smart_turn + silero).
|
|
141
|
+
|
|
142
|
+
## Why this design
|
|
143
|
+
|
|
144
|
+
The agent-and-channels split exists because voice agents have two completely different concerns:
|
|
145
|
+
|
|
146
|
+
1. **Who the agent is** — personality, knowledge, tools, business logic
|
|
147
|
+
2. **How users reach it** — a phone number, a SIP trunk, a browser widget, a WhatsApp chat
|
|
148
|
+
|
|
149
|
+
Most platforms conflate the two: you build a "Twilio bot" or a "WhatsApp bot." Pinecall keeps them separate so you can build the agent once and expose it through whatever channel you need today (or tomorrow).
|
|
150
|
+
|
|
151
|
+
## What's next
|
|
152
|
+
|
|
153
|
+
- [Server-side vs client-side LLM](/concepts/server-vs-client-llm) — the most important architectural decision
|
|
154
|
+
- [Hot-reload](/concepts/hot-reload) — change voice, language, prompt, or tools mid-call
|
|
155
|
+
- [Deployment topologies](/concepts/deployment-topologies) — embedded, standalone, or headless
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Deployment Topologies"
|
|
3
|
+
description: "Embedded, standalone, or headless — pick the topology that fits your architecture."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deployment Topologies
|
|
7
|
+
|
|
8
|
+
Pinecall agents are just Node.js processes. Where you run them is your choice. There are three common topologies — each is valid, each has tradeoffs.
|
|
9
|
+
|
|
10
|
+
## The fundamental split
|
|
11
|
+
|
|
12
|
+
Before topology, understand the two communication patterns:
|
|
13
|
+
|
|
14
|
+
**1. Backend channels** — phone, SIP, WhatsApp. These talk to your Node.js process via the SDK's WebSocket. Your code receives events through an in-process EventEmitter.
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
**2. Browser channels** — WebRTC and chat. The browser connects **directly** to `voice.pinecall.io`. Your backend's only job is minting short-lived tokens.
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
This split is why some topologies support SSE event streaming and others don't — SSE requires the agent to be in the same process as your web server.
|
|
23
|
+
|
|
24
|
+
## Topology 1: Embedded
|
|
25
|
+
|
|
26
|
+
Agent runs inside your existing web app (Express, Next.js, Hono, Remix). The web server and the agent share a Node.js process.
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
**Pros:**
|
|
31
|
+
- SSE streaming works (you can build live dashboards)
|
|
32
|
+
- One deployment unit — easy ops
|
|
33
|
+
- Token endpoint is one route away from the agent
|
|
34
|
+
|
|
35
|
+
**Cons:**
|
|
36
|
+
- The agent process restarts every time you deploy the web app
|
|
37
|
+
- Web traffic and voice traffic share resources
|
|
38
|
+
|
|
39
|
+
**When to use:** small apps, dashboards that need live call event streaming, single-team projects.
|
|
40
|
+
|
|
41
|
+
## Topology 2: Standalone
|
|
42
|
+
|
|
43
|
+
Agent runs as a separate process from your web app. The web app handles HTTP, the agent process handles voice.
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
**Pros:**
|
|
48
|
+
- Independent deploys — restart the agent without touching the web app
|
|
49
|
+
- Independent scaling — give the agent its own resources
|
|
50
|
+
- Crash isolation — a web bug doesn't kill calls in flight
|
|
51
|
+
|
|
52
|
+
**Cons:**
|
|
53
|
+
- No SSE — the web app can't stream events from the agent process directly. If you need live dashboards, the agent has to expose its own SSE endpoint or push to a shared bus (Redis, NATS).
|
|
54
|
+
- Two deployments to manage
|
|
55
|
+
|
|
56
|
+
**When to use:** higher-traffic apps, when ops cares about independent scaling, when you want to avoid the "web deploy kills in-flight calls" problem.
|
|
57
|
+
|
|
58
|
+
## Topology 3: Headless
|
|
59
|
+
|
|
60
|
+
No web server at all. Just the agent. Use this when you only need phone/SIP/WhatsApp — no browser channels, no dashboards, no tokens to mint.
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
// agent/index.js — a complete production agent, no web server needed
|
|
64
|
+
import { Pinecall } from "@pinecall/sdk";
|
|
65
|
+
|
|
66
|
+
const pc = new Pinecall();
|
|
67
|
+
|
|
68
|
+
export const agent = pc.agent("support", {
|
|
69
|
+
prompt: "You are a support agent for an online store...",
|
|
70
|
+
llm: "openai/gpt-5-chat-latest",
|
|
71
|
+
voice: "elevenlabs/sarah",
|
|
72
|
+
stt: "deepgram/flux",
|
|
73
|
+
language: "en",
|
|
74
|
+
phoneNumber: "+13186330963",
|
|
75
|
+
greeting: "Hi! How can I help?",
|
|
76
|
+
tools: [lookupOrder, processReturn],
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Run it with `pinecall run agent/index.js` for a polished boot banner and live transcript.
|
|
81
|
+
|
|
82
|
+
**Pros:**
|
|
83
|
+
- Lowest possible complexity
|
|
84
|
+
- No HTTP surface to attack or maintain
|
|
85
|
+
- Easy to ship as a container, a systemd unit, or a serverless function
|
|
86
|
+
|
|
87
|
+
**Cons:**
|
|
88
|
+
- No browser channels (no WebRTC, no chat) unless someone else mints tokens
|
|
89
|
+
- No SSE
|
|
90
|
+
- No dashboards from this process
|
|
91
|
+
|
|
92
|
+
**When to use:** IoT devices, intercoms, single-purpose phone bots, WhatsApp-only bots, scheduled outbound campaigns.
|
|
93
|
+
|
|
94
|
+
## Comparison
|
|
95
|
+
|
|
96
|
+
| Feature | Embedded | Standalone | Headless |
|
|
97
|
+
|---|---|---|---|
|
|
98
|
+
| SSE (`agent.stream()`) | ✅ | ❌ | ❌ |
|
|
99
|
+
| WebRTC / Chat | ✅ | ✅ (token from web app) | ❌ (or you build it) |
|
|
100
|
+
| Phone / SIP | ✅ | ✅ | ✅ |
|
|
101
|
+
| WhatsApp | ✅ | ✅ | ✅ |
|
|
102
|
+
| Outbound calls | ✅ | ✅ | ✅ |
|
|
103
|
+
| Operational complexity | Medium | Medium | **Lowest** |
|
|
104
|
+
| Independent scaling | ❌ | ✅ | ✅ |
|
|
105
|
+
| Crash isolation | ❌ | ✅ | n/a |
|
|
106
|
+
|
|
107
|
+
## Which one should you pick?
|
|
108
|
+
|
|
109
|
+
- **Just starting out** — embedded. Get something running, split later if you need to.
|
|
110
|
+
- **You need browser channels and a dashboard** — embedded.
|
|
111
|
+
- **You're scaling and ops cares** — standalone.
|
|
112
|
+
- **You're shipping a fixed-purpose device or WhatsApp-only bot** — headless.
|
|
113
|
+
|
|
114
|
+
Migration between topologies is cheap. The agent code is the same in all three. You're just choosing where to run it.
|
|
115
|
+
|
|
116
|
+
## What's next
|
|
117
|
+
|
|
118
|
+
- [Multi-tenant dashboards](/guides/multi-tenant) — embed multiple agents, scope events per user
|
|
119
|
+
- [Dev mode](/guides/dev-mode) — run prod and dev agents on the same phone number
|
|
120
|
+
- [SSE streaming reference](/reference/events) — for embedded dashboards
|