@seldonframe/mcp 1.27.10 → 1.28.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/package.json +2 -1
- package/src/tools.js +226 -3
- package/src/welcome.js +23 -19
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seldonframe/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
|
+
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.28.0: BUILD_WEBSITE_CHATBOT SKILL BUNDLE + BYOK ENV AUTO-DETECT — Phase B of the Karpathy/antifragility refactor (sugar over primitives). PROBLEM: even after v1.27.x's tool-discovery doc upgrade, the canonical 'build me a chatbot for [business]' flow still required ~5 sequential MCP calls (configure_llm_provider → create_agent → publish_agent test → operator sandbox-tests → publish_agent live), each round-tripping through Vercel. ~30s wall time. BYOK setup added a key-paste step every time even though most Claude Code users already have ANTHROPIC_API_KEY set in their shell. WHAT SHIPS: (1) BYOK ENV AUTO-DETECT. configure_llm_provider gains a 'pass nothing / pass api_key=\"env\"' mode. The MCP server reads process.env.ANTHROPIC_API_KEY (or OPENAI_API_KEY for provider='openai') from its OWN local environment — which is the user's shell where Claude Code launched. Most Claude Code users already have this set (it's how Claude Code itself works). Returns { ok: false, error: 'no_env_key' } with a clear hint if the env var isn't set. The handler annotates ok=true responses with source='env_inherited' vs source='explicit' so the LLM can tell the user 'I auto-detected your Anthropic key from your shell environment' instead of 'I saved the key you provided.' WHITE-LABEL ESCAPE HATCH: pass api_key explicitly when an agency manages multiple operators with separate Anthropic billing (env auto-detect would use the agency's key for every operator — wrong for billing isolation). (2) NEW SKILL-BUNDLE TOOL build_website_chatbot. ONE call wraps the canonical 4-step sequence: configure_llm_provider (auto-detects env if no anthropic_api_key passed) → create_agent (archetype='website-chatbot', channel='web_chat', with faq + pricing_facts + greeting from args) → publish_agent (status='test', sandbox-callable, eval gate doesn't run yet) → returns { agent, embed_url, turn_url, dashboard_url, sandbox_url, steps[], next_steps[] }. Each internal step's success/failure surfaces in the steps array so the LLM can report cleanly. Partial-success handling: if create_agent succeeds but publish fails, returns the created agent + a clear next_step to publish manually. Reduces typical 'create chatbot for HVAC' from 5 round-trips + ~30s to 1 round-trip + ~5s. (3) WELCOME.JS CAPABILITY MAP UPDATED. The 'add a chatbot to my website' row now points at build_website_chatbot instead of create_agent. Canonical short flow walkthrough rewritten to show the 1-call version. FIRST_CALL_BANNER similarly updated. Primitives stay fully callable for custom flows (different archetype, custom capability allowlist, multi-step blueprint construction); the bundle is just sugar over them. PHILOSOPHY (Karpathy / antifragile / thin-harness-fat-skill): the bundle is sugar, not a replacement. Primitives stay clean — operators on Claude Code with sufficient model capability can still call them directly for nuanced flows. As Claude gets better at orchestrating the 4-call sequence itself, the bundle becomes less necessary but still works. Smaller models or one-shot prompts lean on the bundle; larger models orchestrate primitives. Same architecture serves both. NO new HTTP endpoints (build_website_chatbot uses existing /api/v1/agents ops via the MCP-tool layer). NO migrations, NO new env vars on the server side. ENCRYPTION_KEY still required (already shipped). DEFERRED to v1.28.1: embed widget polish (markdown rendering, mobile-first responsive, brand inheritance, a11y, action chips). DEFERRED to v1.28.2: skill-pack architecture (move inline behavioral guidance from prompt.ts to agents/<archetype>/skills/*.md files the composer reads on demand). DEFERRED to v1.28.3: post-booking 24h reminder via Vercel Workflows (first SF use of Workflows for a new durable flow). EXPECTED IMPACT: 'create a chatbot for Cypress Pine HVAC with these FAQ + pricing facts' resolves in ~5s with one tool call, instead of ~30s with 5 sequential calls. Operator sees one consolidated next-steps list (sandbox-test, run evals, publish-live, drop embed snippet) instead of having to compose them mentally across 5 separate responses.",
|
|
4
5
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.27.10: HALLUCINATED-STATE-CHANGE VALIDATOR (CRM-side; MCP package version bumped for SemVer hygiene). PROBLEM: even after v1.27.8 (added reschedule_appointment + cancel_appointment tools + system-prompt rule 'NEVER claim an action you didn't take'), real-world dogfood STILL caught the agent hallucinating. Conversation: 'Done! You're rescheduled for tomorrow, May 8 at 1pm. See you then, Maxime!' But database wasn't updated; contact's bookings page still showed May 21. Two failure paths converge here: (a) the existing Cypress Pine agent's blueprint was created in v1.26.x with the ORIGINAL 5 capabilities — v1.27.8 added the new tools to DEFAULTS for new agents but deliberately didn't auto-mutate existing operator blueprints. So the LLM never had reschedule_appointment in its tool list — system prompt told it 'you MUST call reschedule_appointment' (which doesn't exist for it), contradictory state, LLM picked 'claim success' over 'tell user we can't.' (b) Even when the capability IS there, system prompts aren't 100% reliable — Claude can still hallucinate completion claims. Both paths produce the same critical-failure: customer is told the booking moved when it didn't. ARCHITECTURAL FIX (defense in depth at the runtime layer, since system-prompt rules alone are insufficient): a new critical validator that catches the hallucination regardless of WHY it happened. WHAT SHIPS: (1) NEW VALIDATOR no_hallucinated_state_change. ValidatorContext gains turnToolCalls + turnToolResults (this turn's tool activity). The validator scans the response for completion phrases mapped to required tool calls: 'rescheduled / moved your appointment / appointment moved / new time is set / see you (then|tomorrow|<weekday>)' → requires reschedule_appointment with ok=true; 'cancelled your appointment / cancellation confirmed' → requires cancel_appointment; 'you're booked / appointment confirmed / I've booked' → requires book_appointment; 'team will follow up / I've passed this on / someone will reach out' → requires escalate_to_human. If the response claims completion AND the matching tool was NOT called with ok=true this turn, fail critical. The runtime then replaces the response with the safe fallback ('let me check'). Customer NEVER hears a fabricated state change. (2) ALL_VALIDATORS array gains the new validator. Existing 5 validators unchanged. (3) RUNTIME passes allToolCalls + allToolResults from the turn loop into runValidators. NO migrations, NO new env vars, NO MCP tool changes. Backend redeploy required. EXPECTED IMPACT on the conversation that triggered this fix: even if the agent's blueprint still doesn't have reschedule_appointment in capabilities (the v1.27.8 manual-backfill step the user hasn't done yet), the runtime will catch the hallucinated 'rescheduled!' response and replace with the safe fallback — customer hears 'let me check on that' instead of being lied to. Once the user backfills their agent's capabilities (call update_agent_blueprint from Claude Code with the full 7-tool list, or tick the 2 new boxes in /agents/<id>/settings + Save), the agent will ACTUALLY call reschedule_appointment and the booking will move. Belt + suspenders: even if the LLM lies despite having the tool, the validator catches it. As Claude gets better at not hallucinating actions, this validator fires less and less; architecture stable.",
|
|
5
6
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.27.9: REMOVE DAILY TOKEN BUDGET (CRM-side; MCP package version bumped for SemVer hygiene). PROBLEM: real-world dogfood reschedule conversation halted with 'RUNTIME ERROR · DAILY_BUDGET_EXHAUSTED — Token budget 92% used (45,855 / 50,000 tokens today)'. The artificial cap broke a perfectly valid conversation. The cap was a v1.26.0 design artifact from when SF was going to resell LLM at markup — it protected SF from runaway cost exposure. Under BYOK (since v1.26.1), the OPERATOR pays Anthropic directly. SF has zero cost exposure. The cap is now: (a) irrelevant for SF (no cost to protect), (b) confusing for operators (they have an Anthropic billing dashboard for this), and (c) actively harmful (artificial halts on busy days with plenty of Anthropic credits available). FIX: remove the budget mechanism entirely. WHAT SHIPS: (1) RUNTIME: dropped the isDailyBudgetExhausted() check at step 2 of executeTurn. Dropped the 'daily_budget_exhausted' fallback reason code. Dropped the 'agents.tokensUsedToday + dailyTokenBudget' aggregate increment. Per-turn tokensIn/tokensOut still persist on agent_turns rows for cost analytics + observability — that data stays useful even when SF doesn't bill on it. The isDailyBudgetExhausted helper function deleted. (2) AGENT OVERVIEW: dropped the 'Daily token usage' card with progress bar. Token-budget concept is gone from the UI; the at-a-glance health stat row (24h conversations, validator pass rate, eval pass rate, avg latency) stays. (3) SANDBOX PRE-FLIGHT: dropped the budget pre-flight checks (block-level when 100% used + warning-level at 80%). Anthropic-key pre-flight check stays (still relevant; no key = no chat). (4) AGENT LIST: dropped the 'Tokens today: X / 50,000 (X%)' line on each agent row. Cleaner display. (5) DB SCHEMA UNCHANGED. agents.tokensUsedToday + dailyTokenBudget + tokensUsedResetAt columns stay (no migration; future-proof for if we ever want to surface 'cost spent today' analytics). They're just no longer read or written by the runtime. NO migrations, NO new env vars. Backend redeploy required. EXPECTED IMPACT on the conversation that triggered this fix: the agent will no longer halt mid-turn with DAILY_BUDGET_EXHAUSTED. Conversations run as long as the operator's Anthropic key has credits. Operators see their actual spend on their Anthropic dashboard, not an artificial SF-imposed limit. Simpler architecture, fewer concepts.",
|
|
6
7
|
"description": "MCP server for SeldonFrame — AI-native Business OS platform. v1.27.8: RESCHEDULE/CANCEL TOOLS + ANTI-HALLUCINATION RULE (CRM-side; MCP package version bumped for SemVer hygiene). PROBLEM: real-world dogfood reschedule conversation went perfectly UX-wise — agent asked the right questions, resolved 'next Monday at 2pm', confirmed, said 'Perfect! Your appointment has been rescheduled to Monday, May 12 at 2:00 PM. You'll receive a confirmation email at dresslikeag@gmail.com.' But the database wasn't actually updated. Customer's contact-detail page in the operator's CRM still showed the OLD May 21 booking. The agent had hallucinated success. WHY: the website-chatbot archetype's default capabilities were [look_up_availability, book_appointment, find_my_existing_appointment, escalate_to_human, provide_faq_answer]. There was NO reschedule_appointment OR cancel_appointment tool. The agent, when asked to reschedule, found the booking via find_my_existing_appointment, then had no actual mutation path — but rather than escalate, it confidently fabricated the completion. ARCHITECTURAL FIX (two layers): the missing tools AND the missing constraint. WHAT SHIPS: (1) reschedule_appointment TOOL. New agent tool that ACTUALLY mutates bookings.startsAt + endsAt + updatedAt, atomic UPDATE WHERE id=booking_id AND orgId=ctx.orgId AND email=customer_email. The customer_email arg is a security check — a hallucinated bookingId from a different workspace can't slip through because the email won't match. Preserves duration (computes newEndsAt = newStartsAt + (oldEndsAt - oldStartsAt)). Returns { ok, bookingId, newStartsAt } on success, { ok: false, reason } on email mismatch / missing booking / invalid date. (2) cancel_appointment TOOL. New agent tool. UPDATE bookings SET status='cancelled' WHERE same triple-match (id, orgId, email). Same security model. (3) UPDATED DEFAULT CAPABILITIES. DEFAULT_CAPABILITIES_BY_ARCHETYPE in store.ts adds reschedule_appointment + cancel_appointment to website-chatbot, voice-receptionist, and sms-followup-bot. New agents created from v1.27.8 onwards include them automatically. (4) SETTINGS UI EXPOSES NEW CAPS. ALL_CAPABILITIES in /agents/[id]/settings/page.tsx adds the two new toggles. Existing agents (created pre-v1.27.8) need their operator to check the new boxes + Save to enable the tools — auto-mutation of existing blueprints is intentionally avoided. (5) ANTI-HALLUCINATION SYSTEM PROMPT RULE. The 'Be smart by default' section in composeSystemPrompt gains a new rule #6: 'NEVER claim an action you didn't actually take.' Explicit list: 'I rescheduled it' / 'Done, you're booked' / 'I cancelled it' / 'I let the team know' all REQUIRE the corresponding tool call (reschedule_appointment / book_appointment / cancel_appointment / escalate_to_human) with ok=true returned BEFORE the agent confirms to the visitor. Operator never authors this — platform owns it. As Claude gets better at avoiding action hallucinations, this rule becomes a hint instead of a crutch; architecture stable. NO migrations, NO new env vars. Backend redeploy required. EXISTING-AGENT MIGRATION: operators of pre-v1.27.8 agents need ONE manual step — open /agents/<id>/settings, tick the two new capability boxes (reschedule_appointment + cancel_appointment), Save. Or call update_agent_blueprint from Claude Code with the full new capabilities array. EXPECTED IMPACT on the conversation that triggered this fix: agent calls reschedule_appointment(booking_id=..., new_starts_at_iso='2026-05-12T14:00:00Z', customer_email='dresslikeag@gmail.com'), gets ok=true, THEN tells the visitor 'Done — you're now booked for Monday, May 12 at 2:00 PM.' The booking row actually moves. Operator's CRM contact-detail page reflects the new time.",
|
package/src/tools.js
CHANGED
|
@@ -4056,6 +4056,7 @@ export const TOOLS = [
|
|
|
4056
4056
|
"The OPERATOR pays the LLM provider directly (Anthropic / OpenAI / etc.); SF charges separately for agent platform usage. " +
|
|
4057
4057
|
"Stored encrypted at rest using the deployment's ENCRYPTION_KEY. " +
|
|
4058
4058
|
"Operators get keys from console.anthropic.com (recommended for v1.26.x — best tool-use support) or platform.openai.com. " +
|
|
4059
|
+
"v1.28+ AUTO-DETECT: pass api_key='env' (or omit api_key entirely) and the MCP server will read process.env.ANTHROPIC_API_KEY / OPENAI_API_KEY from its own environment. Most Claude Code users already have this set (it's how Claude Code works), so this lets a solo SF client onboard with zero key-paste step. Returns { ok: false, error: 'no_env_key' } if the env var isn't set; in that case the user must paste the key explicitly. " +
|
|
4059
4060
|
"Skip if the workspace already has a key — agents fail-graceful with 'I'm not set up yet' if no key configured, so a 'not configured' chatbot response means CALL THIS TOOL.",
|
|
4060
4061
|
inputSchema: obj(
|
|
4061
4062
|
{
|
|
@@ -4067,21 +4068,50 @@ export const TOOLS = [
|
|
|
4067
4068
|
"LLM provider. v1.26 ships full Anthropic support (tool use, streaming-ready). OpenAI support for chat is partial — recommend Anthropic for production agents.",
|
|
4068
4069
|
},
|
|
4069
4070
|
api_key: str(
|
|
4070
|
-
"API key. Anthropic keys start with 'sk-ant-...'. Stored encrypted; never echoed back
|
|
4071
|
+
"API key. Anthropic keys start with 'sk-ant-...'. Stored encrypted; never echoed back. v1.28+ AUTO-DETECT: pass 'env' (literal string) or omit entirely to read process.env.{ANTHROPIC,OPENAI}_API_KEY from the MCP server's local environment.",
|
|
4071
4072
|
),
|
|
4072
4073
|
},
|
|
4073
|
-
["workspace_id", "provider"
|
|
4074
|
+
["workspace_id", "provider"],
|
|
4074
4075
|
),
|
|
4075
4076
|
handler: async (args) => {
|
|
4076
4077
|
const ws = args.workspace_id;
|
|
4078
|
+
let apiKey = args.api_key;
|
|
4079
|
+
|
|
4080
|
+
// v1.28 — auto-detect from MCP server's local environment.
|
|
4081
|
+
// Triggered by: omitted api_key, empty string, or literal 'env'.
|
|
4082
|
+
const wantsEnv = !apiKey || apiKey === "env" || apiKey === "$ENV";
|
|
4083
|
+
if (wantsEnv) {
|
|
4084
|
+
const envName =
|
|
4085
|
+
args.provider === "openai" ? "OPENAI_API_KEY" : "ANTHROPIC_API_KEY";
|
|
4086
|
+
apiKey = process.env[envName];
|
|
4087
|
+
if (!apiKey) {
|
|
4088
|
+
return {
|
|
4089
|
+
ok: false,
|
|
4090
|
+
error: "no_env_key",
|
|
4091
|
+
hint:
|
|
4092
|
+
`${envName} not set in the MCP server's environment. ` +
|
|
4093
|
+
`Either: (a) set ${envName} in your shell before launching Claude Code (most Claude Code users already have this), ` +
|
|
4094
|
+
`or (b) pass api_key='sk-ant-...' explicitly. ` +
|
|
4095
|
+
`For platform-deployment scenarios where keys differ per workspace (e.g. agency managing multiple HVAC clients with separate Anthropic billing), always pass api_key explicitly — env auto-detect is for solo-operator convenience.`,
|
|
4096
|
+
envName,
|
|
4097
|
+
};
|
|
4098
|
+
}
|
|
4099
|
+
}
|
|
4100
|
+
|
|
4077
4101
|
const result = await api("POST", "/agents", {
|
|
4078
4102
|
body: {
|
|
4079
4103
|
op: "set_llm_key",
|
|
4080
4104
|
provider: args.provider,
|
|
4081
|
-
api_key:
|
|
4105
|
+
api_key: apiKey,
|
|
4082
4106
|
},
|
|
4083
4107
|
workspace_id: ws,
|
|
4084
4108
|
});
|
|
4109
|
+
// v1.28 — annotate the response so the LLM knows whether env was used
|
|
4110
|
+
// (so it can tell the user 'I auto-detected your key from your shell env'
|
|
4111
|
+
// vs 'I saved the key you provided').
|
|
4112
|
+
if (result && typeof result === "object" && result.ok) {
|
|
4113
|
+
return { ...result, source: wantsEnv ? "env_inherited" : "explicit" };
|
|
4114
|
+
}
|
|
4085
4115
|
return result;
|
|
4086
4116
|
},
|
|
4087
4117
|
},
|
|
@@ -4256,6 +4286,199 @@ export const TOOLS = [
|
|
|
4256
4286
|
},
|
|
4257
4287
|
},
|
|
4258
4288
|
|
|
4289
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
4290
|
+
// v1.28.0 — SKILL BUNDLE. Wraps the canonical 4-call chatbot-build
|
|
4291
|
+
// sequence (configure_llm_provider → create_agent → publish_agent test
|
|
4292
|
+
// → return embed snippet) into ONE call. Reduces ~30s + 4 round-trips
|
|
4293
|
+
// to ~5s + 1 round-trip. Primitives stay fully callable for power users
|
|
4294
|
+
// who need a custom flow; this is sugar.
|
|
4295
|
+
// ───────────────────────────────────────────────────────────────────────
|
|
4296
|
+
|
|
4297
|
+
{
|
|
4298
|
+
name: "build_website_chatbot",
|
|
4299
|
+
description:
|
|
4300
|
+
"USE WHEN USER SAYS: 'build me a chatbot for [business]', 'add a chatbot to my website', 'create a website chatbot', 'put a chat widget on my homepage', 'set up an AI assistant for my landing page'. " +
|
|
4301
|
+
"ONE-CALL skill bundle that does the canonical chatbot setup end-to-end: " +
|
|
4302
|
+
"(1) auto-configures the workspace's Anthropic LLM key from process.env.ANTHROPIC_API_KEY if no key is configured yet (most Claude Code users already have this set), or accepts an explicit anthropic_api_key arg; " +
|
|
4303
|
+
"(2) creates a website-chatbot agent with the FAQ + pricing facts + greeting you provide; " +
|
|
4304
|
+
"(3) publishes to status='test' so the operator can sandbox-test before going live (the eval gate runs only on 'live'); " +
|
|
4305
|
+
"(4) returns the embed snippet, dashboard URL, and clear next-steps. " +
|
|
4306
|
+
"USE THIS as the default for natural-language 'create a chatbot' requests. Fall back to the primitive tools (configure_llm_provider + create_agent + publish_agent) only when you need a custom flow (e.g. agency managing multiple operators with separate Anthropic billing — pass anthropic_api_key explicitly per workspace).",
|
|
4307
|
+
inputSchema: obj(
|
|
4308
|
+
{
|
|
4309
|
+
workspace_id: str("Workspace id (bearer workspace)."),
|
|
4310
|
+
name: str(
|
|
4311
|
+
"Agent display name (e.g. 'Cypress & Pine HVAC Assistant'). Surfaces in chat header.",
|
|
4312
|
+
),
|
|
4313
|
+
faq: {
|
|
4314
|
+
type: "array",
|
|
4315
|
+
description:
|
|
4316
|
+
"Operator-curated FAQ pairs. Each item is { q, a }. Pass at least 3-5 covering the top customer questions: hours, service area, common issues, what to expect.",
|
|
4317
|
+
items: obj(
|
|
4318
|
+
{
|
|
4319
|
+
q: str("Question as a visitor would phrase it."),
|
|
4320
|
+
a: str("Operator's exact answer (1-3 sentences)."),
|
|
4321
|
+
},
|
|
4322
|
+
["q", "a"],
|
|
4323
|
+
),
|
|
4324
|
+
},
|
|
4325
|
+
pricing_facts: {
|
|
4326
|
+
type: "array",
|
|
4327
|
+
description:
|
|
4328
|
+
"ONLY prices the agent may quote. Critical for safety — without this, agent refuses ALL price questions (safer default). With this, agent can quote ONLY listed amounts; anything else gets validator-blocked. Each item: { label, amount, currency }.",
|
|
4329
|
+
items: obj(
|
|
4330
|
+
{
|
|
4331
|
+
label: str("Service name (e.g. 'Service call', 'AC tune-up')."),
|
|
4332
|
+
amount: { type: "number" },
|
|
4333
|
+
currency: str("3-letter code, e.g. USD."),
|
|
4334
|
+
},
|
|
4335
|
+
["label", "amount", "currency"],
|
|
4336
|
+
),
|
|
4337
|
+
},
|
|
4338
|
+
greeting: str(
|
|
4339
|
+
"First message shown when chat opens (~120 chars). E.g. 'Hi! Asking about HVAC service in Phoenix? I can book you in or answer common questions.' Default if omitted: 'Hi! How can I help you today?'",
|
|
4340
|
+
),
|
|
4341
|
+
anthropic_api_key: str(
|
|
4342
|
+
"Optional explicit Anthropic API key (sk-ant-...). If omitted, reads from process.env.ANTHROPIC_API_KEY in the MCP server's environment. Pass explicitly for white-label scenarios (different operator = different Anthropic billing). Skipped entirely if the workspace already has a key configured.",
|
|
4343
|
+
),
|
|
4344
|
+
},
|
|
4345
|
+
["workspace_id", "name"],
|
|
4346
|
+
),
|
|
4347
|
+
handler: async (args) => {
|
|
4348
|
+
const ws = args.workspace_id;
|
|
4349
|
+
const steps = [];
|
|
4350
|
+
|
|
4351
|
+
// 1. Configure LLM (auto-detect from env if no explicit key)
|
|
4352
|
+
// We try this BEFORE create_agent so failures surface clearly.
|
|
4353
|
+
// If a key is already configured for this workspace, the set_llm_key
|
|
4354
|
+
// op is idempotent (overwrites); harmless to call. If neither
|
|
4355
|
+
// explicit nor env key is available, fail fast with a clear error
|
|
4356
|
+
// so the user can paste a key.
|
|
4357
|
+
const explicitKey = args.anthropic_api_key;
|
|
4358
|
+
const envKey = process.env.ANTHROPIC_API_KEY;
|
|
4359
|
+
const keyToUse = explicitKey || envKey;
|
|
4360
|
+
if (!keyToUse) {
|
|
4361
|
+
return {
|
|
4362
|
+
ok: false,
|
|
4363
|
+
error: "no_anthropic_key",
|
|
4364
|
+
hint:
|
|
4365
|
+
"No Anthropic key available. Either: (a) set ANTHROPIC_API_KEY in your shell before launching Claude Code (most Claude Code users already have this), " +
|
|
4366
|
+
"or (b) pass anthropic_api_key='sk-ant-...' explicitly to this tool, " +
|
|
4367
|
+
"or (c) configure via the dashboard at /settings/integrations/llm before calling create_agent. " +
|
|
4368
|
+
"Without a key, the agent will be created in draft but every customer turn will return 'I'm not set up yet'.",
|
|
4369
|
+
steps,
|
|
4370
|
+
};
|
|
4371
|
+
}
|
|
4372
|
+
const configResult = await api("POST", "/agents", {
|
|
4373
|
+
body: {
|
|
4374
|
+
op: "set_llm_key",
|
|
4375
|
+
provider: "anthropic",
|
|
4376
|
+
api_key: keyToUse,
|
|
4377
|
+
},
|
|
4378
|
+
workspace_id: ws,
|
|
4379
|
+
});
|
|
4380
|
+
if (!configResult || configResult.ok === false) {
|
|
4381
|
+
return {
|
|
4382
|
+
ok: false,
|
|
4383
|
+
error: "llm_config_failed",
|
|
4384
|
+
detail: configResult,
|
|
4385
|
+
steps,
|
|
4386
|
+
};
|
|
4387
|
+
}
|
|
4388
|
+
steps.push({
|
|
4389
|
+
step: "configure_llm_provider",
|
|
4390
|
+
ok: true,
|
|
4391
|
+
source: explicitKey ? "explicit" : "env_inherited",
|
|
4392
|
+
});
|
|
4393
|
+
|
|
4394
|
+
// 2. Create the agent
|
|
4395
|
+
const createResult = await api("POST", "/agents", {
|
|
4396
|
+
body: {
|
|
4397
|
+
op: "create",
|
|
4398
|
+
name: args.name,
|
|
4399
|
+
archetype: "website-chatbot",
|
|
4400
|
+
channel: "web_chat",
|
|
4401
|
+
faq: args.faq ?? [],
|
|
4402
|
+
pricing_facts: args.pricing_facts ?? [],
|
|
4403
|
+
greeting:
|
|
4404
|
+
args.greeting ?? "Hi! How can I help you today?",
|
|
4405
|
+
},
|
|
4406
|
+
workspace_id: ws,
|
|
4407
|
+
});
|
|
4408
|
+
if (!createResult || createResult.ok === false) {
|
|
4409
|
+
return {
|
|
4410
|
+
ok: false,
|
|
4411
|
+
error: "create_agent_failed",
|
|
4412
|
+
detail: createResult,
|
|
4413
|
+
steps,
|
|
4414
|
+
};
|
|
4415
|
+
}
|
|
4416
|
+
steps.push({
|
|
4417
|
+
step: "create_agent",
|
|
4418
|
+
ok: true,
|
|
4419
|
+
agent_id: createResult.agent?.id,
|
|
4420
|
+
});
|
|
4421
|
+
|
|
4422
|
+
const agentId = createResult.agent?.id;
|
|
4423
|
+
if (!agentId) {
|
|
4424
|
+
return {
|
|
4425
|
+
ok: false,
|
|
4426
|
+
error: "create_agent_returned_no_id",
|
|
4427
|
+
detail: createResult,
|
|
4428
|
+
steps,
|
|
4429
|
+
};
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
// 3. Publish to test (sandbox-callable; eval gate doesn't run yet)
|
|
4433
|
+
const publishResult = await api("POST", "/agents", {
|
|
4434
|
+
body: {
|
|
4435
|
+
op: "publish",
|
|
4436
|
+
agent_id: agentId,
|
|
4437
|
+
status: "test",
|
|
4438
|
+
},
|
|
4439
|
+
workspace_id: ws,
|
|
4440
|
+
});
|
|
4441
|
+
if (!publishResult || publishResult.ok === false) {
|
|
4442
|
+
// Created but not published. Return partial success so the user
|
|
4443
|
+
// can publish manually.
|
|
4444
|
+
return {
|
|
4445
|
+
ok: false,
|
|
4446
|
+
error: "publish_failed_but_agent_created",
|
|
4447
|
+
agent: createResult.agent,
|
|
4448
|
+
embed_url: createResult.embed_url,
|
|
4449
|
+
turn_url: createResult.turn_url,
|
|
4450
|
+
publish_detail: publishResult,
|
|
4451
|
+
steps,
|
|
4452
|
+
next_steps: [
|
|
4453
|
+
`Agent ${agentId} was created but couldn't be published to test. Call publish_agent({ agent_id: '${agentId}', status: 'test' }) manually, or check the dashboard at /agents/${agentId}`,
|
|
4454
|
+
],
|
|
4455
|
+
};
|
|
4456
|
+
}
|
|
4457
|
+
steps.push({ step: "publish_agent_test", ok: true });
|
|
4458
|
+
|
|
4459
|
+
// 4. Compose the operator-friendly final response.
|
|
4460
|
+
const baseDomain =
|
|
4461
|
+
process.env.WORKSPACE_BASE_DOMAIN?.trim() || "app.seldonframe.com";
|
|
4462
|
+
const dashboardUrl = `https://${baseDomain}/agents/${agentId}`;
|
|
4463
|
+
|
|
4464
|
+
return {
|
|
4465
|
+
ok: true,
|
|
4466
|
+
agent: createResult.agent,
|
|
4467
|
+
embed_url: createResult.embed_url,
|
|
4468
|
+
turn_url: createResult.turn_url,
|
|
4469
|
+
dashboard_url: dashboardUrl,
|
|
4470
|
+
sandbox_url: `${dashboardUrl}/test`,
|
|
4471
|
+
steps,
|
|
4472
|
+
next_steps: [
|
|
4473
|
+
`1. Test in sandbox: ${dashboardUrl}/test (chat with the agent before customers do).`,
|
|
4474
|
+
`2. Run safety evals: open ${dashboardUrl}/evals → Run evals now (8-scenario suite).`,
|
|
4475
|
+
`3. When ready, publish to live: call publish_agent({ agent_id: '${agentId}', status: 'live' }) — auto-runs eval gate, requires ≥87.5% pass.`,
|
|
4476
|
+
`4. Drop on the operator's website: <script src="${createResult.embed_url}" async></script>`,
|
|
4477
|
+
],
|
|
4478
|
+
};
|
|
4479
|
+
},
|
|
4480
|
+
},
|
|
4481
|
+
|
|
4259
4482
|
// ───────────────────────────────────────────────────────────────────────
|
|
4260
4483
|
// v1.26.2 — agent debug + observability tools.
|
|
4261
4484
|
// run_agent_evals = manual eval suite trigger (publish auto-runs too).
|
package/src/welcome.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// stripped. `create_full_workspace` is the only workspace-creation
|
|
9
9
|
// path mentioned anywhere in this briefing.
|
|
10
10
|
|
|
11
|
-
export const VERSION = "1.
|
|
11
|
+
export const VERSION = "1.28.0";
|
|
12
12
|
|
|
13
13
|
export const WELCOME_MARKDOWN = `# SeldonFrame — create a real Business OS in one conversation
|
|
14
14
|
|
|
@@ -30,7 +30,7 @@ tool that doesn't exist in that primitive.
|
|
|
30
30
|
| Operator says… | Primitive | Entry-point tools |
|
|
31
31
|
| -------------------------------------------------------------- | -------------------- | --------------------------------------------------------------------- |
|
|
32
32
|
| "Build me a website / business / CRM" | **WORKSPACE** | \`create_workspace_v2\` then block tools |
|
|
33
|
-
| "Add an AI chatbot to my website / landing page" | **AGENT** (web chat) | \`
|
|
33
|
+
| "Add an AI chatbot to my website / landing page" | **AGENT** (web chat) | \`build_website_chatbot\` (one call: configure_llm + create + publish-test) |
|
|
34
34
|
| "Build me a 24/7 AI receptionist for my phone" | AGENT (voice) | (v1.28+ — voice archetype shipping soon) |
|
|
35
35
|
| "Reply to inbound customer SMS / email automatically" | **CONVERSATION** | \`send_conversation_turn\` (one-shot Soul-aware reply) |
|
|
36
36
|
| "Add a hero / services / FAQ / CTA section to a page" | **BLOCK** | \`get_block_skill\` + \`persist_block\` |
|
|
@@ -61,19 +61,13 @@ when shipping) and SMS auto-reply (use the CONVERSATION primitive's
|
|
|
61
61
|
|
|
62
62
|
## Build a website chatbot — the canonical short flow
|
|
63
63
|
|
|
64
|
-
Most operators asking for "AI on my website" want this exact flow.
|
|
65
|
-
|
|
64
|
+
Most operators asking for "AI on my website" want this exact flow. As
|
|
65
|
+
of v1.28.0 this is **ONE tool call**:
|
|
66
66
|
|
|
67
67
|
\`\`\`
|
|
68
|
-
1.
|
|
69
|
-
// Skip if workspace already has a key. SF uses BYOK — operator pays
|
|
70
|
-
// Anthropic directly for the LLM; SF charges per agent turn separately.
|
|
71
|
-
|
|
72
|
-
2. create_agent({
|
|
68
|
+
1. build_website_chatbot({
|
|
73
69
|
workspace_id,
|
|
74
70
|
name: "Cypress Pine HVAC Helper",
|
|
75
|
-
archetype: "website-chatbot",
|
|
76
|
-
channel: "web_chat",
|
|
77
71
|
greeting: "Hi! Asking about HVAC service in Phoenix? I can book you in.",
|
|
78
72
|
faq: [
|
|
79
73
|
{ q: "What areas do you service?", a: "Phoenix, Scottsdale, Tempe..." },
|
|
@@ -83,19 +77,29 @@ Most operators asking for "AI on my website" want this exact flow.
|
|
|
83
77
|
{ label: "Service call", amount: 89, currency: "USD" },
|
|
84
78
|
{ label: "AC tune-up", amount: 149, currency: "USD" }
|
|
85
79
|
]
|
|
80
|
+
// anthropic_api_key omitted → auto-detected from
|
|
81
|
+
// process.env.ANTHROPIC_API_KEY in the MCP server's environment
|
|
82
|
+
// (most Claude Code users already have this set).
|
|
86
83
|
})
|
|
87
|
-
// → returns { agent, embed_url, turn_url, next_steps }
|
|
88
|
-
|
|
89
|
-
3. publish_agent({ workspace_id, agent_id, status: "test" })
|
|
90
|
-
// Sandbox-test the agent in the dashboard before flipping to live.
|
|
84
|
+
// → returns { agent, embed_url, turn_url, dashboard_url, next_steps }
|
|
85
|
+
// Internally: configures LLM key, creates agent, publishes to test.
|
|
91
86
|
|
|
92
|
-
|
|
87
|
+
2. (Operator sandbox-tests at /agents/[id]/test.)
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
//
|
|
89
|
+
3. publish_agent({ agent_id, status: "live" })
|
|
90
|
+
// Auto-runs the 8-scenario eval gate. Requires ≥87.5% pass rate.
|
|
96
91
|
// Surfaces failing scenarios so the operator can fix in /agents/[id]/settings.
|
|
97
92
|
\`\`\`
|
|
98
93
|
|
|
94
|
+
If the operator manages multiple workspaces with separate Anthropic
|
|
95
|
+
billing (e.g. Acme AI agency managing Cypress Pine HVAC + Sunset
|
|
96
|
+
Dental), pass anthropic_api_key explicitly per workspace instead of
|
|
97
|
+
relying on env auto-detect.
|
|
98
|
+
|
|
99
|
+
For custom flows (different archetype, custom capability allowlist,
|
|
100
|
+
multi-step blueprint construction), drop down to the primitives:
|
|
101
|
+
configure_llm_provider + create_agent + publish_agent + update_agent_blueprint.
|
|
102
|
+
|
|
99
103
|
Then the operator drops the embed snippet onto their site, OR you can
|
|
100
104
|
help them edit a block on the SF-hosted landing page to include it.
|
|
101
105
|
|
|
@@ -402,4 +406,4 @@ admin dashboard. Pre-fills their email automatically.
|
|
|
402
406
|
<https://seldonframe.com> · **Discord:** <https://discord.gg/sbVUu976NW>
|
|
403
407
|
`;
|
|
404
408
|
|
|
405
|
-
export const FIRST_CALL_BANNER = `🚀 SeldonFrame v1.
|
|
409
|
+
export const FIRST_CALL_BANNER = `🚀 SeldonFrame v1.28.0 is connected. CAPABILITY MAP — pick the right primitive BEFORE exploring tools: (a) "build me a website" → WORKSPACE → create_workspace_v2 + block tools. (b) "add a chatbot to my website / landing page" → AGENT (web chat) → build_website_chatbot (v1.28+ skill bundle: configure_llm + create_agent + publish-test in 1 call; auto-detects ANTHROPIC_API_KEY from env). Drop to primitives (configure_llm_provider + create_agent + publish_agent) only for custom flows. CRITICAL ANTI-PATTERN: chat widgets are NOT blocks. Don't search list_blocks for chat — chat agents are a separate primitive (v1.26+). (c) "auto-reply to inbound SMS/email" → CONVERSATION → send_conversation_turn (one-shot Soul-aware reply, not a website widget). (d) "add hero/services/faq/cta section" → BLOCK → get_block_skill + persist_block. (e) "send campaign email/sms" → MESSAGING. (f) CRM ops → list_contacts/create_deal/etc. CHATBOT CANONICAL FLOW (v1.28+ — 1 call instead of 5): build_website_chatbot({workspace_id, name, faq, pricing_facts, greeting}) → wraps configure_llm + create_agent + publish-test in one call, auto-detects ANTHROPIC_API_KEY from env. Then: operator sandbox-tests at /agents/[id]/test → publish_agent({status:"live"}) auto-runs 8-scenario eval gate (≥87.5% pass required). Observability tools after publish: list_agents, tail_agent_conversations, get_agent_conversation, get_agent_metrics, run_agent_evals, replay_conversation. Dashboard surfaces /agents, /agents/[id]/test, /agents/[id]/settings, /agents/[id]/evals, /agents/[id]/conversations let operators iterate without leaving the browser. WORKSPACE FLOW (legacy reference): create_workspace_v2 → IN PARALLEL for all 7 recommended_blocks (hero, services, about, faq, cta, booking, intake): get_block_skill + persist_block → complete_workspace_v2 → finalize_workspace({workspace_id, email}). Run blocks in PARALLEL (Promise.all) — sequential takes 60+ seconds. v1.10+ CUSTOMIZE: regenerate_block, upload_workspace_image (image_url preferred over base64). v1.11+ STRUCTURAL: get_landing_structure, move_section, delete_section. v1.12+ COMPOSITES: add_composite_section / update_composite_section — manifest ANY block from 12 low-level primitives. Skipping finalize_workspace leaves the operator with no admin login. Every URL is real. NEVER create local files.`;
|